Skip to content

Commit

Permalink
Add extension options
Browse files Browse the repository at this point in the history
  • Loading branch information
digitalmoksha committed Mar 21, 2024
1 parent 354ecf6 commit dd46394
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 74 deletions.
2 changes: 2 additions & 0 deletions examples/s-expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ fn dump(source: &str) -> io::Result<()> {
.footnotes(true)
.description_lists(true)
.multiline_block_quotes(true)
.math_dollars(true)
.math_code(true)
.build()
.unwrap();

Expand Down
2 changes: 2 additions & 0 deletions fuzz/fuzz_targets/all_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ fuzz_target!(|s: &str| {
extension.footnotes = true;
extension.description_lists = true;
extension.multiline_block_quotes = true;
extension.math_dollars = true;
extension.math_code = true;
extension.front_matter_delimiter = Some("---".to_string());
extension.shortcodes = true;

Expand Down
4 changes: 4 additions & 0 deletions fuzz/fuzz_targets/quadratic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ struct FuzzExtensionOptions {
footnotes: bool,
description_lists: bool,
multiline_block_quotes: bool,
math_dollars: bool,
math_code: bool,
shortcodes: bool,
}

Expand All @@ -208,6 +210,8 @@ impl FuzzExtensionOptions {
extension.footnotes = self.footnotes;
extension.description_lists = self.description_lists;
extension.multiline_block_quotes = self.multiline_block_quotes;
extension.math_dollars = self.math_dollars;
extension.math_code = self.math_code;
extension.shortcodes = self.shortcodes;
extension.front_matter_delimiter = None;
extension.header_ids = None;
Expand Down
46 changes: 23 additions & 23 deletions script/cibuild
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,29 @@ if [ x"$SPEC" = "xtrue" ]; then
PROGRAM_ARG="--program=../../../target/release/comrak --syntax-highlighting none"

set +e
# python3 spec_tests.py --no-normalize --spec spec.txt "$PROGRAM_ARG" \
# || failed=1
# python3 pathological_tests.py "$PROGRAM_ARG" \
# || failed=1
# python3 roundtrip_tests.py --spec spec.txt "$PROGRAM_ARG" \
# || failed=1
# python3 entity_tests.py "$PROGRAM_ARG" \
# || failed=1
# python3 spec_tests.py --no-normalize --spec smart_punct.txt "$PROGRAM_ARG --smart" \
# || failed=1
#
# python3 spec_tests.py --no-normalize --spec extensions.txt "$PROGRAM_ARG" --extensions "table strikethrough autolink tagfilter footnotes tasklist" \
# || failed=1
# python3 roundtrip_tests.py --spec extensions.txt "$PROGRAM_ARG" --extensions "table strikethrough autolink tagfilter footnotes tasklist" \
# || failed=1
# # python3 roundtrip_tests.py --spec extensions-table-prefer-style-attributes.txt "$PROGRAM_ARG --table-prefer-style-attributes" --extensions "table strikethrough autolink tagfilter footnotes tasklist" || failed=1
# python3 roundtrip_tests.py --spec extensions-full-info-string.txt "$PROGRAM_ARG --full-info-string" \
# || failed=1
# python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/multiline_blockquote.txt "$PROGRAM_ARG -e multiline-block-quotes" \
# || failed=1
# python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/math_dollars.txt "$PROGRAM_ARG -e multiline-block-quotes" \
# || failed=1
python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/math_code.txt "$PROGRAM_ARG -e multiline-block-quotes" \
python3 spec_tests.py --no-normalize --spec spec.txt "$PROGRAM_ARG" \
|| failed=1
python3 pathological_tests.py "$PROGRAM_ARG" \
|| failed=1
python3 roundtrip_tests.py --spec spec.txt "$PROGRAM_ARG" \
|| failed=1
python3 entity_tests.py "$PROGRAM_ARG" \
|| failed=1
python3 spec_tests.py --no-normalize --spec smart_punct.txt "$PROGRAM_ARG --smart" \
|| failed=1

python3 spec_tests.py --no-normalize --spec extensions.txt "$PROGRAM_ARG" --extensions "table strikethrough autolink tagfilter footnotes tasklist" \
|| failed=1
python3 roundtrip_tests.py --spec extensions.txt "$PROGRAM_ARG" --extensions "table strikethrough autolink tagfilter footnotes tasklist" \
|| failed=1
# python3 roundtrip_tests.py --spec extensions-table-prefer-style-attributes.txt "$PROGRAM_ARG --table-prefer-style-attributes" --extensions "table strikethrough autolink tagfilter footnotes tasklist" || failed=1
python3 roundtrip_tests.py --spec extensions-full-info-string.txt "$PROGRAM_ARG --full-info-string" \
|| failed=1
python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/multiline_blockquote.txt "$PROGRAM_ARG -e multiline-block-quotes" \
|| failed=1
python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/math_dollars.txt "$PROGRAM_ARG -e math-dollars" \
|| failed=1
python3 spec_tests.py --no-normalize --spec ../../../src/tests/fixtures/math_code.txt "$PROGRAM_ARG -e math-code" \
|| failed=1

python3 spec_tests.py --no-normalize --spec regression.txt "$PROGRAM_ARG" \
Expand Down
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ enum Extension {
Footnotes,
DescriptionLists,
MultilineBlockQuotes,
MathDollars,
MathCode,
}

#[derive(Clone, Copy, Debug, ValueEnum)]
Expand Down Expand Up @@ -212,6 +214,8 @@ fn main() -> Result<(), Box<dyn Error>> {
.footnotes(exts.contains(&Extension::Footnotes))
.description_lists(exts.contains(&Extension::DescriptionLists))
.multiline_block_quotes(exts.contains(&Extension::MultilineBlockQuotes))
.math_dollars(exts.contains(&Extension::MathDollars))
.math_code(exts.contains(&Extension::MathCode))
.front_matter_delimiter(cli.front_matter_delimiter);

#[cfg(feature = "shortcodes")]
Expand Down
15 changes: 12 additions & 3 deletions src/parser/inlines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
'^' if self.options.extension.superscript && !self.within_brackets => {
Some(self.handle_delim(b'^'))
}
'$' => Some(self.handle_dollars()),
'$' if self.options.extension.math_dollars || self.options.extension.math_code => {
Some(self.handle_dollars())
}
_ => {
let endpos = self.find_special_char();
let mut contents = self.input[self.pos..endpos].to_vec();
Expand Down Expand Up @@ -628,6 +630,10 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
opendollarlength: usize,
code_math: bool,
) -> Option<usize> {
if !(self.options.extension.math_dollars || self.options.extension.math_code) {
return None;
}

if opendollarlength > MAX_MATH_DOLLARS {
return None;
}
Expand Down Expand Up @@ -660,7 +666,7 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
self.pos += 1;
return Some(self.pos);
} else {
// self.pos += 1;
self.pos += 1;
}
} else {
// dollar signs must also be backslash-escaped if they occur within math
Expand Down Expand Up @@ -690,7 +696,10 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
let mut code_math = false;

// check for code math
if opendollars == 1 && self.peek_char().map_or(false, |&c| c == b'`') {
if opendollars == 1
&& self.options.extension.math_code
&& self.peek_char().map_or(false, |&c| c == b'`')
{
code_math = true;
self.pos += 1;
}
Expand Down
43 changes: 43 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,48 @@ pub struct ExtensionOptions {
/// ```
pub multiline_block_quotes: bool,

/// Enables math using dollar syntax.
///
/// ``` md
/// Inline math $1 + 2$ and display math $$x + y$$
///
/// $$
/// x^2
/// $$
/// ```
///
/// ```
/// # use comrak::{markdown_to_html, Options};
/// let mut options = Options::default();
/// options.extension.math_dollars = true;
/// assert_eq!(markdown_to_html("$1 + 2$ and $$x = y$$", &options),
/// "<p><code data-math-style=\"inline\">1 + 2</code> and <code data-math-style=\"display\">x = y</code></p>\n");
/// assert_eq!(markdown_to_html("$$\nx^2\n$$\n", &options),
/// "<pre><code class=\"language-math\" data-math-style=\"display\">x^2\n</code></pre>\n");
/// ```
pub math_dollars: bool,

/// Enables math using code syntax.
///
/// ```` md
/// Inline math $`1 + 2`$
///
/// ```math
/// x^2
/// ```
/// ````
///
/// ```
/// # use comrak::{markdown_to_html, Options};
/// let mut options = Options::default();
/// options.extension.math_code = true;
/// assert_eq!(markdown_to_html("$`1 + 2`$", &options),
/// "<p><code data-math-style=\"inline\">1 + 2</code></p>\n");
/// assert_eq!(markdown_to_html("```math\nx^2\n```\n", &options),
/// "<pre><code class=\"language-math\" data-math-style=\"display\">x^2\n</code></pre>\n");
/// ```
pub math_code: bool,

#[cfg(feature = "shortcodes")]
#[cfg_attr(docsrs, doc(cfg(feature = "shortcodes")))]
/// Phrases wrapped inside of ':' blocks will be replaced with emojis.
Expand Down Expand Up @@ -1123,6 +1165,7 @@ impl<'a, 'o, 'c> Parser<'a, 'o, 'c> {
);
self.advance_offset(line, first_nonspace + matched - offset, false);
} else if !indented
&& self.options.extension.math_dollars
&& unwrap_into(
scanners::open_math_fence(&line[self.first_nonspace..]),
&mut matched,
Expand Down
3 changes: 3 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod description_lists;
mod footnotes;
mod fuzz;
mod header_ids;
mod math;
mod multiline_block_quotes;
mod options;
mod pathological;
Expand Down Expand Up @@ -119,6 +120,8 @@ macro_rules! html_opts {
footnotes: true,
description_lists: true,
multiline_block_quotes: true,
math_dollars: true,
math_code: true,
front_matter_delimiter: Some("---".to_string()),
shortcodes: true,
},
Expand Down
2 changes: 2 additions & 0 deletions src/tests/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ fn exercise_full_api() {
extension.footnotes(false);
extension.description_lists(false);
extension.multiline_block_quotes(false);
extension.math_dollars(false);
extension.math_code(false);
extension.front_matter_delimiter(None);
#[cfg(feature = "shortcodes")]
extension.shortcodes(true);
Expand Down
70 changes: 22 additions & 48 deletions src/tests/fixtures/math_code.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,78 +19,52 @@ x=y + 2
</code></pre>
````````````````````````````````

In inline math, the opening `$` must not be followed by
a whitespace, and the closing `$` must not be
preceeded by whitespace.

```````````````````````````````` example
This is not math: 2000$.
And neither is this $ 4 $.
Or this $4
$.
.
<p>This is not math: 2000$.
And neither is this $ 4 $.
Or this $4
$.</p>
````````````````````````````````

Display math delimiters can be surrounded by whitespace:
In inline math, it behaves just like inline code.

```````````````````````````````` example
This is display math:
$$
e=mc^2
$$
This is math:$`2000`$.
.
<p>This is display math:</p>
<pre><code class="language-math" data-math-style="display">e=mc^2
</code></pre>
<p>This is math:<code data-math-style="inline">2000</code>.</p>
````````````````````````````````


Note that math can contain embedded math. In scanning
for a closing delimiter, we skip material in balanced
for a closing delimiter, we do not need to skip material in balanced
curly braces:

```````````````````````````````` example disabled
```````````````````````````````` example
This is display math:
$$

```math
\text{Hello $x^2$}
$$
```
And this is inline math:
$\text{Hello $x$ there!}$
$`\text{Hello $x$ there!}`$
.
<p>This is display math:
<span class="math display">\[
\text{Hello $x^2$}
\]</span>
And this is inline math:
<span class="math inline">\(\text{Hello $x$ there!}\)</span></p>
<p>This is display math:</p>
<pre><code class="language-math" data-math-style="display">\text{Hello $x^2$}
</code></pre>
<p>And this is inline math:
<code data-math-style="inline">\text{Hello $x$ there!}</code></p>
````````````````````````````````


To avoid treating currency signs as math delimiters,
one may occasionally have to backslash-escape them:
Dollar signs not required to be backslashed. It may be
required to render the math properly, but it's not required
for parsing:

```````````````````````````````` example
The cost is between \$10 and 30$.
$`\text{$}`$
.
<p>The cost is between $10 and 30$.</p>
````````````````````````````````

Dollar signs must also be backslash-escaped if they
occur within math:

```````````````````````````````` example
$\text{\$}$
.
<p><code data-math-style="inline">\text{\$}</code></p>
<p><code data-math-style="inline">\text{$}</code></p>
````````````````````````````````

Everything inside the math construction is treated
as math, and not given its normal commonmark meaning.

```````````````````````````````` example
$b<a>c$
$`b<a>c`$
.
<p><code data-math-style="inline">b&lt;a&gt;c</code></p>
````````````````````````````````
2 changes: 2 additions & 0 deletions src/tests/propfuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ fn propfuzz_doesnt_crash(md: String) {
footnotes: true,
description_lists: true,
multiline_block_quotes: true,
math_dollars: true,
math_code: true,
front_matter_delimiter: None,
#[cfg(feature = "shortcodes")]
shortcodes: true,
Expand Down

0 comments on commit dd46394

Please sign in to comment.