beginnings of callout support
This commit is contained in:
parent
b20313fe4b
commit
a33845f832
|
@ -13,7 +13,7 @@ from urllib.parse import urlparse
|
||||||
|
|
||||||
import markdown
|
import markdown
|
||||||
from markdown import Markdown
|
from markdown import Markdown
|
||||||
from markdown.blockprocessors import BlockProcessor, BlockParser
|
from markdown.blockprocessors import BlockProcessor, BlockParser, BlockQuoteProcessor
|
||||||
from markdown.extensions import Extension
|
from markdown.extensions import Extension
|
||||||
from markdown.extensions.footnotes import (FootnoteExtension, FootnoteBlockProcessor, FootnoteInlineProcessor,
|
from markdown.extensions.footnotes import (FootnoteExtension, FootnoteBlockProcessor, FootnoteInlineProcessor,
|
||||||
FootnoteTreeprocessor, FootnotePostTreeprocessor, FootnotePostprocessor)
|
FootnoteTreeprocessor, FootnotePostTreeprocessor, FootnotePostprocessor)
|
||||||
|
@ -861,6 +861,71 @@ class ObsidianStyleFootnotes(FootnoteExtension):
|
||||||
md.postprocessors.register(FootnotePostprocessor(self), 'footnote', 25)
|
md.postprocessors.register(FootnotePostprocessor(self), 'footnote', 25)
|
||||||
|
|
||||||
|
|
||||||
|
class ObsidianStyleBlockquotes(Extension):
|
||||||
|
|
||||||
|
class ObsidianBlockQuote(BlockQuoteProcessor):
|
||||||
|
CALLOUT = re.compile(r'^\[!([a-z]+)\]([-+])?(?:[ ]+(.*))?')
|
||||||
|
|
||||||
|
def normal_blockquote(self, parent: etree.Element, block: str) -> None:
|
||||||
|
sibling = self.lastChild(parent)
|
||||||
|
if sibling is not None and sibling.tag == "blockquote":
|
||||||
|
# Previous block was a blockquote so set that as this blocks parent
|
||||||
|
quote = sibling
|
||||||
|
else:
|
||||||
|
# This is a new blockquote. Create a new parent element.
|
||||||
|
quote = etree.SubElement(parent, 'blockquote')
|
||||||
|
# Recursively parse block with blockquote as parent.
|
||||||
|
# change parser state so blockquotes embedded in lists use `p` tags
|
||||||
|
self.parser.state.set('blockquote')
|
||||||
|
self.parser.parseChunk(quote, block)
|
||||||
|
self.parser.state.reset()
|
||||||
|
|
||||||
|
def callout_block(self, parent: etree.Element, lines: list[str]) -> None:
|
||||||
|
m = self.CALLOUT.match(lines[0])
|
||||||
|
callout_type = m.group(1)
|
||||||
|
# folding = m.group(2)
|
||||||
|
title = m.group(3)
|
||||||
|
if not title:
|
||||||
|
title = callout_type.title()
|
||||||
|
base_div = etree.SubElement(parent, 'div', {'class': 'callout', 'data-callout': callout_type})
|
||||||
|
title_div = etree.SubElement(base_div, 'div', {'class': 'callout-title'})
|
||||||
|
# TODO: add title icon here
|
||||||
|
inner_title_div = etree.SubElement(title_div, 'div', {'class': 'callout-title-inner'})
|
||||||
|
inner_title_div.text = title
|
||||||
|
content_div = etree.SubElement(base_div, 'div', {'class': 'callout-content'})
|
||||||
|
lines.pop(0)
|
||||||
|
first = True
|
||||||
|
for line in lines:
|
||||||
|
if first:
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
etree.SubElement(content_div, 'br')
|
||||||
|
self.parser.state.set('list')
|
||||||
|
self.parser.parseBlocks(content_div, [line])
|
||||||
|
self.parser.state.reset()
|
||||||
|
|
||||||
|
def run(self, parent: etree.Element, blocks: list[str]) -> None:
|
||||||
|
block = blocks.pop(0)
|
||||||
|
lines: list[str] = []
|
||||||
|
callout = False
|
||||||
|
m = self.RE.search(block)
|
||||||
|
if m:
|
||||||
|
before = block[:m.start()] # Lines before blockquote
|
||||||
|
# Pass lines before blockquote in recursively for parsing first.
|
||||||
|
self.parser.parseBlocks(parent, [before])
|
||||||
|
# Remove `> ` from beginning of each line.
|
||||||
|
lines = [self.clean(line) for line in block[m.start():].split('\n')]
|
||||||
|
callout = (self.CALLOUT.match(lines[0]) is not None)
|
||||||
|
block = '\n'.join(lines)
|
||||||
|
if callout:
|
||||||
|
self.callout_block(parent, lines)
|
||||||
|
else:
|
||||||
|
self.normal_blockquote(parent, block)
|
||||||
|
|
||||||
|
def extendMarkdown(self, md) -> None:
|
||||||
|
md.parser.blockprocessors.register(ObsidianStyleBlockquotes.ObsidianBlockQuote(md.parser), 'quote', 20)
|
||||||
|
|
||||||
|
|
||||||
def create_markdown_parser(context: Context) -> markdown.Markdown:
|
def create_markdown_parser(context: Context) -> markdown.Markdown:
|
||||||
"""
|
"""
|
||||||
Creates a Markdown parser with all our extensions loaded.
|
Creates a Markdown parser with all our extensions loaded.
|
||||||
|
@ -887,6 +952,7 @@ def create_markdown_parser(context: Context) -> markdown.Markdown:
|
||||||
MetaStripper(),
|
MetaStripper(),
|
||||||
ObsidianComments(),
|
ObsidianComments(),
|
||||||
ObsidianStyleFootnotes(SUPERSCRIPT_TEXT='[{}]', SEPARATOR='-'),
|
ObsidianStyleFootnotes(SUPERSCRIPT_TEXT='[{}]', SEPARATOR='-'),
|
||||||
|
ObsidianStyleBlockquotes(),
|
||||||
ObsidianImages(context),
|
ObsidianImages(context),
|
||||||
ObsidianLinks(context),
|
ObsidianLinks(context),
|
||||||
ObsidianLists(),
|
ObsidianLists(),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user