added proper link resolution
This commit is contained in:
parent
0fdbd3d221
commit
f34f446bf9
|
@ -3,7 +3,7 @@
|
|||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from tree import SourceNode
|
||||
from tree import SourceNode, SourceIndex
|
||||
from mparse import create_markdown_parser
|
||||
|
||||
# The command line parser
|
||||
|
@ -29,7 +29,9 @@ def main():
|
|||
for node in nodes:
|
||||
node.load_metadata(source_dir)
|
||||
|
||||
mdparse = create_markdown_parser()
|
||||
src_index = SourceIndex(nodes)
|
||||
|
||||
mdparse = create_markdown_parser(src_index)
|
||||
for node in nodes:
|
||||
node.parse_markdown(source_dir, mdparse)
|
||||
|
||||
|
|
|
@ -23,10 +23,14 @@ class MetaStripper(Extension):
|
|||
|
||||
|
||||
class ObsidianLinks(Extension):
|
||||
def __init__(self, src_index, **kwargs):
|
||||
super(ObsidianLinks, self).__init__(**kwargs)
|
||||
self._src_index = src_index
|
||||
|
||||
class ObsidianLinksProc(InlineProcessor):
|
||||
def __init__(self, pattern, md):
|
||||
def __init__(self, pattern, md, src_index):
|
||||
super(ObsidianLinks.ObsidianLinksProc, self).__init__(pattern, md)
|
||||
self._src_index = src_index
|
||||
|
||||
def parse_reference(self, contents):
|
||||
text = None
|
||||
|
@ -34,31 +38,37 @@ class ObsidianLinks(Extension):
|
|||
if len(t) > 1:
|
||||
text = t[1]
|
||||
contents = t[0]
|
||||
|
||||
node, linktype = self._src_index.lookup(contents)
|
||||
if not text:
|
||||
text = contents
|
||||
return contents, text
|
||||
if node:
|
||||
return node.link_target, text
|
||||
return None, text
|
||||
|
||||
def handleMatch(self, m, data):
|
||||
link, text = self.parse_reference(m.group(0)[2:-2])
|
||||
el = etree.Element('a')
|
||||
el.set('href', link)
|
||||
el.text = text
|
||||
if link is None:
|
||||
el = etree.Element('span')
|
||||
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)
|
||||
|
||||
def extendMarkdown(self, md):
|
||||
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):
|
||||
md.inlinePatterns.register(SimpleTagInlineProcessor(r'()~~(.*?)~~', 'del'), 'strikeout', 0)
|
||||
|
||||
|
||||
class Highlight(Extension):
|
||||
def extendMarkdown(self, md):
|
||||
md.inlinePatterns.register(SimpleTagInlineProcessor(r'()\=\=(.*?)\=\=', 'ins'), 'highlight', 0)
|
||||
|
||||
|
||||
def create_markdown_parser():
|
||||
return markdown.Markdown(extensions=[MetaStripper(), ObsidianLinks(), Strikeout(), Highlight()])
|
||||
def create_markdown_parser(src_index):
|
||||
return markdown.Markdown(extensions=[MetaStripper(), ObsidianLinks(src_index), ObsidianInlines()])
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from urllib.parse import quote as urlquote
|
||||
import yaml
|
||||
|
||||
# The paths that are always to be ignored.
|
||||
|
@ -21,6 +22,11 @@ class SourceNode:
|
|||
def __str__(self):
|
||||
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
|
||||
def generate_list(cls, source_root):
|
||||
nodes = []
|
||||
|
@ -43,10 +49,8 @@ class SourceNode:
|
|||
def load_metadata(self, source_dir):
|
||||
if self._is_md:
|
||||
with open(source_dir / self._path, "r", encoding="utf-8") as f:
|
||||
print(">>>opened")
|
||||
l = f.readline()
|
||||
if l == '---\n':
|
||||
print(">>>startmd")
|
||||
metalines = []
|
||||
l = f.readline()
|
||||
while l != '---\n':
|
||||
|
@ -59,3 +63,37 @@ class SourceNode:
|
|||
markdown_parser.reset()
|
||||
with open(source_dir / self._path, "r", encoding="utf-8") as f:
|
||||
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