Class: Ace::PromptPrep::Atoms::FrontmatterExtractor

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/prompt_prep/atoms/frontmatter_extractor.rb

Overview

Extract YAML frontmatter from markdown content

Constant Summary collapse

FRONTMATTER_DELIMITER =
/^---\s*$/

Class Method Summary collapse

Class Method Details

.extract(content) ⇒ Hash

Extract frontmatter and body from content

Parameters:

  • content (String)

    The content to parse

Returns:

  • (Hash)

    Hash with :frontmatter, :body, :has_frontmatter keys



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/ace/prompt_prep/atoms/frontmatter_extractor.rb', line 16

def self.extract(content)
  return empty_result(content) if content.nil? || content.empty?

  lines = content.lines
  return empty_result(content) unless lines.first&.match?(FRONTMATTER_DELIMITER)

  # Find closing delimiter
  closing_index = lines[1..].find_index { |line| line.match?(FRONTMATTER_DELIMITER) }
  return empty_result(content) unless closing_index

  # Extract frontmatter YAML (between delimiters)
  frontmatter_lines = lines[1..closing_index]
  frontmatter_yaml = frontmatter_lines.join

  # Parse YAML
  begin
    frontmatter = YAML.safe_load(frontmatter_yaml) || {}
  rescue Psych::SyntaxError, Psych::DisallowedClass => e
    # Invalid YAML - return as if no frontmatter
    return empty_result(content, error: "Invalid YAML in frontmatter: #{e.message}")
  end

  # Extract body (everything after closing delimiter)
  body_start = closing_index + 2 # +1 for array index offset, +1 for closing delimiter
  body = lines[body_start..].join

  {
    frontmatter: frontmatter,
    raw_frontmatter: frontmatter_yaml,
    body: body,
    has_frontmatter: true,
    error: nil
  }
end