Skip to content

Commit

Permalink
Support non-fully qualified titles when parsing wikilink syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
MatMoore committed Aug 1, 2023
1 parent 5c48de8 commit 6c9faf3
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## [Unreleased]
- Support non-fully qualified titles when parsing wikilink syntax.

## [0.5.2] - 2023-07-30
- Fix handling of `index.md` at the root level.
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ gem "rake", "~> 13.0"
gem "rspec", "~> 3.0"

gem "standard", "~> 1.3"

gem "pry"
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
coderay (1.1.3)
diff-lcs (1.5.0)
json (2.6.3)
kramdown (2.4.0)
Expand All @@ -17,10 +18,14 @@ GEM
kramdown (~> 2.0)
language_server-protocol (3.17.0.3)
lint_roller (1.1.0)
method_source (1.0.0)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
racc (1.7.1)
rainbow (3.1.1)
rake (13.0.6)
Expand Down Expand Up @@ -74,6 +79,7 @@ PLATFORMS

DEPENDENCIES
obsidian-parser!
pry
rake (~> 13.0)
rspec (~> 3.0)
standard (~> 1.3)
Expand Down
7 changes: 4 additions & 3 deletions lib/obsidian/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ def self.build_slug(title, parent_slug)
end

class MarkdownContent
def initialize(path)
def initialize(path, root)
@path = path
@root = root
end

def generate_html
markdown = @path.read
Obsidian::ObsidianFlavoredMarkdown.parse(markdown).to_html
Obsidian::ObsidianFlavoredMarkdown.parse(markdown, @root).to_html
end
end

Expand Down Expand Up @@ -49,7 +50,7 @@ def initialize(vault_directory)
@index.add_page(
slug,
last_modified: path.mtime,
content: MarkdownContent.new(path)
content: MarkdownContent.new(path, @index)
)
end

Expand Down
13 changes: 8 additions & 5 deletions lib/obsidian/parser/obsidian_flavored_markdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,24 @@ module ObsidianFlavoredMarkdown

# Convert Obsidian-flavored-markdown syntax to something parseable
# (i.e. with Github-flavored-markdown syntax)
def self.normalize(markdown_text)
def self.normalize(markdown_text, root)
markdown_text.gsub(WIKILINK_SYNTAX) do |s|
text = $~[:text]
target = $~[:target]
fragment = $~[:fragment]
display_text = text.nil? ? target.split("/").last : text
href = fragment.nil? ? target : "#{target}##{fragment}"
page = root.find_in_tree(target)
return text.nil? ? target.split("/").last : text if page.nil?

display_text = text.nil? ? page.slug.split("/").last : text
href = fragment.nil? ? page.slug : "#{page.slug}##{fragment}"

"[#{display_text}](#{href})"
end
end

# Parse links from obsidian-flavored-markdown text
def self.parse(markdown_text)
document = Kramdown::Document.new(normalize(markdown_text), input: "GFM")
def self.parse(markdown_text, root)
document = Kramdown::Document.new(normalize(markdown_text, root), input: "GFM")
Obsidian::ParsedMarkdownDocument.new(document)
end
end
Expand Down
24 changes: 20 additions & 4 deletions spec/obsidian/parser/obsidian_flavored_markdown_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,41 @@

RSpec.describe Obsidian::ObsidianFlavoredMarkdown do
describe ".normalize" do
let(:index) { Obsidian::Page.create_root }

before do
index.add_page("foo/bar")
end

it "turns wikilinks into normal links" do
result = described_class.normalize("[[foo]]")
result = described_class.normalize("[[foo]]", index)
expect(result).to eq("[foo](foo)")
end

it "uses only the basepath for titles" do
result = described_class.normalize("[[foo/bar]]")
result = described_class.normalize("[[foo/bar]]", index)
expect(result).to eq("[bar](foo/bar)")
end

it "uses the custom display name if present" do
result = described_class.normalize("[[foo/bar|baz]]")
result = described_class.normalize("[[foo/bar|baz]]", index)
expect(result).to eq("[baz](foo/bar)")
end

# Note: this is part of Github Flavored Markdown
# See https://github.github.com/gfm/#example-510
it "includes fragments if present" do
result = described_class.normalize("[[foo/bar#baz]]")
result = described_class.normalize("[[foo/bar#baz]]", index)
expect(result).to eq("[bar](foo/bar#baz)")
end

it "infers the full slug if a prefix is missing" do
result = described_class.normalize("[[bar]]", index)
expect(result).to eq("[bar](foo/bar)")
end

it "infers the full slug if a prefix is missing and there is a fragment" do
result = described_class.normalize("[[bar#baz]]", index)
expect(result).to eq("[bar](foo/bar#baz)")
end
end
Expand Down
19 changes: 13 additions & 6 deletions spec/obsidian/parser/parsed_markdown_document_spec.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
# frozen_string_literal: true

RSpec.describe Obsidian::ParsedMarkdownDocument do
let(:index) { Obsidian::Page.create_root }

before do
index.add_page("foo/bar")
index.add_page("animals/cat")
end

it "extracts [foo](bar) links" do
markdown = "here is a link: [foo](bar)"

converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown)
converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown, index)
links = converter.extract_links

expect(links).to include(["bar", "foo"])
Expand All @@ -13,15 +20,15 @@
it "extracts [foo](bar) links" do
markdown = "here is a link: [foo](bar)"

converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown)
converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown, index)
links = converter.extract_links

expect(links).to include(["bar", "foo"])
end

it "extracts links with titles" do
markdown = '[link](/uri "title")'
converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown)
converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown, index)
links = converter.extract_links

expect(links).to include(["/uri", "link"])
Expand All @@ -30,7 +37,7 @@
it "extracts links with no destinations" do
markdown = "[link1]() [link2](<>)"

converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown)
converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown, index)
links = converter.extract_links

expect(links).to include(["", "link1"], ["", "link2"])
Expand All @@ -43,7 +50,7 @@
[bar]: /url "title"
END

converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown)
converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown, index)
links = converter.extract_links

expect(links).to include(["/url", "foo"])
Expand All @@ -52,7 +59,7 @@
it "extracts wikilinks" do
markdown = "[[animals/cat]]"

converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown)
converter = Obsidian::ObsidianFlavoredMarkdown.parse(markdown, index)
links = converter.extract_links

expect(links).to include(["animals/cat", "cat"])
Expand Down

0 comments on commit 6c9faf3

Please sign in to comment.