Files
rendercv/tests/renderer/templater/test_markdown_parser.py
Sina Atalay 5cc5fbdf9e Massive Refactor: Architecture Redesign and Technical Debt Cleanup (#528)
* Rename `data` folder with schema

* Start refactoring data models

* Work on entry models

* Keep working on entries

* Keep working on data models

* Push old data files

* Keep working on data models

* First draft of schema.cv

* Keep working on schema

* Keep working on schema

* Improve schema.models

* Keep working on rendercv.schema

* Work on schema.design

* Keep working on rendercv.schema

* Complete variant_class_generator

* Keep working rendercv.schema

* Keep working on rendercv.schema

* Final touches to rendercv.schema

* Improve json schema descriptions in rendercv.schema

* Start working on rendercv.schema tests

* Keep implementing rendercv.schema tests

* Add more tests for rendercv.schema

* Improve rendercv.schema

* Improve docstrings and comments in rendercv.schema

* Implement better pydantic error handling in `rendercv.schema`

* Improve variant class system

* Fix rendercv.schema tests

* Start working on rendercv.templater

* Update template names

* Switching to new rendercv typst template soon

* Work on new templater

* Rename renderer with renderer_old

* Don't use utils in rendercv.schema

* Complete connections

* Update renderer folder structure

* Work on new renderer

* Work on new renderer

* Date processing on new renderer

* Improve date processing, support multiple emails, phones, and websites

* Improve markdown to Typst

* Complete entry template processing

* Time span computation in new renderer

* Better entry templates

* Setup new templates

* Improve rendercv.schema

* Start adding tests for rendercv.renderer

* New markdown parser!

* Improve markdown to typst conversion

* Finalize markdown parser

* Add new test files for rendercv.renderer

* Fix cv and connections

* Add connections test

* Improve connection tests

* Improve entry templates

* Add model processor tests

* Improve templater

* Rename old folders

* Improve schema

* Add file generation logic to renderer

* Fix naming issues

* Fix schema tests

* Add path type tests

* Add font family and typst dimension type tests

* Rename old tests

* Fix design tests

* Start integration testing of renderer

* Improve entry tempates

* Handle nested highlights properly

* Finalize Typst preamble template

* Start working on new CLI

* Remove old test files

* Implement override dictionary in new schema

* Start working on new CLI

* Better prints on render command

* New structure

* New render printer

* Add all the commands to new CLI

* Work on new command in new cli

* Improve new command

* Add error handler to new cli

* Work on create theme command

* Complete create theme command

* Remove old source files

* Improve exceptions

* Create new docs

* Add writing tests guide

* Fix cli printer and write tests

* Test copy templates

* Add app tests

* Bring back accidentally removed files

* Imporve cli and tests

* Fix path issues

* Improve

* Improve

* Add reference file comparison tests

* Fix path resolver

* Start working on test_pdf_png

* Implement comparison of multiple files (png)

* Start testing typst

* Fix templating issues

* Fix header and entry templates issues

* Implement short second rows

* Fix date issues

* Fix nested bullets and add summary

* Update testdata

* Implement footer

* Update testdata

* Reimagined design and locale schema, first iteration

* Reimagined design and locale second iteration

* Update design and locale schemas

* Adapt templater to the new design and locale

* Fix tests

* Update lib.typ and testdata for the new locale and design

* Implement proper tests with all combinations of entries

* Remove some docstrings

* fix connections logic

* Improve

* Start working on examples

* Update testdata

* Fix long second row issue

* fix templating issues

* Fix lib.typ issues

* Update testdata

* Fix clean_trailing_parts

* Update test cv

* update test cv

* Update theme defaults

* update schema and fix moderncv

* Fix moderncv issues

* Update testdata

* Update testdata and examples

* Fix issues about photo

* Fix typst photo path issues

* improve entry templates from yaml

* add new locale

* Rename writing tests doc

* Update writing tests

* Improve tests

* Add more cli tests

* Increase test coverage

* Rename variant pydantic model generator

* Improve tests

* Update testdata and improve tests

* Format, fix pre-commit errors

* Fix scripts and update entry figures

* Improve tests

* Write docstrings of schema

* Write schema docstrings

* Setup api reference

* Start working on new docs

* Work on docs

* Improve progress panel of render command

* Finalize new docs index

* Complete CLI docs

* Work on YAML input structure page

* Finalize user guide

* Start working on developer guide

* Improve api reference

* Improve developer guide

* Improve developer guide

* Improve developer gide

* Improve developer guide

* Improve developer guide

* Update developer guide

* Improve developer guide

* Improve developer guide

* Improve developer guide

* Developer guide first draft

* update developer guide

* Update examples

* Update testdata

* Handle wrong installation (rendercv instead of rendercv[full])

* Remove unnecessary files

* Write set up vs code page

* Update README.md

* Change docs description

* Compress design options gif

* minor updates

* Polish all the json schema descriptions

* Update testdata and examples

* Remove some emdashed from docs

* Add whatsapp support

* Add TestEscapeTypstCharacters to tests

* Implement custom connections

* Add page break before sections feature

* Revert page break before sections feature

* Rebase to main

* Fix social network tests, update schema
2025-12-09 17:03:56 +03:00

188 lines
6.2 KiB
Python

import pytest
from rendercv.renderer.templater.markdown_parser import (
escape_typst_characters,
markdown_to_html,
markdown_to_typst,
)
class TestEscapeTypstCharacters:
def test_returns_newline_unchanged(self):
assert escape_typst_characters("\n") == "\n"
@pytest.mark.parametrize(
("string", "expected"),
[
("#", r"\#"),
("$", r"\$"),
("[", r"\["),
("]", r"\]"),
("\\", r"\\"),
('"', r"\""),
("@", r"\@"),
("%", r"\%"),
("~", r"\~"),
("_", r"\_"),
("/", r"\/"),
(">", r"\>"),
("<", r"\<"),
],
)
def test_escapes_typst_special_characters(self, string, expected):
assert escape_typst_characters(string) == expected
@pytest.mark.parametrize(
("string", "expected"),
[
("* test", "#sym.ast.basic test"),
("*test", "#sym.ast.basic#h(0pt, weak: true) test"),
],
)
def test_replaces_asterisks_with_typst_symbols(self, string, expected):
assert escape_typst_characters(string) == expected
def test_preserves_typst_commands_while_escaping_outside(self):
string = "Keep #emph[a_b] but escape 5% and _"
expected = "Keep #emph[a_b] but escape 5\\% and \\_"
assert escape_typst_characters(string) == expected
def test_preserves_math_blocks(self):
string = "$$a*b + c$$ and #1"
expected = "$a*b + c$ and \\#1"
assert escape_typst_characters(string) == expected
@pytest.mark.parametrize(
("markdown_string", "expected_typst_string"),
[
("plain", "plain"),
("**b**", "#strong[b]"),
("*i*", "#emph[i]"),
("***x***", "#strong[#emph[x]]"),
("`c`", "`c`"),
("[x](https://myurl.com)", '#link("https://myurl.com")[x]'),
(
"[**b** *i* ***bi*** `c`](https://myurl.com)",
'#link("https://myurl.com")[#strong[b] #emph[i] #strong[#emph[bi]] `c`]',
),
("**a *b* c**", "#strong[a #emph[b] c]"),
(
"quote*",
"quote#sym.ast.basic#h(0pt, weak: true)",
),
(
"asteri*sks",
"asteri#sym.ast.basic#h(0pt, weak: true) sks",
),
(
"* test",
"#sym.ast.basic test",
),
(
"*test",
"#sym.ast.basic#h(0pt, weak: true) test",
),
(
r"\*'s",
"#sym.ast.basic#h(0pt, weak: true) 's",
),
(
r"\* x",
"#sym.ast.basic x",
),
(
r"\*.x",
"#sym.ast.basic#h(0pt, weak: true) .x",
),
(
r"\*\*bold\*\*",
(
"#sym.ast.basic#h(0pt, weak: true) "
"#sym.ast.basic#h(0pt, weak: true) "
"bold#sym.ast.basic#h(0pt, weak: true) "
"#sym.ast.basic#h(0pt, weak: true)"
),
),
# Typst commands should be preserved
(
"#test-typst-command[argument]",
"#test-typst-command[argument]",
),
(
"#test-typst-command",
"#test-typst-command",
),
(
"#test-typst-command(a, b)",
"#test-typst-command(a, b)",
),
(
"#test-typst-command(a, b)[c, d]",
"#test-typst-command(a, b)[c, d]",
),
# things that look like commands but aren't:
("#1", r"\#1"),
("I made $100", r"I made \$100"),
# inside math: no escaping, keep everything as is:
(
r"$$a*b * c #cmd[x]$$",
r"$a*b * c #cmd[x]$",
),
("My # Text", "My \\# Text"),
("My % Text", "My \\% Text"),
("My ~ Text", "My \\~ Text"),
("My _ Text", "My \\_ Text"),
("My $ Text", "My \\$ Text"),
("My [ Text", "My \\[ Text"),
("My ] Text", "My \\] Text"),
("My \\ Text", "My \\\\ Text"),
('My " Text', 'My \\" Text'),
("My @ Text", "My \\@ Text"),
(
"[link_test#](Shouldn't be escaped in here & % # ~)",
'#link("Shouldn\'t be escaped in here & % # ~")[link\\_test\\#]',
),
(
"$$a=5_4^3 % & #$$ # $$aaaa ___ &&$$",
"$a=5_4^3 % & #$ \\# $aaaa ___ &&$",
),
("60%", "60\\%"),
(
(
"!!! summary\n"
" Did #emph[this] and this is a #strong[bold]"
' #link("https://example.com")[link]. But I must explain to you how all'
" this mistaken idea of denouncing pleasure and praising pain was born"
" and I will give you a complete account of the system, and expound the"
" actual teachings of the great explorer of the truth, the"
" master-builder of human happiness. No one rejects, dislikes, or"
" avoids pleasure itself, because it is pleasure, but because those who"
" do not know how to pursue pleasure rationally encounter consequences"
" that are extremely painful."
),
(
"#summary[Did #emph[this] and this is a #strong[bold]"
' #link("https://example.com")[link]. But I must explain to you how all'
" this mistaken idea of denouncing pleasure and praising pain was born"
" and I will give you a complete account of the system, and expound the"
" actual teachings of the great explorer of the truth, the"
" master-builder of human happiness. No one rejects, dislikes, or"
" avoids pleasure itself, because it is pleasure, but because those who"
" do not know how to pursue pleasure rationally encounter consequences"
" that are extremely painful.]"
),
),
],
)
def test_markdown_to_typst(markdown_string, expected_typst_string):
assert markdown_to_typst(markdown_string) == expected_typst_string
def test_markdown_to_html():
assert (
markdown_to_html("Hello, **world**!") == "<p>Hello, <strong>world</strong>!</p>"
)