Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
a8548d5
chore: regenerate type declarations with pinned TypeScript 4.9.5
OlgaRedozubova Jul 27, 2026
071164e
Preserve list marker padding for block-content items
OlgaRedozubova Jul 27, 2026
5f82830
Measure list markers by display width, not code-unit length
OlgaRedozubova Jul 27, 2026
ce991ea
Do not leak env state from an aborted list parse
OlgaRedozubova Jul 27, 2026
dca0933
List rendering: footnote block rules stop at a list start (3.0.2)
OlgaRedozubova Jul 28, 2026
1cccbb6
Code-block styles scale with the em context (3.0.2)
OlgaRedozubova Jul 28, 2026
491c333
Harden footnote/list fixes: silent env-restore, minimal footnote term…
OlgaRedozubova Jul 28, 2026
c080c85
Marker width for math/wrapped markers; extract char-width helpers
OlgaRedozubova Jul 28, 2026
6ea00cf
Harden list marker padding: no env leak, scalable ex units
OlgaRedozubova Jul 28, 2026
60bd96e
Marker padding in em: scalable, floored at the default indent
OlgaRedozubova Jul 28, 2026
4872204
Fix caption numbering shift from speculative list parse; 3.1.0
OlgaRedozubova Jul 29, 2026
5566f54
List marker padding: per-glyph-class em width, clamped
OlgaRedozubova Jul 29, 2026
b77fe77
List marker padding: attribute per nesting level, indent nested lists
OlgaRedozubova Jul 29, 2026
d76a157
List marker padding: reserve only on overflow; fix \item detection
OlgaRedozubova Jul 30, 2026
37c71bb
List marker padding: order-independent resolution, total clamp; valid…
OlgaRedozubova Jul 30, 2026
bc57340
Markdown lists: indent in em, not the browser default 40px
OlgaRedozubova Jul 30, 2026
233e6b5
List CSS review: disclose footnotes-list + specificity floor; lock sc…
OlgaRedozubova Jul 30, 2026
ddbae23
List CSS: make the TOC padding guard order-independent
OlgaRedozubova Jul 30, 2026
f1ea8b5
List marker padding: unify block+inline attribution; review cleanups;…
OlgaRedozubova Jul 31, 2026
a51ea0a
docs: trim changelog to house style; fix stale spec Testing section
OlgaRedozubova Jul 31, 2026
cb7d79b
List rendering: table-cell export, review-response hardening
OlgaRedozubova Jul 31, 2026
840dfdf
Lists: roll back all nested-rule env from a discarded speculative parse
OlgaRedozubova Jul 31, 2026
06123c1
Lists: speed up marker width, env rollback, and token copy
OlgaRedozubova Aug 3, 2026
301fe7c
docs: correct list perf numbers and tighten wording
OlgaRedozubova Aug 3, 2026
2eb05a7
Lists: sharpen non-ASCII marker width and item splitting; more perf
OlgaRedozubova Aug 3, 2026
938e008
Lists: monospace marker width, blockquote-safe probe memo
OlgaRedozubova Aug 3, 2026
e272b25
Revert the doc/icons stylesheet edits
OlgaRedozubova Aug 3, 2026
9235035
Lists: ceil marker reserve, close env-replay clobber, monospace cells
OlgaRedozubova Aug 3, 2026
3fd28a5
Lists: full link labels in cell export, tighter probe-memo key
OlgaRedozubova Aug 3, 2026
3d45a7e
Lists/tabular: astral & zero-width marker width, closer-lookahead perf
OlgaRedozubova Aug 3, 2026
c2b2b3a
Lists: tighten cell leaf-run scope, snapshot reach, and whitespace class
OlgaRedozubova Aug 4, 2026
e2f8ff1
Lists/tabular/footnote: unify the closer-position cache; mono double-…
OlgaRedozubova Aug 4, 2026
9a7a466
Lists: escape link destination and html_inline label; restore continu…
OlgaRedozubova Aug 4, 2026
8141f15
docs: restructure list-rendering spec to the house template
OlgaRedozubova Aug 4, 2026
3105032
Lists: close a dangling <a> in a cell, clamp inline list depth
OlgaRedozubova Aug 4, 2026
4faf2cf
Lists: link label/href edges, zero-width controls, probe can't throw
OlgaRedozubova Aug 4, 2026
19d5f16
docs: condense the 3.1.0 changelog and roll it to August
OlgaRedozubova Aug 4, 2026
dff4fee
Footnotes: a throwing terminator probe never fails the render
OlgaRedozubova Aug 4, 2026
06f0866
Lists: roll back the list-level stack on a discarded parse; label esc…
OlgaRedozubova Aug 4, 2026
3424f6e
Lists: wider Wide blocks, fuller label escaping, narrower probe guard
OlgaRedozubova Aug 4, 2026
8f39ad6
Lists: math label verbatim with delimiters; keep sub/sup/ins markup
OlgaRedozubova Aug 4, 2026
6b1efb9
Lists: guard the terminator probe inside the rule; share warnDistinct
OlgaRedozubova Aug 5, 2026
009e007
Lists: roll back env by diff, wide BMP emoji, degrade a failed rule
OlgaRedozubova Aug 5, 2026
de7f797
Lists: abort an over-deep unclosed env in the body walk, one closer s…
OlgaRedozubova Aug 5, 2026
58d3707
Lists: drop the probe memo, pool the env snapshot, index-based inline…
OlgaRedozubova Aug 5, 2026
b2ba28f
Lists: clear the snapshot pool slot, reset warn-dedup per render, cle…
OlgaRedozubova Aug 5, 2026
a7bac50
docs: reorganize the list spec and expand the changelog breaking changes
OlgaRedozubova Aug 5, 2026
9b5dc54
Lists: image src through mdHref on both cell paths; tsv/csv branch cl…
OlgaRedozubova Aug 5, 2026
9b6844d
Lists: handle every \begin/\end on a line in source order
OlgaRedozubova Aug 6, 2026
023629a
Lists: cell math uses one delimiter pair, `$…$` by default
OlgaRedozubova Aug 6, 2026
3ffc0c0
Lists: keep the \renewcommand line break under forLatex
OlgaRedozubova Aug 6, 2026
077bd6a
Lists: own-key env rollback, backslash href, src-pos-cache unit tests
OlgaRedozubova Aug 6, 2026
2b5dac6
Lists: block-parse a float in a list body that carries no \item
OlgaRedozubova Aug 6, 2026
6b0f76c
Lists: gate the markerless block-env branch on LATEX_BLOCK_ENV_OPEN_RE
OlgaRedozubova Aug 6, 2026
cc4fdbd
Lists: wrapper envs are opaque to the list scanner
OlgaRedozubova Aug 6, 2026
9001881
Lists: precise wrapper-opaque guard, single-line wrappers, wrapper-ne…
OlgaRedozubova Aug 7, 2026
a747f19
findEndMarker escape parity; order-based opacity guard; derive wrappe…
OlgaRedozubova Aug 7, 2026
c1f6060
Lists: wrap a chunk before the first \item in a marker-less <li>
OlgaRedozubova Aug 10, 2026
0834b50
Lists: verbatim-aware opacity guard via shared math-spans/verbatim-ra…
OlgaRedozubova Aug 10, 2026
d8e727b
Lists: break the math-spans import cycle, union verbatim ranges, O(n)…
OlgaRedozubova Aug 10, 2026
84b5943
Lists: close a single-line nested tabular through one shared opaque-o…
OlgaRedozubova Aug 10, 2026
be87ae7
Lists: snapshot the level stack structurally; drop marker tokens per …
OlgaRedozubova Aug 11, 2026
33ac6a7
Lists: skip a verbatim closer and take the real one; per-family diagn…
OlgaRedozubova Aug 11, 2026
6675446
Lists: cache the structural closer/opener counts; harden env rollback…
OlgaRedozubova Aug 11, 2026
cef44ee
Lists: guard both env restores, free src caches at chain end, structu…
OlgaRedozubova Aug 11, 2026
a3a589e
Lists: extract the source model into its own module
OlgaRedozubova Aug 12, 2026
7675ea5
Lists: one text predicate for every reader; count sibling closers by …
OlgaRedozubova Aug 12, 2026
efd8715
Lists: restore only keys env owns; count free closers for a sibling; …
OlgaRedozubova Aug 12, 2026
30da3ad
Lists: derive the host <li> from a container stack; close a crossed e…
OlgaRedozubova Aug 13, 2026
21c7e28
Fix diagnostic and restore paths that could cost a list
OlgaRedozubova Aug 13, 2026
2a1eff5
Drop a redundant list invariant and render its fixtures once
OlgaRedozubova Aug 13, 2026
c2f61ad
Escape a pipe in the table_markdown ascii export
OlgaRedozubova Aug 14, 2026
fcc3dda
Drop a math opener that pairs only past its own paragraph
OlgaRedozubova Aug 14, 2026
458ea3c
A command written in an argument is text, for every reader
OlgaRedozubova Aug 18, 2026
36f0f17
A closer with no list open stays text
OlgaRedozubova Aug 18, 2026
8f29f64
List rendering: masked tail, list-level wrap, seeded fuzz
OlgaRedozubova Aug 18, 2026
44624c0
Lists: orphan closer, marker token ownership, review answers
OlgaRedozubova Aug 18, 2026
939d385
Lists: stop a test leak cascading, cache the code-span index once
OlgaRedozubova Aug 19, 2026
204f74f
Lists: count braces only inside supported commands, let a wrapper own…
OlgaRedozubova Aug 19, 2026
55e6f31
Lists: keep a line's leftover, and let the paragraph hold an env it o…
OlgaRedozubova Aug 20, 2026
19c4b74
Lists: no marker-less item for a command that configures the list
OlgaRedozubova Aug 20, 2026
a2d7ac8
Lists: one reader for a `[...]` option, and stop dropping a line besi…
OlgaRedozubova Aug 20, 2026
093bba2
Tests: a grid for the inline path, and growth bounds that do not read…
OlgaRedozubova Aug 20, 2026
01edf8e
Lists: an unclosed `[...]` option costs its line, not the document
OlgaRedozubova Aug 20, 2026
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
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ webpack.config.js
webpack.dev.js
.gitignore
.yarnignore
/pr-specs
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -970,10 +970,10 @@ The `MathpixMarkdown` React element accepts the following props:
| `include_linearmath` | boolean&nbsp;*`false`* | outputs linearmath `<linearmath style="display: none">...</linearmath>` |
| `include_latex` | boolean&nbsp;*`true`* | outputs latex `<latex style="display: none">...</latex>` |
| `include_svg` | boolean&nbsp;*`true`* | outputs svg `<svg>...</svg>` |
| `include_tsv` | boolean&nbsp;*`false`* | outputs tsv `<tsv style="display: none">...</tsv>` |
| `include_csv` | boolean&nbsp;*`false`* | outputs csv `<csv style="display: none">...</csv>` |
| `include_tsv` | boolean&nbsp;*`false`* | outputs tsv `<tsv style="display: none">...</tsv>`. A link contributes its `href` and an image its `src` in place of the visible text — these formats hold no markup; use `include_table_markdown` for the label. Whatever else the cell holds is still exported beside it, space-separated, so a cell is not an address even when it starts with one (`[a](http://u) tail` → `http://u tail`) |
| `include_csv` | boolean&nbsp;*`false`* | outputs csv `<csv style="display: none">...</csv>`. Same link/image rule as `include_tsv` |
| `include_table_html` | boolean&nbsp;*`true`* | outputs html table `<table>...</table>` |
| `include_table_markdown` | boolean&nbsp;*`false`* | outputs markdown table `<table-markdown>...</table-markdown>` |
| `include_table_markdown` | boolean&nbsp;*`false`* | outputs markdown table `<table-markdown>...</table-markdown>`. A link keeps its address as written; see [Security notes on the Markdown exports](#security-notes-on-the-markdown-exports) |
| `include_smiles` | boolean&nbsp;*`false`* | outputs smiles `<smiles>...</smiles>` |
| `tsv_separators` | `{column: '\t', row: '\n'}` | Separators for tsv tables |
| `csv_separators` | `{column: ',', row: '\n', toQuoteAllFields: false}` | Separators for csv tables. If `toQuoteAllFields=true` - all fields will be enclosed in double quotes|
Expand All @@ -984,6 +984,31 @@ The `MathpixMarkdown` React element accepts the following props:
| `table_markdown` | `{math_as_ascii: false, math_inline_delimiters: ['$','$']}`| By default, math goes into Markdown tables as latex and is enclosed in `$...$` delimiters. If `math_as_ascii` is set to `true`, then math will be represented as asciimath |
| `skipMathToHtml` | boolean&nbsp;*`false`* | When `true`, skips SVG serialization and `token.mathEquation` storage. Overrides `include_svg`; other MathJax outputs (`mathml`, `asciimath`, `linearmath`, etc.) still respect their own `include_*` flags. Intended for callers that walk the token tree directly and never read the serialized math HTML. |

### Security notes on the Markdown exports

`include_table_markdown`, `include_tsv` and `include_csv` return text, so the reader re-parses it.

- A rejected link (`javascript:`, `data:`, or anything a custom `validateLink` refuses) produces no `<a>` and stays as the literal `[label](address)` — in the HTML output and in the export alike. A reader with a permissive validator will make it a link again, so **validating the scheme is the reader's job**.
- An accepted link is exported with its address as written: escaping guards the Markdown syntax, not the URL scheme. `tsv`/`csv` carry the address without the label.
- A cell's inline markup is exported as written, raw HTML included — `<b onclick="…">x</b>` in a cell, or in a link label, reaches the export verbatim, and only `\`, `[` and `]` are escaped. A reader that parses the result with HTML enabled will render it, so **sanitising HTML is the reader's job** as well. This branch widened only how much of a link label is exported, not what is escaped.

Both are pinned by tests. If the reader cannot validate, treat the exported text as untrusted input or render from the HTML output.

### Diagnostics

Malformed LaTeX makes the list rules report to the global `console.warn`, prefixed `[list]`, `[list-state]`, `[env]` or `[mmd]`. There is **no option to silence or redirect them** — a server that renders untrusted input at volume should expect them in its log.

- They are informational. `[list] list rule failed` means one list was left as literal text while the rest of the document rendered. A marker asking for more room than the `20em` cap allows is **not** reported: the reserve is generous enough that the chain usually still fits, so the line said nothing a consumer could act on.
- Each distinct case is reported once per render, capped at 40 per family and 200 in total; past either cap one line says the rest are silent.
- A failure never throws out of `markdownToHTML` — the rule declines and the document renders — so a warning is the only signal that a list degraded.
- Deduplication counts per render, which is per call to `markdownToHTML`. A consumer driving `md.block.parse` or `md.inline.parse` directly never reaches the reset, so its keys accumulate until the per-family cap (40) reports and stops that family; the other families keep speaking.
- MathJax reports invalid math on its own channel, prefixed `[TexConvert]`, not deduplicated and not covered by the caps above. Malformed math written inside a list wrapper env now reaches it, where `3.0.1` never built the wrapper and so never sent it.

### Two notes for consumers who reach past the public API

- **Toggle a rule, do not swap its `fn`.** The footnote rules cache which block rules terminate them, and that cache is dropped when markdown-it invalidates its own rule cache — which `enable`, `disable` and `ruler.at` do. Assigning `rule.fn` inside `md.block.ruler.__rules__` does not, so the cache would keep pointing at your old function. Use `md.block.ruler.at(name, fn)`.
- **Keep `env` small.** A list parse snapshots every own string key of the `env` you pass, so that it can be put back exactly, and it does so once per line that opens a list. Measured on 200 list units: 62 ms with a plain `env`, 164 ms with a thousand extra keys on it.

### TOutputMathJax

| | type&nbsp;*`default`* | description |
Expand Down Expand Up @@ -1151,6 +1176,11 @@ Build the es5 file for node.
$ npm run build
```

`lib/` and `es5/` are committed, and only `npm run build` produces what is committed. `npm run compile`
is for iterating: it skips `es5/`, and it prints tuple types in `.d.ts` on one line where the build's
`ts-loader` prints them across several — so its output shows up as a diff in files no source change
touched.

# Testing

```shell
Expand Down
Loading