Module: OKF::Markdown::Frontmatter

Defined in:
lib/okf/markdown/frontmatter.rb

Defined Under Namespace

Classes: ParseError

Constant Summary collapse

FRONTMATTER_PATTERN =
/\A---[ \t]*\n(.*?)\n---[ \t]*(?:\n|\z)/m.freeze
PSYCH_KEYWORDS =

Psych gained keyword arguments for safe_load in 3.1 (Ruby 2.6); older versions take the permitted classes positionally.

Gem::Version.new(Psych::VERSION) >= Gem::Version.new("3.1.0")

Class Method Summary collapse

Class Method Details

.dump(frontmatter, body) ⇒ Object



36
37
38
39
40
# File 'lib/okf/markdown/frontmatter.rb', line 36

def dump(frontmatter, body)
  attrs = stringify_keys(frontmatter || {})
  yaml = YAML.dump(attrs).sub(/\A---[ \t]*\n/, "")
  "---\n#{yaml}---\n\n#{body}"
end

.load_yaml(text) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/okf/markdown/frontmatter.rb', line 46

def load_yaml(text)
  if PSYCH_KEYWORDS
    YAML.safe_load(text, permitted_classes: [ Date, Time ], aliases: false)
  else
    YAML.safe_load(text, [ Date, Time ], [], false)
  end
end

.parse(content) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/okf/markdown/frontmatter.rb', line 20

def parse(content)
  text = content.to_s
  raise ParseError, "content is not valid UTF-8" unless text.encoding == Encoding::UTF_8 && text.valid_encoding?

  match = FRONTMATTER_PATTERN.match(text)
  raise ParseError, "missing YAML frontmatter" unless match

  data = load_yaml(match[1])
  raise ParseError, "frontmatter must be a mapping" unless data.nil? || data.is_a?(Hash)

  body = text[match.end(0)..-1] || ""
  [ stringify_keys(data || {}), body.sub(/\A\n/, "") ]
rescue Psych::SyntaxError => e
  raise ParseError, "invalid YAML frontmatter: #{e.message}"
end

.stringify_keys(hash) ⇒ Object



42
43
44
# File 'lib/okf/markdown/frontmatter.rb', line 42

def stringify_keys(hash)
  hash.to_h.map { |key, value| [ key.to_s, value ] }.to_h
end