Skip to content

Commit

Permalink
Switch to Markly for HTML rendering
Browse files Browse the repository at this point in the history
Unfortunately Markly does not include header generation, so for now I've
implemented this with a custom renderer.
  • Loading branch information
MatMoore committed Aug 3, 2023
1 parent d45745f commit 866c2f7
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 24 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
## [Unreleased]
- Replace Kramdown with Markly
- Enabled support for Github Flavored Markdown tables and tasklists

## [0.5.4] - 2023-08-02
- Fix page getting clobbered when wikilinks point to non-existent pages.
Expand Down
6 changes: 0 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ PATH
remote: .
specs:
obsidian-parser (0.5.4)
kramdown (~> 2.4)
kramdown-parser-gfm (~> 1.1)
markly (~> 0.7.0)

GEM
Expand All @@ -13,10 +11,6 @@ GEM
coderay (1.1.3)
diff-lcs (1.5.0)
json (2.6.3)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
language_server-protocol (3.17.0.3)
lint_roller (1.1.0)
markly (0.7.0)
Expand Down
4 changes: 3 additions & 1 deletion lib/obsidian/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require_relative "parser/obsidian_flavored_markdown"
require_relative "parser/page"
require_relative "parser/markdown_content"
require_relative "parser/html_renderer"

require "forwardable"

Expand All @@ -20,6 +21,7 @@ class Parser

def initialize(vault_directory)
@index = Obsidian::Page.create_root
renderer = HtmlRenderer.new

vault_directory.glob("**/*.md").each do |path|
dirname, basename = path.relative_path_from(vault_directory).split
Expand All @@ -39,7 +41,7 @@ def initialize(vault_directory)
@index.add_page(
slug,
last_modified: path.mtime,
content: MarkdownContent.new(path, @index)
content: MarkdownContent.new(path, @index, renderer: renderer)
)
end

Expand Down
40 changes: 40 additions & 0 deletions lib/obsidian/parser/html_renderer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class HtmlRenderer < Markly::Renderer::HTML
def header(node)
block do
out("<h", node.header_level, " id=\"", header_id(node), "\">",
:children, "</h", node.header_level, ">")
end
end

private

def header_id(node)
# Taken from Kramdown
# https://github.com/gettalong/kramdown/blob/bd678ecb59f70778fdb3b08bdcd39e2ab7379b45/lib/kramdown/converter/base.rb
gen_id = extract_text(node).gsub(/^[^a-zA-Z]+/, "")
gen_id.tr!("^a-zA-Z0-9 -", "")
gen_id.tr!(" ", "-")
gen_id.downcase!

gen_id = "section" if gen_id.empty?

@used_ids ||= {}
if @used_ids.key?(gen_id)
gen_id += "-#{@used_ids[gen_id] += 1}"
else
@used_ids[gen_id] = 0
end

gen_id
end

def extract_text(node)
node.each do |subnode|
if subnode.type == :text
return subnode.string_content
end
end

""
end
end
5 changes: 3 additions & 2 deletions lib/obsidian/parser/markdown_content.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

module Obsidian
class MarkdownContent
def initialize(path, root)
def initialize(path, root, renderer:)
@path = path
@root = root
@renderer = renderer
end

def generate_html
markdown = @path.read
Obsidian::ObsidianFlavoredMarkdown.parse(markdown, root: @root).to_html
Obsidian::ObsidianFlavoredMarkdown.parse(markdown, root: @root, renderer: @renderer).to_html
end
end
end
9 changes: 3 additions & 6 deletions lib/obsidian/parser/obsidian_flavored_markdown.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

require "kramdown"
require "kramdown-parser-gfm"
require "markly"

module Obsidian
Expand Down Expand Up @@ -38,11 +36,10 @@ def self.expand_wikilinks(markdown_text, root:)
end
end

def self.parse(markdown_text, root: nil)
def self.parse(markdown_text, renderer:, root: nil)
normalized = expand_wikilinks(markdown_text, root: root)
document = Kramdown::Document.new(normalized, input: "GFM")
document2 = Markly.parse(normalized, flags: Markly::SMART | Markly::UNSAFE | Markly::HARD_BREAKS, extensions: [:table, :tasklist, :autolink])
Obsidian::ParsedMarkdownDocument.new(document, document2)
document = Markly.parse(normalized, flags: Markly::SMART | Markly::UNSAFE | Markly::HARD_BREAKS, extensions: [:table, :tasklist, :autolink])
Obsidian::ParsedMarkdownDocument.new(document, renderer: renderer)
end
end
end
9 changes: 5 additions & 4 deletions lib/obsidian/parser/parsed_markdown_document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

module Obsidian
class ParsedMarkdownDocument
def initialize(document, document2)
@document2 = document
@document = document2
def initialize(document, renderer:)
@document = document
@renderer = renderer
end

def extract_links
Expand All @@ -22,12 +22,13 @@ def extract_links
end

def to_html
@document2.to_html
renderer.render(document)
end

private

attr_reader :document
attr_reader :renderer

def _extract_text_content(element)
if element.type == :text
Expand Down
2 changes: 0 additions & 2 deletions obsidian-parser.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

spec.add_dependency "kramdown", "~> 2.4"
spec.add_dependency "kramdown-parser-gfm", "~> 1.1"
spec.add_dependency "markly", "~> 0.7.0"

# For more information and examples about making a new gem, check out our
Expand Down
4 changes: 2 additions & 2 deletions spec/obsidian/parser/parsed_markdown_document_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
let(:index) { nil }

def create_instance(markdown)
Obsidian::ObsidianFlavoredMarkdown.parse(markdown, root: index)
Obsidian::ObsidianFlavoredMarkdown.parse(markdown, root: index, renderer: HtmlRenderer.new)
end

it "extracts [foo](bar) links" do
Expand Down Expand Up @@ -38,7 +38,7 @@ def create_instance(markdown)
[bar]: /url "title"
END

parsed_document = Obsidian::ObsidianFlavoredMarkdown.parse(markdown)
parsed_document = Obsidian::ObsidianFlavoredMarkdown.parse(markdown, renderer: HtmlRenderer.new)

links = parsed_document.extract_links

Expand Down
2 changes: 1 addition & 1 deletion spec/obsidian/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
end

it "converts markdown into HTML content" do
expect(parser.pages.find { |note| note.title == "cat" }.content.generate_html).to eq("<h2 id=\"cats-are-the-best\">Cats are the best</h2>\n\n<p>Meow meow meow</p>\n")
expect(parser.pages.find { |note| note.title == "cat" }.content.generate_html).to eq("<h2 id=\"cats-are-the-best\">Cats are the best</h2>\n<p>Meow meow meow</p>\n")
end

it "adds index.md content to index pages" do
Expand Down

0 comments on commit 866c2f7

Please sign in to comment.