allow configuration of some code generation details within Markdown converter
This commit is contained in:
parent
72a2ea1ab5
commit
8c4ab0c4d5
|
@ -6,6 +6,41 @@ prefix = "/"
|
||||||
# If true, generate relative URLs for all internal URLs. Default is false.
|
# If true, generate relative URLs for all internal URLs. Default is false.
|
||||||
relative = false
|
relative = false
|
||||||
|
|
||||||
|
[classnames]
|
||||||
|
# CSS class to use for an invalid reference.
|
||||||
|
invalid-reference = "invalid-reference"
|
||||||
|
# CSS class to use for an Obsidian link.
|
||||||
|
obsidian-link = "obsidian-link"
|
||||||
|
|
||||||
|
[callout-icons]
|
||||||
|
# The default callout icon.
|
||||||
|
_default = "pencil"
|
||||||
|
# Specific callout icons for other callouts.
|
||||||
|
abstract = "clipboard-list"
|
||||||
|
attention = "triangle-alert"
|
||||||
|
bug = "bug"
|
||||||
|
caution = "triangle-alert"
|
||||||
|
check = "check"
|
||||||
|
cite = "quote"
|
||||||
|
danger = "zap"
|
||||||
|
done = "check"
|
||||||
|
error = "zap"
|
||||||
|
example = "list"
|
||||||
|
fail = "x"
|
||||||
|
failure = "x"
|
||||||
|
faq = "circle-help"
|
||||||
|
help = "circle-help"
|
||||||
|
info = "info"
|
||||||
|
missing = "x"
|
||||||
|
question = "circle-help"
|
||||||
|
quote = "quote"
|
||||||
|
success = "check"
|
||||||
|
summary = "clipboard-list"
|
||||||
|
tip = "flame"
|
||||||
|
tldr = "clipboard-list"
|
||||||
|
todo = "circle-check"
|
||||||
|
warning = "triangle-alert"
|
||||||
|
|
||||||
[templates]
|
[templates]
|
||||||
# The template directory name under the Obsidian vault. Default is ".dragonglass.tmpl".
|
# The template directory name under the Obsidian vault. Default is ".dragonglass.tmpl".
|
||||||
directory = ".dragonglass.tmpl"
|
directory = ".dragonglass.tmpl"
|
||||||
|
|
|
@ -19,7 +19,35 @@ DEFAULT_TEMPLATE_DIRECTORY = ".dragonglass.tmpl"
|
||||||
DEFAULT_TEMPLATE_NAME = "default.html"
|
DEFAULT_TEMPLATE_NAME = "default.html"
|
||||||
""" The default stylesheet name."""
|
""" The default stylesheet name."""
|
||||||
DEFAULT_STYLESHEET_NAME = "dragonglass.css"
|
DEFAULT_STYLESHEET_NAME = "dragonglass.css"
|
||||||
|
"""The default callout icon."""
|
||||||
|
CALLOUT_DEFICON = 'pencil'
|
||||||
|
"""The default callout icons."""
|
||||||
|
CALLOUT_ICONS = {
|
||||||
|
'abstract': 'clipboard-list',
|
||||||
|
'attention': 'triangle-alert',
|
||||||
|
'bug': 'bug',
|
||||||
|
'caution': 'triangle-alert',
|
||||||
|
'check': 'check',
|
||||||
|
'cite': 'quote',
|
||||||
|
'danger': 'zap',
|
||||||
|
'done': 'check',
|
||||||
|
'error': 'zap',
|
||||||
|
'example': 'list',
|
||||||
|
'fail': 'x',
|
||||||
|
'failure': 'x',
|
||||||
|
'faq': 'circle-help',
|
||||||
|
'help': 'circle-help',
|
||||||
|
'info': 'info',
|
||||||
|
'missing': 'x',
|
||||||
|
'question': 'circle-help',
|
||||||
|
'quote': 'quote',
|
||||||
|
'success': 'check',
|
||||||
|
'summary': 'clipboard-list',
|
||||||
|
'tip': 'flame',
|
||||||
|
'tldr': 'clipboard-list',
|
||||||
|
'todo': 'circle-check',
|
||||||
|
'warning': 'triangle-alert'
|
||||||
|
}
|
||||||
|
|
||||||
class Context:
|
class Context:
|
||||||
"""
|
"""
|
||||||
|
@ -98,3 +126,29 @@ class Context:
|
||||||
if not self.template_dir.is_dir():
|
if not self.template_dir.is_dir():
|
||||||
return DEFAULT_TEMPLATE_NAME
|
return DEFAULT_TEMPLATE_NAME
|
||||||
return node.metadata.get("template", self._default_template_name)
|
return node.metadata.get("template", self._default_template_name)
|
||||||
|
|
||||||
|
def get_classname(self, classname: str) -> str:
|
||||||
|
"""
|
||||||
|
Return a classname configured in the configuration file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
classname (str): The key for the classname to get, which is also the default value.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: the configured classname, or the ``classname`` argument itself if nothing was configured.
|
||||||
|
"""
|
||||||
|
classnames_section = self.config.get("classnames", {})
|
||||||
|
return classnames_section.get(classname, classname)
|
||||||
|
|
||||||
|
def get_callout_iconname(self, callout: str) -> str:
|
||||||
|
"""
|
||||||
|
Return the name for a Lucide icon that represents a particular callout type.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callout (str): The type of the callout in question.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The name of an icon, or a default icon name.
|
||||||
|
"""
|
||||||
|
callout_icons = self.config.get('callout-icons', {})
|
||||||
|
return callout_icons.get(callout, CALLOUT_ICONS.get(callout, callout_icons.get('_default', CALLOUT_DEFICON)))
|
||||||
|
|
|
@ -73,23 +73,6 @@ def sanitize_reference(s: str) -> str:
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
|
|
||||||
def find_extension(md: markdown.Markdown, cls: type[Extension]) -> Extension | None:
|
|
||||||
"""
|
|
||||||
Locate a registered extension in the Markdown parser.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
md (markdown.Markdown): The Markdown parser to look through.
|
|
||||||
cls (type): The class of the extension to be retrieved.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Extension: The retrieved extension, or ``None`` if it was not found.
|
|
||||||
"""
|
|
||||||
for ex in md.registeredExtensions:
|
|
||||||
if isinstance(ex, cls):
|
|
||||||
return ex
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class MetaStripper(Extension):
|
class MetaStripper(Extension):
|
||||||
"""
|
"""
|
||||||
An extension that strips the metadata off the front of Obsidian pages, as it's already been parsed in an
|
An extension that strips the metadata off the front of Obsidian pages, as it's already been parsed in an
|
||||||
|
@ -145,7 +128,7 @@ class ObsidianImages(Extension):
|
||||||
"""
|
"""
|
||||||
Returns the CSS class name for an invalid reference in the text.
|
Returns the CSS class name for an invalid reference in the text.
|
||||||
"""
|
"""
|
||||||
return 'invalid-reference'
|
return self._context.get_classname('invalid-reference')
|
||||||
|
|
||||||
def _parse_dimensions(self, s: str) -> tuple[str, int, int]:
|
def _parse_dimensions(self, s: str) -> tuple[str, int, int]:
|
||||||
"""
|
"""
|
||||||
|
@ -306,18 +289,37 @@ class ObsidianLinks(Extension):
|
||||||
Markdown link processing to handle Obsidian internal links as well as external links.
|
Markdown link processing to handle Obsidian internal links as well as external links.
|
||||||
"""
|
"""
|
||||||
def __init__(self, context: Context, **kwargs: dict[str, Any]) -> None:
|
def __init__(self, context: Context, **kwargs: dict[str, Any]) -> None:
|
||||||
|
"""
|
||||||
|
Initialize the ObsidianLinks extension.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
context (Context): Context object that contains configuration information.
|
||||||
|
**kwargs (dict[str, Any]: Additional configuration information.
|
||||||
|
"""
|
||||||
super(ObsidianLinks, self).__init__(**kwargs)
|
super(ObsidianLinks, self).__init__(**kwargs)
|
||||||
self._context = context
|
self._context = context
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def obsidian_link_classname(self) -> str:
|
def obsidian_link_classname(self) -> str:
|
||||||
return 'obsidian-link'
|
"""Returns the classname for Obsidian links."""
|
||||||
|
return self._context.get_classname('obsidian-link')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def invalid_reference_classname(self) -> str:
|
def invalid_reference_classname(self) -> str:
|
||||||
return 'invalid-reference'
|
"""Returns the classname for invalid references."""
|
||||||
|
return self._context.get_classname('invalid-reference')
|
||||||
|
|
||||||
def _parse_reference(self, contents: str) -> tuple[str | None, str]:
|
def _parse_reference(self, contents: str) -> tuple[str | None, str]:
|
||||||
|
"""
|
||||||
|
Parse a reference and break it into link target and title.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
contents (str): Contents of a link reference to look up.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The link target, or ``None`` if the link is invalid.
|
||||||
|
str: The link title to be used.
|
||||||
|
"""
|
||||||
contents = contents.replace(r'\|','|') # handle case where we're inside tables
|
contents = contents.replace(r'\|','|') # handle case where we're inside tables
|
||||||
text = None
|
text = None
|
||||||
t = contents.split('|')
|
t = contents.split('|')
|
||||||
|
@ -337,11 +339,34 @@ class ObsidianLinks(Extension):
|
||||||
return None, text
|
return None, text
|
||||||
|
|
||||||
class ObsidianLinksProc(InlineProcessor):
|
class ObsidianLinksProc(InlineProcessor):
|
||||||
|
"""Processor that handles Obsidian links, [[page]]."""
|
||||||
def __init__(self, pattern: str, md: markdown.Markdown, extref: Any) -> None:
|
def __init__(self, pattern: str, md: markdown.Markdown, extref: Any) -> None:
|
||||||
|
"""
|
||||||
|
Initialize the ObsidianLinksProc.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pattern (str): Regular expression pattern to be matched by this processor.
|
||||||
|
md (markdown.Markdown): Reference to the Markdown parser.
|
||||||
|
extref (ObsidianLinks): Backreference to the outer object.
|
||||||
|
"""
|
||||||
super(ObsidianLinks.ObsidianLinksProc, self).__init__(pattern, md)
|
super(ObsidianLinks.ObsidianLinksProc, self).__init__(pattern, md)
|
||||||
self._extref = extref
|
self._extref = extref
|
||||||
|
|
||||||
def handleMatch(self, m: re.Match[str], data: str) -> tuple[etree.Element, int, int]: # noqa: N802
|
def handleMatch(self, m: re.Match[str], data: str) -> tuple[etree.Element, int, int]: # noqa: N802
|
||||||
|
"""
|
||||||
|
Handles a match on the reference for this processor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m (re.Match[str]): The regular expression match data.
|
||||||
|
data (str): The entire block of text surrounding the pattern, as a multi-line string.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
el (etree.Element): The new HTML element being added to the tree, or ``None`` if the match was rejected.
|
||||||
|
int: The index of the first character in ``data`` that was "consumed" by the pattern, or ``None``
|
||||||
|
if the match was rejected,
|
||||||
|
int: The index of the first character in ``data`` that was *not* consumed by the pattern, or ``None``
|
||||||
|
if the match was rejected.
|
||||||
|
"""
|
||||||
link, text = self._extref._parse_reference(m.group(1))
|
link, text = self._extref._parse_reference(m.group(1))
|
||||||
if link is None:
|
if link is None:
|
||||||
el = etree.Element('span')
|
el = etree.Element('span')
|
||||||
|
@ -355,11 +380,34 @@ class ObsidianLinks(Extension):
|
||||||
return el, m.start(0), m.end(0)
|
return el, m.start(0), m.end(0)
|
||||||
|
|
||||||
class GenericLinksProc(InlineProcessor):
|
class GenericLinksProc(InlineProcessor):
|
||||||
|
"""Processor that handles generic links, [link text](url)."""
|
||||||
def __init__(self, pattern: str, md: markdown.Markdown, extref: Any) -> None:
|
def __init__(self, pattern: str, md: markdown.Markdown, extref: Any) -> None:
|
||||||
|
"""
|
||||||
|
Initialize the GenericLinksProc.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pattern (str): Regular expression pattern to be matched by this processor.
|
||||||
|
md (markdown.Markdown): Reference to the Markdown parser.
|
||||||
|
extref (ObsidianLinks): Backreference to the outer object.
|
||||||
|
"""
|
||||||
super(ObsidianLinks.GenericLinksProc, self).__init__(pattern, md)
|
super(ObsidianLinks.GenericLinksProc, self).__init__(pattern, md)
|
||||||
self._extref = extref
|
self._extref = extref
|
||||||
|
|
||||||
def handleMatch(self, m: re.Match[str], data: str) -> tuple[etree.Element, int, int]: # noqa: N802
|
def handleMatch(self, m: re.Match[str], data: str) -> tuple[etree.Element, int, int]: # noqa: N802
|
||||||
|
"""
|
||||||
|
Handles a match on the reference for this processor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m (re.Match[str]): The regular expression match data.
|
||||||
|
data (str): The entire block of text surrounding the pattern, as a multi-line string.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
el (etree.Element): The new HTML element being added to the tree, or ``None`` if the match was rejected.
|
||||||
|
int: The index of the first character in ``data`` that was "consumed" by the pattern, or ``None``
|
||||||
|
if the match was rejected,
|
||||||
|
int: The index of the first character in ``data`` that was *not* consumed by the pattern, or ``None``
|
||||||
|
if the match was rejected.
|
||||||
|
"""
|
||||||
text = m.group(1)
|
text = m.group(1)
|
||||||
link = m.group(2)
|
link = m.group(2)
|
||||||
if link.startswith('<') and link.endswith('>'): # handle whitespace encoding
|
if link.startswith('<') and link.endswith('>'): # handle whitespace encoding
|
||||||
|
@ -635,7 +683,6 @@ class ObsidianLists(Extension):
|
||||||
bool: ``True`` if this processor can handle the block, ``False`` if not.
|
bool: ``True`` if this processor can handle the block, ``False`` if not.
|
||||||
"""
|
"""
|
||||||
if self._extref.LIST_START in block:
|
if self._extref.LIST_START in block:
|
||||||
logger.debug("DETECT")
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -664,7 +711,6 @@ class ObsidianLists(Extension):
|
||||||
blocks.insert(0, chunk[p + len(self._extref.LIST_END) + 1:])
|
blocks.insert(0, chunk[p + len(self._extref.LIST_END) + 1:])
|
||||||
list_lines = chunk[:p].rstrip().split('\n')
|
list_lines = chunk[:p].rstrip().split('\n')
|
||||||
assert len(list_lines) > 0
|
assert len(list_lines) > 0
|
||||||
logger.debug(f"*** Found list: {list_lines}")
|
|
||||||
_, excess = self._build_list(parent, list_lines)
|
_, excess = self._build_list(parent, list_lines)
|
||||||
if len(excess) > 0:
|
if len(excess) > 0:
|
||||||
blocks.insert(0, '\n'.join(excess))
|
blocks.insert(0, '\n'.join(excess))
|
||||||
|
@ -862,36 +908,36 @@ class ObsidianStyleFootnotes(FootnoteExtension):
|
||||||
|
|
||||||
|
|
||||||
class ObsidianStyleBlockquotes(Extension):
|
class ObsidianStyleBlockquotes(Extension):
|
||||||
|
"""Extension that handles both blockquotes and callouts in the Obsidian style."""
|
||||||
|
def __init__(self, context: Context, **kwargs: dict[str, Any]) -> None:
|
||||||
|
"""
|
||||||
|
Initialize the ObsidianStyleBlockquotes extension.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
context (Context): Context object that contains configuration information.
|
||||||
|
**kwargs (dict[str, Any]: Additional configuration information.
|
||||||
|
"""
|
||||||
|
super(ObsidianStyleBlockquotes, self).__init__(**kwargs)
|
||||||
|
self._context = context
|
||||||
|
|
||||||
|
def _callout_iconname(self, callout: str) -> str:
|
||||||
|
"""
|
||||||
|
Returns the Lucide icon name for a specific type of callout.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callout (str): The callout type.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The icon name to use.
|
||||||
|
"""
|
||||||
|
return self._context.get_callout_iconname(callout)
|
||||||
|
|
||||||
class ObsidianBlockQuote(BlockQuoteProcessor):
|
class ObsidianBlockQuote(BlockQuoteProcessor):
|
||||||
CALLOUT = re.compile(r'^\[!([a-z]+)\]([-+])?(?:[ ]+(.*))?')
|
CALLOUT = re.compile(r'^\[!([a-z]+)\]([-+])?(?:[ ]+(.*))?')
|
||||||
CALLOUT_DEFICON = 'pencil'
|
|
||||||
CALLOUT_ICONS = {
|
def __init__(self, parser: BlockParser, extref: Any) -> None:
|
||||||
'abstract': 'clipboard-list',
|
super(ObsidianStyleBlockquotes.ObsidianBlockQuote, self).__init__(parser)
|
||||||
'attention': 'triangle-alert',
|
self._extref = extref
|
||||||
'bug': 'bug',
|
|
||||||
'caution': 'triangle-alert',
|
|
||||||
'check': 'check',
|
|
||||||
'cite': 'quote',
|
|
||||||
'danger': 'zap',
|
|
||||||
'done': 'check',
|
|
||||||
'error': 'zap',
|
|
||||||
'example': 'list',
|
|
||||||
'fail': 'x',
|
|
||||||
'failure': 'x',
|
|
||||||
'faq': 'circle-help',
|
|
||||||
'help': 'circle-help',
|
|
||||||
'info': 'info',
|
|
||||||
'missing': 'x',
|
|
||||||
'question': 'circle-help',
|
|
||||||
'quote': 'quote',
|
|
||||||
'success': 'check',
|
|
||||||
'summary': 'clipboard-list',
|
|
||||||
'tip': 'flame',
|
|
||||||
'tldr': 'clipboard-list',
|
|
||||||
'todo': 'circle-check',
|
|
||||||
'warning': 'triangle-alert'
|
|
||||||
}
|
|
||||||
|
|
||||||
def normal_blockquote(self, parent: etree.Element, block: str) -> None:
|
def normal_blockquote(self, parent: etree.Element, block: str) -> None:
|
||||||
sibling = self.lastChild(parent)
|
sibling = self.lastChild(parent)
|
||||||
|
@ -908,7 +954,7 @@ class ObsidianStyleBlockquotes(Extension):
|
||||||
self.parser.state.reset()
|
self.parser.state.reset()
|
||||||
|
|
||||||
def callout_block(self, parent: etree.Element, lines: list[str]) -> None:
|
def callout_block(self, parent: etree.Element, lines: list[str]) -> None:
|
||||||
m = self.CALLOUT.match(lines[0])
|
m = self.CALLOUT.match(lines.pop(0))
|
||||||
callout_type = m.group(1)
|
callout_type = m.group(1)
|
||||||
folding = m.group(2)
|
folding = m.group(2)
|
||||||
title = m.group(3)
|
title = m.group(3)
|
||||||
|
@ -923,7 +969,7 @@ class ObsidianStyleBlockquotes(Extension):
|
||||||
title_div = etree.SubElement(base_div, 'div', {'class': 'callout-title'})
|
title_div = etree.SubElement(base_div, 'div', {'class': 'callout-title'})
|
||||||
icon_div = etree.SubElement(title_div, 'div', {'class': 'callout-icon'})
|
icon_div = etree.SubElement(title_div, 'div', {'class': 'callout-icon'})
|
||||||
etree.SubElement(icon_div, 'span',
|
etree.SubElement(icon_div, 'span',
|
||||||
{'data-lucide': self.CALLOUT_ICONS.get(callout_type, self.CALLOUT_DEFICON)})
|
{'data-lucide': self._extref._callout_iconname(callout_type)})
|
||||||
inner_title_div = etree.SubElement(title_div, 'div', {'class': 'callout-title-inner'})
|
inner_title_div = etree.SubElement(title_div, 'div', {'class': 'callout-title-inner'})
|
||||||
inner_title_div.text = title
|
inner_title_div.text = title
|
||||||
if folding:
|
if folding:
|
||||||
|
@ -933,7 +979,6 @@ class ObsidianStyleBlockquotes(Extension):
|
||||||
fold_div = etree.SubElement(title_div, 'div', {'class': baseclass})
|
fold_div = etree.SubElement(title_div, 'div', {'class': baseclass})
|
||||||
etree.SubElement(fold_div, 'span',
|
etree.SubElement(fold_div, 'span',
|
||||||
{'data-lucide': 'chevron-right' if folding == '-' else 'chevron-down'})
|
{'data-lucide': 'chevron-right' if folding == '-' else 'chevron-down'})
|
||||||
lines.pop(0)
|
|
||||||
if len(lines) > 0:
|
if len(lines) > 0:
|
||||||
content_div = etree.SubElement(base_div, 'div', {'class': 'callout-content'})
|
content_div = etree.SubElement(base_div, 'div', {'class': 'callout-content'})
|
||||||
if folding:
|
if folding:
|
||||||
|
@ -955,11 +1000,10 @@ class ObsidianStyleBlockquotes(Extension):
|
||||||
# Remove `> ` from beginning of each line.
|
# Remove `> ` from beginning of each line.
|
||||||
lines = [self.clean(line) for line in block[m.start():].split('\n')]
|
lines = [self.clean(line) for line in block[m.start():].split('\n')]
|
||||||
callout = (self.CALLOUT.match(lines[0]) is not None)
|
callout = (self.CALLOUT.match(lines[0]) is not None)
|
||||||
block = '\n'.join(lines)
|
|
||||||
if callout:
|
if callout:
|
||||||
self.callout_block(parent, lines)
|
self.callout_block(parent, lines)
|
||||||
else:
|
else:
|
||||||
self.normal_blockquote(parent, block)
|
self.normal_blockquote(parent, '\n'.join(lines))
|
||||||
|
|
||||||
class CalloutLinesProcessor(BlockProcessor):
|
class CalloutLinesProcessor(BlockProcessor):
|
||||||
def test(self, parent: etree.Element, block: str) -> bool:
|
def test(self, parent: etree.Element, block: str) -> bool:
|
||||||
|
@ -984,7 +1028,7 @@ class ObsidianStyleBlockquotes(Extension):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def extendMarkdown(self, md) -> None:
|
def extendMarkdown(self, md) -> None:
|
||||||
md.parser.blockprocessors.register(ObsidianStyleBlockquotes.ObsidianBlockQuote(md.parser), 'quote', 20)
|
md.parser.blockprocessors.register(ObsidianStyleBlockquotes.ObsidianBlockQuote(md.parser, self), 'quote', 20)
|
||||||
md.parser.blockprocessors.register(ObsidianStyleBlockquotes.CalloutLinesProcessor(md.parser),
|
md.parser.blockprocessors.register(ObsidianStyleBlockquotes.CalloutLinesProcessor(md.parser),
|
||||||
'callout-text', 11)
|
'callout-text', 11)
|
||||||
|
|
||||||
|
@ -1015,7 +1059,7 @@ def create_markdown_parser(context: Context) -> markdown.Markdown:
|
||||||
MetaStripper(),
|
MetaStripper(),
|
||||||
ObsidianComments(),
|
ObsidianComments(),
|
||||||
ObsidianStyleFootnotes(SUPERSCRIPT_TEXT='[{}]', SEPARATOR='-'),
|
ObsidianStyleFootnotes(SUPERSCRIPT_TEXT='[{}]', SEPARATOR='-'),
|
||||||
ObsidianStyleBlockquotes(),
|
ObsidianStyleBlockquotes(context),
|
||||||
ObsidianImages(context),
|
ObsidianImages(context),
|
||||||
ObsidianLinks(context),
|
ObsidianLinks(context),
|
||||||
ObsidianLists(),
|
ObsidianLists(),
|
||||||
|
|
|
@ -7,12 +7,18 @@ from jinja2 import Environment
|
||||||
|
|
||||||
from .config import Context
|
from .config import Context
|
||||||
|
|
||||||
|
"""Class names we want to look up in the configuration file."""
|
||||||
|
KNOWN_CLASSNAMES = [
|
||||||
|
'invalid-reference',
|
||||||
|
'obsidian-link'
|
||||||
|
]
|
||||||
|
|
||||||
"""Template data for the default stylesheet."""
|
"""Template data for the default stylesheet."""
|
||||||
STYLESHEET_DATA = """/* Dragonglass default CSS file - ensure all generated HTML pages reference this */
|
STYLESHEET_DATA = """/* Dragonglass default CSS file - ensure all generated HTML pages reference this */
|
||||||
a {
|
a {
|
||||||
color: #8a5cf5;
|
color: #8a5cf5;
|
||||||
}
|
}
|
||||||
.invalid-reference {
|
.{{ invalid_reference }} {
|
||||||
color: #ad8df8;
|
color: #ad8df8;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-decoration-color: #e6ddfd;
|
text-decoration-color: #e6ddfd;
|
||||||
|
@ -222,8 +228,15 @@ def write_default_stylesheet(ctxt: Context, tenv: Environment, dest_dir: Path) -
|
||||||
tenv (Environment): Template engine used to render the default stylesheet data.
|
tenv (Environment): Template engine used to render the default stylesheet data.
|
||||||
dest_dir (Path): The destination directory to write the stylesheet to.
|
dest_dir (Path): The destination directory to write the stylesheet to.
|
||||||
"""
|
"""
|
||||||
|
vars = {}
|
||||||
|
|
||||||
|
# Fill in all the class names as variables.
|
||||||
|
for n in KNOWN_CLASSNAMES:
|
||||||
|
vname = n.replace("-", '_')
|
||||||
|
vars[vname] = ctxt.get_classname(n)
|
||||||
|
|
||||||
to_file = dest_dir / ctxt.default_stylesheet
|
to_file = dest_dir / ctxt.default_stylesheet
|
||||||
tmpl = tenv.from_string(STYLESHEET_DATA)
|
tmpl = tenv.from_string(STYLESHEET_DATA)
|
||||||
data = tmpl.render({})
|
data = tmpl.render(vars)
|
||||||
with to_file.open("wt") as f:
|
with to_file.open("wt") as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user