added proper link resolution
This commit is contained in:
parent
0fdbd3d221
commit
f34f446bf9
|
@ -3,7 +3,7 @@
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tree import SourceNode
|
from tree import SourceNode, SourceIndex
|
||||||
from mparse import create_markdown_parser
|
from mparse import create_markdown_parser
|
||||||
|
|
||||||
# The command line parser
|
# The command line parser
|
||||||
|
@ -29,7 +29,9 @@ def main():
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
node.load_metadata(source_dir)
|
node.load_metadata(source_dir)
|
||||||
|
|
||||||
mdparse = create_markdown_parser()
|
src_index = SourceIndex(nodes)
|
||||||
|
|
||||||
|
mdparse = create_markdown_parser(src_index)
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
node.parse_markdown(source_dir, mdparse)
|
node.parse_markdown(source_dir, mdparse)
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,14 @@ class MetaStripper(Extension):
|
||||||
|
|
||||||
|
|
||||||
class ObsidianLinks(Extension):
|
class ObsidianLinks(Extension):
|
||||||
|
def __init__(self, src_index, **kwargs):
|
||||||
|
super(ObsidianLinks, self).__init__(**kwargs)
|
||||||
|
self._src_index = src_index
|
||||||
|
|
||||||
class ObsidianLinksProc(InlineProcessor):
|
class ObsidianLinksProc(InlineProcessor):
|
||||||
def __init__(self, pattern, md):
|
def __init__(self, pattern, md, src_index):
|
||||||
super(ObsidianLinks.ObsidianLinksProc, self).__init__(pattern, md)
|
super(ObsidianLinks.ObsidianLinksProc, self).__init__(pattern, md)
|
||||||
|
self._src_index = src_index
|
||||||
|
|
||||||
def parse_reference(self, contents):
|
def parse_reference(self, contents):
|
||||||
text = None
|
text = None
|
||||||
|
@ -34,31 +38,37 @@ class ObsidianLinks(Extension):
|
||||||
if len(t) > 1:
|
if len(t) > 1:
|
||||||
text = t[1]
|
text = t[1]
|
||||||
contents = t[0]
|
contents = t[0]
|
||||||
|
|
||||||
|
node, linktype = self._src_index.lookup(contents)
|
||||||
if not text:
|
if not text:
|
||||||
text = contents
|
text = contents
|
||||||
return contents, text
|
if node:
|
||||||
|
return node.link_target, text
|
||||||
|
return None, text
|
||||||
|
|
||||||
def handleMatch(self, m, data):
|
def handleMatch(self, m, data):
|
||||||
link, text = self.parse_reference(m.group(0)[2:-2])
|
link, text = self.parse_reference(m.group(0)[2:-2])
|
||||||
el = etree.Element('a')
|
if link is None:
|
||||||
el.set('href', link)
|
el = etree.Element('span')
|
||||||
el.text = text
|
el.set('class', 'invalid-reference')
|
||||||
|
el.text = text
|
||||||
|
else:
|
||||||
|
el = etree.Element('a')
|
||||||
|
el.set('href', link)
|
||||||
|
el.text = text
|
||||||
return el, m.start(0), m.end(0)
|
return el, m.start(0), m.end(0)
|
||||||
|
|
||||||
def extendMarkdown(self, md):
|
def extendMarkdown(self, md):
|
||||||
OBSLINK_PATTERN = r'\[\[(.*?)\]\]'
|
OBSLINK_PATTERN = r'\[\[(.*?)\]\]'
|
||||||
md.inlinePatterns.register(ObsidianLinks.ObsidianLinksProc(OBSLINK_PATTERN, md), 'obsidian_links', 0)
|
md.inlinePatterns.register(ObsidianLinks.ObsidianLinksProc(OBSLINK_PATTERN, md, self._src_index),
|
||||||
|
'obsidian_links', 0)
|
||||||
|
|
||||||
|
|
||||||
class Strikeout(Extension):
|
class ObsidianInlines(Extension):
|
||||||
def extendMarkdown(self, md):
|
def extendMarkdown(self, md):
|
||||||
md.inlinePatterns.register(SimpleTagInlineProcessor(r'()~~(.*?)~~', 'del'), 'strikeout', 0)
|
md.inlinePatterns.register(SimpleTagInlineProcessor(r'()~~(.*?)~~', 'del'), 'strikeout', 0)
|
||||||
|
|
||||||
|
|
||||||
class Highlight(Extension):
|
|
||||||
def extendMarkdown(self, md):
|
|
||||||
md.inlinePatterns.register(SimpleTagInlineProcessor(r'()\=\=(.*?)\=\=', 'ins'), 'highlight', 0)
|
md.inlinePatterns.register(SimpleTagInlineProcessor(r'()\=\=(.*?)\=\=', 'ins'), 'highlight', 0)
|
||||||
|
|
||||||
|
|
||||||
def create_markdown_parser():
|
def create_markdown_parser(src_index):
|
||||||
return markdown.Markdown(extensions=[MetaStripper(), ObsidianLinks(), Strikeout(), Highlight()])
|
return markdown.Markdown(extensions=[MetaStripper(), ObsidianLinks(src_index), ObsidianInlines()])
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from urllib.parse import quote as urlquote
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
# The paths that are always to be ignored.
|
# The paths that are always to be ignored.
|
||||||
|
@ -21,6 +22,11 @@ class SourceNode:
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"SourceNode({self._path}, {self._is_dir}) [is_md={self._is_md}]"
|
return f"SourceNode({self._path}, {self._is_dir}) [is_md={self._is_md}]"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def link_target(self):
|
||||||
|
xpath = self._path.with_suffix('.html') if self._is_md else self._path
|
||||||
|
return urlquote(xpath.as_posix())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate_list(cls, source_root):
|
def generate_list(cls, source_root):
|
||||||
nodes = []
|
nodes = []
|
||||||
|
@ -43,10 +49,8 @@ class SourceNode:
|
||||||
def load_metadata(self, source_dir):
|
def load_metadata(self, source_dir):
|
||||||
if self._is_md:
|
if self._is_md:
|
||||||
with open(source_dir / self._path, "r", encoding="utf-8") as f:
|
with open(source_dir / self._path, "r", encoding="utf-8") as f:
|
||||||
print(">>>opened")
|
|
||||||
l = f.readline()
|
l = f.readline()
|
||||||
if l == '---\n':
|
if l == '---\n':
|
||||||
print(">>>startmd")
|
|
||||||
metalines = []
|
metalines = []
|
||||||
l = f.readline()
|
l = f.readline()
|
||||||
while l != '---\n':
|
while l != '---\n':
|
||||||
|
@ -59,3 +63,37 @@ class SourceNode:
|
||||||
markdown_parser.reset()
|
markdown_parser.reset()
|
||||||
with open(source_dir / self._path, "r", encoding="utf-8") as f:
|
with open(source_dir / self._path, "r", encoding="utf-8") as f:
|
||||||
self.text = markdown_parser.convert(f.read())
|
self.text = markdown_parser.convert(f.read())
|
||||||
|
|
||||||
|
|
||||||
|
class SourceIndex:
|
||||||
|
def __init__(self, nodelist):
|
||||||
|
self._byname = {}
|
||||||
|
self._byalias = {}
|
||||||
|
for node in nodelist:
|
||||||
|
if node._is_dir:
|
||||||
|
continue
|
||||||
|
if node._is_md:
|
||||||
|
tmp = node._path.with_suffix('')
|
||||||
|
key = tmp.name
|
||||||
|
if key not in self._byname:
|
||||||
|
self._byname[key] = node
|
||||||
|
self._byname[tmp.as_posix()] = node
|
||||||
|
if node.metadata:
|
||||||
|
aliases = node.metadata.get('aliases', [])
|
||||||
|
if isinstance(aliases, list):
|
||||||
|
for alias in aliases:
|
||||||
|
if alias not in self._byalias:
|
||||||
|
self._byalias[alias] = node
|
||||||
|
else:
|
||||||
|
key = self._path.name
|
||||||
|
if key not in self._byname:
|
||||||
|
self._byname[key] = node
|
||||||
|
self._byname[self._path.as_posix()] = node
|
||||||
|
|
||||||
|
def lookup(self, reference):
|
||||||
|
if reference in self._byname:
|
||||||
|
return self._byname[reference], 'NAME'
|
||||||
|
elif reference in self._byalias:
|
||||||
|
return self._byalias[reference], 'ALIAS'
|
||||||
|
else:
|
||||||
|
return None, None
|
||||||
|
|
Loading…
Reference in New Issue
Block a user