Track general purpose custom markup
This commit is contained in:
parent
4353265dca
commit
0196f3f86a
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,4 +2,4 @@
|
||||
/index.pickle
|
||||
__pycache__
|
||||
|
||||
/wikinote/markup_custom.py
|
||||
/wikinote/markup_custom2.py
|
||||
|
@ -411,9 +411,13 @@ class FootnoteInlineProcessor(markdown.extensions.footnotes.FootnoteInlineProces
|
||||
return None, None, None
|
||||
|
||||
# Custom directives and roles
|
||||
try:
|
||||
from . import markup_custom
|
||||
directives.update(markup_custom.directives)
|
||||
roles.update(markup_custom.roles)
|
||||
|
||||
try:
|
||||
from . import markup_custom2
|
||||
directives.update(markup_custom2.directives)
|
||||
roles.update(markup_custom2.roles)
|
||||
except ImportError:
|
||||
pass
|
||||
|
119
wikinote/markup_custom.py
Normal file
119
wikinote/markup_custom.py
Normal file
@ -0,0 +1,119 @@
|
||||
# WikiNote3
|
||||
# Copyright © 2020 Lee Yingtong Li (RunasSudo)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import flask
|
||||
|
||||
import os.path
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
directives = {}
|
||||
roles = {}
|
||||
|
||||
class DirectiveElement(ET.Element):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.directive = None
|
||||
|
||||
class Directive:
|
||||
def __init__(self, md, arg=None, content=None):
|
||||
self.md = md
|
||||
self.arg = arg
|
||||
self.content = content
|
||||
|
||||
class RoleElement(ET.Element):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.role = None
|
||||
|
||||
class Role:
|
||||
def __init__(self, parser, content=None):
|
||||
self.parser = parser
|
||||
self.md = parser.md
|
||||
self.content = content
|
||||
|
||||
def capitalise(n):
|
||||
if n.startswith('('):
|
||||
return '(' + capitalise(n[1:])
|
||||
return n[0].upper() + n[1:]
|
||||
|
||||
class DirectiveTag(Directive):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.md.meta['tags'] = self.md.meta.get('tags', []) + self.arg.split(', ')
|
||||
|
||||
def render(self):
|
||||
return DirectiveElement('div')
|
||||
|
||||
directives['tag'] = DirectiveTag
|
||||
|
||||
class DirectiveInclude(Directive):
|
||||
def render(self):
|
||||
el = DirectiveElement('div')
|
||||
with open(flask.safe_join('./data', self.arg), 'r') as f:
|
||||
self.md.parser.parseChunk(el, f.read())
|
||||
return el
|
||||
|
||||
directives['include'] = DirectiveInclude
|
||||
|
||||
def make_role_ref(is_upper):
|
||||
class RoleRef(Role):
|
||||
def render(self):
|
||||
if ';' in self.content:
|
||||
label, path = self.content.split(';')
|
||||
else:
|
||||
path = self.content
|
||||
label = path.split('/')[-1]
|
||||
if is_upper:
|
||||
label = label[0].upper() + label[1:]
|
||||
else:
|
||||
label = label[0].lower() + label[1:]
|
||||
|
||||
# Tooltip wrapper
|
||||
el = RoleElement('span')
|
||||
el.set('class', 'tooltip xref')
|
||||
el.set('data-xref', path)
|
||||
|
||||
# Link
|
||||
a = ET.SubElement(el, 'a')
|
||||
if os.path.exists(flask.safe_join('./data/pages', path + '.md')):
|
||||
a.set('class', 'ref')
|
||||
else:
|
||||
a.set('class', 'ref redlink')
|
||||
self.md.meta['redlinks'] = self.md.meta.get('redlinks', []) + [path]
|
||||
a.set('href', flask.url_for('page_view', path=path))
|
||||
a.text = label
|
||||
|
||||
# Tooltip content container
|
||||
div = ET.SubElement(el, 'span')
|
||||
div.set('class', 'tooltip-content')
|
||||
div.text = 'Loading…'
|
||||
|
||||
return el
|
||||
return RoleRef
|
||||
|
||||
roles['ref'] = make_role_ref(False)
|
||||
roles['Ref'] = make_role_ref(True)
|
||||
|
||||
class RoleImage(Role):
|
||||
def render(self):
|
||||
el = RoleElement('a')
|
||||
el.set('href', flask.url_for('image_about', name=self.content))
|
||||
img = ET.SubElement(el, 'img')
|
||||
img.set('src', flask.url_for('image_view', name=self.content))
|
||||
return el
|
||||
|
||||
roles['image'] = RoleImage
|
Reference in New Issue
Block a user