mirror of
https://github.com/vale981/recommonmark
synced 2025-03-05 10:01:39 -05:00
refactor code block highlight to transform, add support for math latex
This commit is contained in:
parent
699d13dd76
commit
fc62292ad9
2 changed files with 80 additions and 37 deletions
|
@ -4,7 +4,6 @@ import itertools
|
|||
from docutils import parsers, nodes, utils
|
||||
|
||||
from docutils.parsers.rst import roles, states
|
||||
from docutils.utils.code_analyzer import Lexer, LexerError
|
||||
|
||||
from CommonMark import DocParser, HTMLRenderer
|
||||
from warnings import warn
|
||||
|
@ -123,32 +122,7 @@ class CommonMarkParser(parsers.Parser):
|
|||
self.current_node.append(verbatim_node)
|
||||
|
||||
def code(self, language, text):
|
||||
classes = ['code', 'highlight']
|
||||
|
||||
# embedded rst in codeblocks
|
||||
if language == 'eval_rst':
|
||||
rst_parser = parsers.rst.Parser()
|
||||
rst_parser.parse(text, self.current_node.document)
|
||||
return
|
||||
|
||||
if language:
|
||||
classes.append(language)
|
||||
|
||||
try:
|
||||
tokens = Lexer(utils.unescape(text, 1), language, True)
|
||||
except LexerError as error:
|
||||
raise error
|
||||
|
||||
node = nodes.literal_block(text, '', classes=classes)
|
||||
|
||||
# analyze content and add nodes for every token
|
||||
for classes, value in tokens:
|
||||
if classes:
|
||||
node += nodes.inline(value, value, classes=classes)
|
||||
else:
|
||||
# insert as Text to decrease the verbosity of the output
|
||||
node += nodes.Text(value, value)
|
||||
|
||||
node = nodes.literal_block(text, '', language=language)
|
||||
self.current_node.append(node)
|
||||
|
||||
def paragraph(self, block):
|
||||
|
|
|
@ -3,6 +3,7 @@ import os
|
|||
import sys
|
||||
from states import DummyStateMachine
|
||||
from docutils import nodes, transforms
|
||||
from docutils.statemachine import StringList
|
||||
|
||||
class AutoStructify(transforms.Transform):
|
||||
"""Automatically try to transform blocks to sphinx directives.
|
||||
|
@ -162,27 +163,95 @@ class AutoStructify(transforms.Transform):
|
|||
node['refuri'] = uri
|
||||
return None
|
||||
|
||||
def auto_code_block(self, node):
|
||||
"""Try to automatically generate nodes for codeblock syntax.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
node : nodes.literal_block
|
||||
Original codeblock node
|
||||
Returns
|
||||
-------
|
||||
tocnode: docutils node
|
||||
The converted toc tree node, None if conversion is not possible.
|
||||
"""
|
||||
|
||||
assert isinstance(node, nodes.literal_block)
|
||||
if 'language' not in node:
|
||||
return None
|
||||
self.state_machine.reset(self.document,
|
||||
node.parent,
|
||||
self.current_level)
|
||||
content = node.rawsource.split('\n')
|
||||
language = node['language']
|
||||
if language == 'math':
|
||||
return self.state_machine.run_directive(
|
||||
'math', content=content)
|
||||
elif language == 'eval_rst':
|
||||
# allow embed non section level rst
|
||||
node = nodes.section()
|
||||
self.state_machine.state.nested_parse(
|
||||
StringList(content, source=node.rawsource),
|
||||
0, node=node, match_titles=False)
|
||||
return node.children[:]
|
||||
# embedded rst in codeblocks
|
||||
if language == 'eval_rst':
|
||||
rst_parser = parsers.rst.Parser()
|
||||
rst_parser.parse(text, self.current_node.document)
|
||||
return
|
||||
return None
|
||||
else:
|
||||
return self.state_machine.run_directive(
|
||||
'code-block', arguments=[language],
|
||||
content=content)
|
||||
|
||||
def find_replace(self, node):
|
||||
"""Try to find replace node for current node.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
node : docutil node
|
||||
Node to find replacement for.
|
||||
|
||||
Returns
|
||||
-------
|
||||
nodes : node or list of node
|
||||
The replacement nodes of current node.
|
||||
Returns None if no replacement can be found.
|
||||
"""
|
||||
newnode = None
|
||||
if isinstance(node, nodes.Sequential):
|
||||
newnode = self.auto_toc_tree(node)
|
||||
elif isinstance(node, nodes.reference):
|
||||
newnode = self.auto_doc_ref(node)
|
||||
elif isinstance(node, nodes.literal_block):
|
||||
newnode = self.auto_code_block(node)
|
||||
return newnode
|
||||
|
||||
def traverse(self, node):
|
||||
"""Traverse the document tree rooted at node.
|
||||
|
||||
node : docutil node
|
||||
current root node to traverse
|
||||
"""
|
||||
newnode = None
|
||||
old_level = self.current_level
|
||||
if isinstance(node, nodes.section):
|
||||
if 'level' in node:
|
||||
self.current_level = node['level']
|
||||
elif isinstance(node, nodes.Sequential):
|
||||
newnode = self.auto_toc_tree(node)
|
||||
elif isinstance(node, nodes.reference):
|
||||
newnode = self.auto_doc_ref(node)
|
||||
to_visit = []
|
||||
to_replace = []
|
||||
for c in node.children[:]:
|
||||
newnode = self.find_replace(c)
|
||||
if newnode is not None:
|
||||
to_replace.append((c, newnode))
|
||||
else:
|
||||
to_visit.append(c)
|
||||
|
||||
if newnode:
|
||||
node.replace_self(newnode)
|
||||
else:
|
||||
for c in node.children[:]:
|
||||
self.traverse(c)
|
||||
for oldnode, newnodes in to_replace:
|
||||
node.replace(oldnode, newnodes)
|
||||
|
||||
for child in to_visit:
|
||||
self.traverse(child)
|
||||
self.current_level = old_level
|
||||
|
||||
def apply(self):
|
||||
|
|
Loading…
Add table
Reference in a new issue