Skip to content
This repository was archived by the owner on Nov 2, 2023. It is now read-only.

Commit b95edce

Browse files
committed
Merge remote-tracking branch 'math-fork/feature/md-equations'
2 parents 4aca849 + 18a73b0 commit b95edce

File tree

4 files changed

+87
-7
lines changed

4 files changed

+87
-7
lines changed

md2notion/NotionPyRenderer.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
from collections.abc import Iterable
55
from notion.block import CodeBlock, DividerBlock, HeaderBlock, SubheaderBlock, \
66
SubsubheaderBlock, QuoteBlock, TextBlock, NumberedListBlock, \
7-
BulletedListBlock, ImageBlock, CollectionViewBlock, TodoBlock
7+
BulletedListBlock, ImageBlock, CollectionViewBlock, TodoBlock, EquationBlock
88
from mistletoe.base_renderer import BaseRenderer
9-
from mistletoe.block_token import HTMLBlock
10-
from mistletoe.span_token import Image, Link, HTMLSpan
9+
from mistletoe.block_token import HTMLBlock, CodeFence
10+
from mistletoe.span_token import Image, Link, HTMLSpan, SpanToken
1111
from html.parser import HTMLParser
1212

1313
def flatten(l):
@@ -28,6 +28,16 @@ def newNotionPyRendererCls(*extraExtensions):
2828
return notionPyRendererCls(*chain(new_extension, extraExtensions))
2929
return newNotionPyRendererCls
3030

31+
def addLatexExtension(notionPyRendererCls):
32+
"""A decorator that add the latex extensions to the argument list.
33+
Markdown such as $equation$ is parsed as inline-equations and
34+
$$equation$$ is parsed as an equation block.
35+
"""
36+
def newNotionPyRendererCls(*extraExtensions):
37+
new_extension = [BlockEquation, InlineEquation]
38+
return notionPyRendererCls(*chain(new_extension, extraExtensions))
39+
return newNotionPyRendererCls
40+
3141
class NotionPyRenderer(BaseRenderer):
3242
"""
3343
A class that will render out a Markdown file into a descriptor for upload
@@ -399,3 +409,24 @@ def render_html_block(self, token):
399409
def render_html_span(self, token):
400410
assert not hasattr(token, "children")
401411
return self.render_html(token)
412+
413+
def render_block_equation(self, token):
414+
def blockFunc(blockStr):
415+
return {
416+
'type': EquationBlock,
417+
'title': blockStr.replace('\\', '\\\\')
418+
}
419+
return self.renderMultipleToStringAndCombine(token.children, blockFunc)
420+
421+
def render_inline_equation(self, token):
422+
return self.renderMultipleToStringAndCombine(token.children, lambda s: f"$${s}$$")
423+
424+
425+
class InlineEquation(SpanToken):
426+
pattern = re.compile(r"(?<!\\|\$)(?:\\\\)*(\$+)(?!\$)(.+?)(?<!\$)\1(?!\$)", re.DOTALL)
427+
parse_inner = True
428+
parse_group = 2
429+
430+
431+
class BlockEquation(CodeFence):
432+
pattern = re.compile(r'( {0,3})((?:\$){2,}) *(\S*)')

md2notion/upload.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
import mistletoe
1111
from notion.block import EmbedOrUploadBlock, CollectionViewBlock, PageBlock
1212
from notion.client import NotionClient
13-
from .NotionPyRenderer import NotionPyRenderer, addHtmlImgTagExtension
13+
from .NotionPyRenderer import NotionPyRenderer, addHtmlImgTagExtension, addLatexExtension
14+
1415

1516
def relativePathForMarkdownUrl(url, mdFilePath):
1617
"""
@@ -181,12 +182,16 @@ def cli(argv):
181182
parser.set_defaults(mode='create')
182183
parser.add_argument('--html-img', action='store_true', default=False,
183184
help="Upload images in HTML <img> tags (disabled by default)")
185+
parser.add_argument('--latex', action='store_true', default=False,
186+
help="Support for latex inline ($..$) and block ($$..$$) equations (disabled by default)")
184187

185188
args = parser.parse_args(argv)
186189

187190
notionPyRendererCls = NotionPyRenderer
188191
if args.html_img:
189192
notionPyRendererCls = addHtmlImgTagExtension(notionPyRendererCls)
193+
if args.latex:
194+
notionPyRendererCls = addLatexExtension(notionPyRendererCls)
190195

191196
print("Initializing Notion.so client...")
192197
client = NotionClient(token_v2=args.token_v2)

tests/test_NotionPyRenderer.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import re
55
import mistletoe
66
import notion
7-
from md2notion.NotionPyRenderer import NotionPyRenderer, addHtmlImgTagExtension
7+
from md2notion.NotionPyRenderer import NotionPyRenderer, addHtmlImgTagExtension, addLatexExtension
88

99
def test_header(capsys, headerLevel):
1010
'''it renders a range of headers, warns if it cant render properly'''
@@ -126,7 +126,7 @@ def test_imageBlockText():
126126
def test_imageInHtml():
127127
'''it should render an image that is mentioned in the html <img> tag'''
128128
#arrange/act
129-
output = mistletoe.markdown("head<img src=\"https://via.placeholder.com/500\" />tail",
129+
output = mistletoe.markdown("head<img src=\"https://via.placeholder.com/500\" />tail",
130130
addHtmlImgTagExtension(NotionPyRenderer))
131131

132132
#assert
@@ -157,7 +157,37 @@ def test_imageInHtmlBlock():
157157
assert output[1]['caption'] == "ImCaption"
158158
assert isinstance(output[2], dict)
159159
assert output[2]['type'] == notion.block.TextBlock
160-
assert output[2]['title'] == "tail"
160+
assert output[2]['title'] == "tail"
161+
162+
def test_latex_inline():
163+
output = mistletoe.markdown(r"""
164+
# Test for latex blocks
165+
Text before $f(x) = \sigma(w \cdot x + b)$ Text after
166+
""", addLatexExtension(NotionPyRenderer))
167+
168+
assert output[1] is not None
169+
assert output[1]['type'] == notion.block.TextBlock
170+
assert output[1]['title'] == r'Text before $$f(x) = \sigma(w \cdot x + b)$$ Text after'
171+
172+
173+
def test_latex_block():
174+
output = mistletoe.markdown(r"""
175+
# Test for latex blocks
176+
Text before
177+
178+
$$
179+
f(x) = \sigma(w \cdot x + b)
180+
$$
181+
182+
Text after
183+
""", addLatexExtension(NotionPyRenderer))
184+
185+
assert output[2] is not None
186+
assert output[2]['type'] == notion.block.EquationBlock
187+
assert output[2]['title'] == 'f(x) = \\\\sigma(w \\\\cdot x + b)\n'
188+
189+
def test_cli_latex_extension():
190+
pass
161191

162192
def test_escapeSequence():
163193
'''it should render out an escape sequence'''

tests/test_upload.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,17 @@ def test_cli_html_img_tag(mockClient, upload):
325325
renderer = args0[3]()
326326
assert "HTMLSpan" in renderer.render_map
327327
assert "HTMLBlock" in renderer.render_map
328+
329+
@patch('md2notion.upload.upload')
330+
@patch('md2notion.upload.NotionClient', new_callable=MockClient)
331+
def test_cli_latex(mockClient, upload):
332+
'''should enable the extension'''
333+
334+
#act
335+
cli(['token_v2', 'page_url', 'tests/TEST.md', '--append', '--latex'])
336+
337+
#assert
338+
args0, kwargs0 = upload.call_args
339+
renderer = args0[3]()
340+
assert "InlineEquation" in renderer.render_map
341+
assert "BlockEquation" in renderer.render_map

0 commit comments

Comments
 (0)