Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ import markdownItMath from "markdown-it-math";

// Optional (with defaults)
const options = {
inlineDelimiters: ["$", ["$`", "`$"]]
inlineDelimiters: ["$", ["$`", "`$"]],
inlineAllowWhiteSpacePadding: false,
blockDelimiters: "$$",
defaultRendererOptions,
inlineCustomElement, // see below
Expand Down Expand Up @@ -146,6 +147,11 @@ default renderer.
strings or pairs containing empty strings are ignored. If no valid
strings or pairs are provided, it will turn off the rule.
Default ``["$", ["$`", "`$"]]``.
- `inlineAllowWhiteSpacePadding`: Whether to allow whitespace
immediately after the opening delimiter and immediately before the
closing delimiter. You may want this if you use e.g. ``$`...`$`` or
`\(...\)` as delimiters where the risk of non-intended math
expression is low.
- `blockDelimiters`: Same as above, but for block expressions. Default `"$$"`.
- `defaultRendererOptions`: The options passed into the default
renderer. Ignored if you use a custom renderer. Default `{}`
Expand Down Expand Up @@ -299,7 +305,7 @@ const md = markdownIt().use(markdownItMath, {
return temml.renderToString(src);
},

blockDelimiters: [$$, ["\\[", "\\]"]],
blockDelimiters: ["$$", ["\\[", "\\]"]],
blockRenderer(src, token) {
if (token.markup === "$$") {
return mathup(src, { display: "block" }).toString();
Expand Down
33 changes: 25 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ function fromDelimiterOption(delimiters) {
}

/**
* @param {Array<[string, string]>} delimiters
* @param {object} options
* @param {Array<[string, string]>} options.delimiters
* @param {boolean} options.allowWhiteSpacePadding
* @returns {RuleInline}
*/
function createInlineMathRule(delimiters) {
function createInlineMathRule({ delimiters, allowWhiteSpacePadding }) {
return (state, silent) => {
const start = state.pos;

Expand All @@ -76,8 +78,11 @@ function createInlineMathRule(delimiters) {
for (const [open, close] of markers) {
const pos = start + open.length;

if (state.md.utils.isWhiteSpace(state.src.charCodeAt(pos))) {
// Don’t allow whitespace immediately after open delimiter ... for now.
if (
state.md.utils.isWhiteSpace(state.src.charCodeAt(pos)) &&
!allowWhiteSpacePadding
) {
// Don’t allow whitespace immediately after open delimiter
continue;
}

Expand All @@ -88,12 +93,19 @@ function createInlineMathRule(delimiters) {
continue;
}

// Don’t allow whitespace immediately before close delimiter ... for now.
if (state.md.utils.isWhiteSpace(state.src.charCodeAt(matchStart - 1))) {
if (
state.md.utils.isWhiteSpace(state.src.charCodeAt(matchStart - 1)) &&
!allowWhiteSpacePadding
) {
// Don’t allow whitespace immediately before close delimiter
continue;
}

const content = state.src.slice(pos, matchStart).replaceAll("\n", " ");
let content = state.src.slice(pos, matchStart).replaceAll("\n", " ");

if (allowWhiteSpacePadding) {
content = content.replace(/^ (.+) $/, "$1");
}

if (!silent) {
const token = state.push("math_inline", "math", 0);
Expand Down Expand Up @@ -281,6 +293,7 @@ function defaultBlockRenderer(options, md) {
* @property {string} [inlineClose] - Deprecated: Use inlineDelimiters
* @property {CustomElementOption} [inlineCustomElement] - If you want to render to a custom element.
* @property {Renderer} [inlineRenderer] - Custom renderer for inline math. Default mathup.
* @property {boolean} [inlineAllowWhiteSpacePadding] - If you want allow inline math to start or end with whitespace.
* @property {string | Delimiter[]} [blockDelimiters] - Block math delimters.
* @property {string} [blockOpen] - Deprecated: Use blockDelimiters
* @property {string} [blockClose] - Deprecated: Use blockDelimiters
Expand All @@ -295,6 +308,7 @@ export default function markdownItMath(
{
defaultRendererOptions = {},

inlineAllowWhiteSpacePadding = false,
inlineOpen,
inlineClose,
inlineDelimiters = inlineOpen && inlineClose
Expand All @@ -320,7 +334,10 @@ export default function markdownItMath(
) {
const inlineDelimitersArray = fromDelimiterOption(inlineDelimiters);
if (inlineDelimitersArray) {
const inlineMathRule = createInlineMathRule(inlineDelimitersArray);
const inlineMathRule = createInlineMathRule({
delimiters: inlineDelimitersArray,
allowWhiteSpacePadding: inlineAllowWhiteSpacePadding,
});

md.inline.ruler.before("escape", "math_inline", inlineMathRule);

Expand Down
61 changes: 46 additions & 15 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,10 @@ $$
});

suite("Options", () => {
test("Thick dollar delims", (t) => {
test("Thick dollar delims", () => {
const md = markdownIt().use(markdownItMath, {
inlineCustomElement,
blockCustomElement,
inlineDelimiters: "$$",
blockDelimiters: "$$$",
});
Expand All @@ -384,10 +386,13 @@ $$$
$$$
`;

t.assert.snapshot(md.render(src));
assert.equal(
md.render(src),
[p(`Foo ${mathspan("1+1 = 2")} bar`), mathblock("1+1 = 2")].join(""),
);
});

test("No delimiters turns off rules", (t) => {
test("No delimiters turns off rules", () => {
const md = markdownIt().use(markdownItMath, {
inlineDelimiters: "",
blockDelimiters: [],
Expand All @@ -400,13 +405,15 @@ $$
$$
`;

t.assert.snapshot(md.render(src));
assert.equal(md.render(src), p("Foo $1+1 = 2$ bar", "$$\n1+1 = 2\n$$"));
});

test("Empty open or close dilimeters are filtered out", (t) => {
test("Empty open or close dilimeters are filtered out", () => {
const md = markdownIt().use(markdownItMath, {
inlineDelimiters: ["", ["", "$"]],
blockCustomElement,
blockDelimiters: [["$$", ""]],
inlineCustomElement,
inlineDelimiters: ["", ["", "$"]],
});

const src = `Foo $1+1 = 2$ bar
Expand All @@ -416,21 +423,37 @@ $$
$$
`;

t.assert.snapshot(md.render(src));
assert.equal(md.render(src), p("Foo $1+1 = 2$ bar", "$$\n1+1 = 2\n$$"));
});

test("Space dollar delims", (t) => {
test("Space dollar delims", () => {
const md = markdownIt().use(markdownItMath, {
blockCustomElement,
inlineCustomElement,
inlineDelimiters: [["$ ", " $"]],
});

const src = `Foo $ 1+1 = 2 $ bar`;
const src = `foo $ 1+1 = 2 $ bar`;

t.assert.snapshot(md.render(src));
assert.equal(md.render(src), p(`foo ${mathspan("1+1 = 2")} bar`));
});

test("Allow inline space padding", () => {
const md = markdownIt().use(markdownItMath, {
blockCustomElement,
inlineCustomElement,
inlineAllowWhiteSpacePadding: true,
});

const src = "foo $` 1+1 = 2 `$ bar";

assert.equal(md.render(src), p(`foo ${mathspan("1+1 = 2")} bar`));
});

test("LaTeX style delims", (t) => {
test("LaTeX style delims", () => {
const md = markdownIt().use(markdownItMath, {
inlineCustomElement,
blockCustomElement,
inlineDelimiters: [["\\(", "\\)"]],
blockDelimiters: [["\\[", "\\]"]],
});
Expand All @@ -442,7 +465,10 @@ $$
\]
`;

t.assert.snapshot(md.render(src));
assert.equal(
md.render(src),
[p(`Foo ${mathspan("1+1 = 2")} bar`), mathblock("1+1 = 2")].join(""),
);
});

test("Different options for the default renderer", (t) => {
Expand Down Expand Up @@ -538,17 +564,22 @@ $$`;
});

suite("Depricated", () => {
test("inlineOpen inlineClose blockOpen blockClose", (t) => {
const md = markdownIt().use(markdownItMath, {
test("inlineOpen inlineClose blockOpen blockClose", () => {
const mdDepricated = markdownIt().use(markdownItMath, {
inlineOpen: "$((",
inlineClose: "))$",
blockOpen: "$[[",
blockClose: "]]$",
});

const mdRecommended = markdownIt().use(markdownItMath, {
inlineDelimiters: [["$((", "))$"]],
blockDelimiters: [["$[[", "]]$"]],
});

const src = '$(("inline"))$\n$[["block"]]$';

t.assert.snapshot(md.render(src));
assert.equal(mdDepricated.render(src), mdRecommended.render(src));
});
});
});
24 changes: 0 additions & 24 deletions test/test.js.snapshot
Original file line number Diff line number Diff line change
@@ -1,31 +1,7 @@
exports[`Options > Depricated > inlineOpen inlineClose blockOpen blockClose 1`] = `
"<p><math><mtext>inline</mtext></math></p>\\n<math display=\\"block\\"><mtext>block</mtext></math>\\n"
`;

exports[`Options > Different options for the default renderer 1`] = `
"<p><math><mn>40,2</mn></math></p>\\n<math display=\\"block\\"><mn>40,2</mn></math>\\n"
`;

exports[`Options > Empty open or close dilimeters are filtered out 1`] = `
"<p>Foo $1+1 = 2$ bar</p>\\n<p>$$\\n1+1 = 2\\n$$</p>\\n"
`;

exports[`Options > LaTeX style delims 1`] = `
"<p>Foo <math><mrow><mn>1</mn><mo>+</mo><mn>1</mn></mrow><mo>=</mo><mn>2</mn></math> bar</p>\\n<math display=\\"block\\"><mrow><mn>1</mn><mo>+</mo><mn>1</mn></mrow><mo>=</mo><mn>2</mn></math>\\n"
`;

exports[`Options > No delimiters turns off rules 1`] = `
"<p>Foo $1+1 = 2$ bar</p>\\n<p>$$\\n1+1 = 2\\n$$</p>\\n"
`;

exports[`Options > Space dollar delims 1`] = `
"<p>Foo <math><mrow><mn>1</mn><mo>+</mo><mn>1</mn></mrow><mo>=</mo><mn>2</mn></math> bar</p>\\n"
`;

exports[`Options > Thick dollar delims 1`] = `
"<p>Foo <math><mrow><mn>1</mn><mo>+</mo><mn>1</mn></mrow><mo>=</mo><mn>2</mn></math> bar</p>\\n<math display=\\"block\\"><mrow><mn>1</mn><mo>+</mo><mn>1</mn></mrow><mo>=</mo><mn>2</mn></math>\\n"
`;

exports[`Options > Use Temml as renderer > block 1`] = `
"<math display=\\"block\\" class=\\"tml-display\\" style=\\"display:block math;\\"><mrow><mrow><mi>sin</mi><mo>⁡</mo></mrow><mo form=\\"prefix\\" stretchy=\\"false\\">(</mo><mn>2</mn><mi>π</mi><mo form=\\"postfix\\" stretchy=\\"false\\">)</mo></mrow></math>\\n"
`;
Expand Down