Skip to content

Commit

Permalink
Expose YAML frontmatter
Browse files Browse the repository at this point in the history
  • Loading branch information
MatMoore committed May 26, 2024
1 parent 72aa05f commit 928aa85
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 12 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
## [Unreleased]

- Added support for wikilinks that embed files. These are rendered as images or links in the HTML content.
- Added method `#page.generate_html` to replace `#page.content.generate_html`, and removed the `MarkdownDocument` class. `#page.content` is now a callable that returns the markdown content.
- Added `#mark_referenced` and `#referenced?` to page objects
- Added `#prune!` method to page objects, to remove non-referenced pages
- Added method `Page#generate_html` to replace `Page#content.generate_html`, and removed the `MarkdownDocument` class. `Page#content` is now a callable that returns the markdown content.
- Added `Page#mark_referenced` and `Page#referenced?`
- Added `Page#prune!` method to page objects, to remove non-referenced pages
- Added `Page#parse` method to expose `ParsedMarkdownDocument` objects
- Added `#frontmatter` to `ParsedMarkdownDocument`

## [0.7.0] - 2023-08-03

Expand Down
9 changes: 9 additions & 0 deletions SMELLS.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Bad naming

- MarkdownParser does more than parse markdown - it takes a file from the vault and parses it into an object that can be inspected
- The document argument of ParsedMarkdownDocument is very vague

Huge classes

- Page has lots of optional arguments that should not really be optional
- Could perhaps extract out some graph behaviour to a mixin
12 changes: 10 additions & 2 deletions lib/obsidian/parser/frontmatter_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,27 @@ class Obsidian::MarkdownParser::FrontMatterParser
def parse(content)
enumerator = content.each_line
first_line = enumerator.next
complete = false

if first_line.chomp != "---"
puts "bye"
return {}
end

lines = []
loop do
line = enumerator.next
break if line.chomp == "---"
if line.chomp == "---"
complete = true
break
end
lines << line
end

YAML.safe_load(lines.join)
puts lines
puts complete

complete ? YAML.safe_load(lines.join) : {}
rescue YAML::SyntaxError, StopIteration
{}
end
Expand Down
14 changes: 12 additions & 2 deletions lib/obsidian/parser/markdown_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ class MarkdownParser
\]\]
}x

def initialize(frontmatter_parser: FrontMatterParser.new, renderer: HtmlRenderer.new)
@frontmatter_parser = frontmatter_parser
@renderer = renderer
end

# Convert Obsidian-flavored-markdown syntax to something parseable
# (i.e. with Github-flavored-markdown syntax)
def expand_wikilinks(markdown_text, root:)
Expand Down Expand Up @@ -79,11 +84,16 @@ def expand_attachments(markdown_text, root:, media_root:)
end

def parse(markdown_text, root: nil, media_root: nil)
renderer = HtmlRenderer.new
frontmatter = frontmatter_parser.parse(markdown_text)
normalized1 = expand_attachments(markdown_text, root: root, media_root: media_root)
normalized2 = expand_wikilinks(normalized1, root: root)
document = Markly.parse(normalized2, flags: Markly::SMART | Markly::UNSAFE | Markly::HARD_BREAKS, extensions: [:table, :tasklist, :autolink])
Obsidian::ParsedMarkdownDocument.new(document, renderer: renderer)
Obsidian::ParsedMarkdownDocument.new(document, renderer: renderer, frontmatter: frontmatter)
end

private

attr_reader :renderer
attr_reader :frontmatter_parser
end
end
8 changes: 6 additions & 2 deletions lib/obsidian/parser/page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,14 @@ def find_in_tree(query_slug)
nil
end

def generate_html(markdown_parser: MarkdownParser.new)
def parse(markdown_parser: MarkdownParser.new)
return nil if content.nil?

markdown_parser.parse(content.call, root: root, media_root: media_root).to_html
markdown_parser.parse(content.call, root: root, media_root: media_root)
end

def generate_html(markdown_parser: MarkdownParser.new)
parse(markdown_parser: markdown_parser).to_html
end

def referenced?
Expand Down
7 changes: 6 additions & 1 deletion lib/obsidian/parser/parsed_markdown_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

module Obsidian
class ParsedMarkdownDocument
def initialize(document, renderer:)
def initialize(document, renderer:, frontmatter: {})
@document = document
@renderer = renderer
@links = extract_links
@frontmatter = frontmatter
end

def extract_links
Expand All @@ -25,6 +27,9 @@ def to_html
renderer.render(document)
end

attr_reader :frontmatter
attr_reader :links

private

attr_reader :document
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

RSpec.describe(Obsidian::MarkdownParser::FrontMatterParser) do
subject(:parser) { described_class.new }

it "parses valid yaml" do
content = %(---
foo: 1
Expand Down
24 changes: 22 additions & 2 deletions spec/obsidian/parser/markdown_parser_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# frozen_string_literal: true

RSpec.describe Obsidian::MarkdownParser do
describe ".expand_wikilinks" do
subject(:parser) { described_class.new }

describe "#expand_wikilinks" do
let(:index) { Obsidian::Page.create_root }
subject(:parser) { described_class.new }

before do
index.add_page("foo/bar")
Expand Down Expand Up @@ -110,4 +111,23 @@
end
end
end

describe "#parse" do
it "parses frontmatter if available" do
content = %(---
foo: 1
bar: banana
---
some text
)
result = parser.parse(content)
expect(result.frontmatter).to eq("foo" => 1, "bar" => "banana")
end

it "returns empty frontmatter if not available" do
content = "some text"
result = parser.parse(content)
expect(result.frontmatter).to eq({})
end
end
end

0 comments on commit 928aa85

Please sign in to comment.