Class: Textus::Format::Yaml
Constant Summary collapse
- RAW_REQUIRED =
%w[ingested_at content_hash].freeze
- RAW_SOURCE_KINDS =
%w[url file asset].freeze
Class Method Summary collapse
- .data_to_payload(data) ⇒ Object
- .enforce_name_match!(path, meta) ⇒ Object
- .extensions ⇒ Object
- .nested_glob ⇒ Object
- .parse(raw, path: nil) ⇒ Object
-
.rewrite_name(path, basename) ⇒ Object
rubocop:disable Naming/PredicateMethod.
- .serialize(meta:, body:, content: nil) ⇒ Object
- .serialize_for_put(meta:, body:, content:, path:) ⇒ Object
- .validate_against(schema, parsed) ⇒ Object
- .validate_path_extension(path, nested) ⇒ Object
- .validate_raw_entry!(parsed, lane) ⇒ Object
Class Method Details
.data_to_payload(data) ⇒ Object
119 120 121 122 |
# File 'lib/textus/format/yaml.rb', line 119 def self.data_to_payload(data) data = data.transform_keys(&:to_s) if data.is_a?(Hash) { meta: data["_meta"] || {}, body: nil, content: data["content"] || data } end |
.enforce_name_match!(path, meta) ⇒ Object
96 97 98 99 100 101 102 103 104 |
# File 'lib/textus/format/yaml.rb', line 96 def self.enforce_name_match!(path, ) return unless .is_a?(Hash) && ["name"] ext = extensions.first basename = File.basename(path, ext) return if ["name"] == basename raise BadFrontmatter.new(path, "name '#{["name"]}' does not match basename '#{basename}'") end |
.extensions ⇒ Object
65 |
# File 'lib/textus/format/yaml.rb', line 65 def self.extensions = [".yaml", ".yml"] |
.nested_glob ⇒ Object
67 |
# File 'lib/textus/format/yaml.rb', line 67 def self.nested_glob = "**/*.{yaml,yml}" |
.parse(raw, path: nil) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/textus/format/yaml.rb', line 6 def self.parse(raw, path: nil) raw = raw.dup.force_encoding(Encoding::UTF_8) raise BadFrontmatter.new(path, "entry is not valid UTF-8") unless raw.valid_encoding? begin parsed = ::YAML.safe_load(raw, permitted_classes: [Date, Time], aliases: false) rescue Psych::SyntaxError, Psych::AliasesNotEnabled, Psych::DisallowedClass => e raise BadFrontmatter.new(path, "YAML parse failed: #{e.}") end raise BadFrontmatter.new(path, "YAML top-level must be a mapping") unless parsed.is_a?(Hash) = parsed["_meta"] fm = .is_a?(Hash) ? : {} = parsed.except("_meta") { "_meta" => fm, "body" => raw, "content" => } end |
.rewrite_name(path, basename) ⇒ Object
rubocop:disable Naming/PredicateMethod
85 86 87 88 89 90 91 92 93 94 |
# File 'lib/textus/format/yaml.rb', line 85 def self.rewrite_name(path, basename) # rubocop:disable Naming/PredicateMethod raw = File.binread(path) parsed = parse(raw, path: path) = parsed["_meta"] return false unless .is_a?(Hash) && ["name"].is_a?(String) && ["name"] != basename = .merge("name" => basename) File.binwrite(path, serialize(meta: , body: "", content: parsed["content"])) true end |
.serialize(meta:, body:, content: nil) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/textus/format/yaml.rb', line 23 def self.serialize(meta:, body:, content: nil) if content.is_a?(Hash) on_disk = && !.empty? ? { "_meta" => }.merge(content) : content ::YAML.dump(on_disk).sub(/\A---\n/, "") elsif body && !body.to_s.empty? b = body.to_s b += "\n" unless b.end_with?("\n") b else raise UsageError.new("yaml serialize requires :content or :body") end end |
.serialize_for_put(meta:, body:, content:, path:) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/textus/format/yaml.rb', line 69 def self.serialize_for_put(meta:, body:, content:, path:) raise UsageError.new("put for yaml requires content: or body:") if content.nil? && (body.nil? || body.to_s.empty?) if content.nil? begin parsed = parse(body.to_s, path: path) rescue BadFrontmatter => e raise BadContent.new(path, "bad_content: #{e.}") end [body.to_s, parsed["_meta"], body.to_s, parsed["content"]] else bytes = serialize(meta: , body: "", content: content) [bytes, , bytes, content] end end |
.validate_against(schema, parsed) ⇒ Object
36 37 38 |
# File 'lib/textus/format/yaml.rb', line 36 def self.validate_against(schema, parsed) schema.validate!(parsed["content"] || {}) end |
.validate_path_extension(path, nested) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/textus/format/yaml.rb', line 106 def self.validate_path_extension(path, nested) ext = File.extname(path) if nested return if ext == "" raise UsageError.new("nested yaml path must not have an extension") end return if [".yaml", ".yml"].include?(ext) raise UsageError.new("yaml format requires '.yaml' or '.yml' path (got #{ext.inspect})") end |
.validate_raw_entry!(parsed, lane) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/textus/format/yaml.rb', line 43 def self.validate_raw_entry!(parsed, lane) return unless lane == "raw" content = parsed["content"] || {} return if content["superseded_by"] missing = RAW_REQUIRED.reject { |f| content[f] } raise Textus::BadContent.new(nil, "raw entry missing required field(s): #{missing.join(", ")}") if missing.any? source = content["source"] || {} kind = source["kind"] unless RAW_SOURCE_KINDS.include?(kind) raise Textus::BadContent.new( nil, "raw entry source.kind must be #{RAW_SOURCE_KINDS.join("|")}, got #{kind.inspect}" ) end return unless kind == "url" && !source["url"] raise Textus::BadContent.new(nil, "raw entry with source.kind=url must have source.url") end |