diff --git a/CHANGELOG.md b/CHANGELOG.md index b84d942..fbd60e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,146 +7,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Added - -- **The delimited inline comment `{% ... %}` is highlighted** (PART 9 §21a, markup-carve/carve#1239). It had no rule: the comment rules covered `%%` lines and `%%%` fences only, and no other brace rule could reach it, because the attribute block demands `:`, `.`, `#` or an identifier after the brace. So the payload read as ordinary text and the markers inside it stayed live - `{% *not bold* %}` rendered a bold run inside a comment. It is now scoped whole as `comment.block.inline.carve`, in paragraphs and in table cells. +## [0.1.5] - 2026-08-21 -- **A bare `::: figure` highlights as a composite figure, not as a generic container** (PART 9 §4c, markup-carve/carve#1215; tracked as markup-carve/carve-grammars#222). The kind word `figure` is reserved among the `:::` types: a bare opener - the fence, its separator, the word `figure`, and nothing else - is one figure of ordered panels. It now carries `markup.other.figure-group.carve` over the whole container and `entity.name.type.figure-group.carve` on the kind word, so the editor can tell it from the div it used to look exactly like. +### Added - The distinction lives in the tail of one line and the tail is all that decides it. `::: figure "A title"` and `::: figure [g]` are not that production at all, so they keep every scope they had. So does `:::figure`: the separator is a space run, never a tab (PART 7, corpus 254 renders that line as a paragraph), so the rule is spelled with a space run rather than the `[ \t]+` the generic rules beside it use. +- **The delimited inline comment `{% ... %}` is highlighted** (#84, markup-carve/carve#1239). It had no rule at all, so the payload read as ordinary text and the markers inside it stayed live. Scoped whole, in paragraphs and in table cells. +- **A bare `::: figure` is a composite figure, not a generic container** (#68, markup-carve/carve#1215). `::: figure "A title"`, `::: figure [g]` and `:::figure` are other productions and keep every scope they had. Groups do not nest. The caption after the closing fence stays an over-approximation shared with every Carve TextMate grammar - it sits one line past the closer, outside any begin/end span. +- **The language attribute `{:fr}` is scoped** (#67, markup-carve/carve#1114). An unrecognized attribute item does not degrade gracefully: one bad item left the whole block unscoped, so a span carrying a language lost its attribute coloring entirely. All six sites that spell the item alternation take it, including both glued marker rules. - Groups do not nest. A bare `::: figure` at any depth inside an open group is a generic container, which falls out of the rule leaving itself out of its own body: the generic container here is a per-line rule that recurses into no pattern list, so it cannot reach back to the group rule from any depth. +### Fixed - The group caption after the closing fence already scoped as a caption and still does. That claim is an over-approximation shared with every Carve TextMate grammar - a `^ ` line after any other `:::` closer gets it too - and it is not fixable with container state, because the caption sits one line *past* the closer, outside the span any begin/end rule can hold. markup-carve/carve-grammars#222 expected this repo's stateful model to pin the caption exactly; measured, it cannot, and the no-nesting rule is what the state buys instead. +- **A block opener on a list item's marker line opens the block there.** Seven shapes took no scope, or the wrong one: `- > q` (#75), `- %%%` (#76), `- # h`, `- ---`, `- ::: d`, `- :: term` (#79), and `` - ```js `` with `- |= a |` (#83). The comment fence was the damaging one - it opened no block, left the hidden body live, and ran to the end of the document, graying out every block after the item. All seven now share one marker prefix, so the family accepts and rejects the same marker forms, and each leaves the marker its own list scopes. +- **Opening a `.crv` file no longer fails when JCEF is not on the plugin's class path** (#88). JCEF is its own plugin - `com.intellij.modules.jcef` - rather than part of `com.intellij.modules.platform`, and this plugin declared no dependency on it, so `JBCefBrowser` was missing and `CarvePreviewEditorProvider` threw `NoClassDefFoundError` on PhpStorm 2026.2. The provider hides the default editor, so the file did not open at all. The two preview extension points moved into an optional `carve-jcef.xml` that loads only where JCEF does: without it the text editor opens the file and highlighting, export, templates and the language server are unaffected. +- **The preview, HTML export and language server run on a current engine again** (#70, #72). The vendored bundle rendered 23 of 1317 corpus documents differently where a bundle built from carve-js `main` renders them correctly. Rebuilt from carve-js `5695480e` and carve-lsp `ef1ca246`, with the spec pin moved to carve `b78950f` - the revision carve-js itself pins, so the engine and the corpus agree rather than the engine running ahead of the goldens: 0 of 1330 documents render differently now. +- **An unclosed fence is pinned per fence** (#82). `%%%` degrades to a line comment and hides nothing, while ` ``` `, `~~~` and `:::` run to the end of the document - so bounding the code fence by analogy would be the regression. The comment fence's own case is not fixable in a TextMate grammar: whether the opener is a fence depends on whether a closer appears later, and a begin pattern sees one line. ### Changed -- **The preview and HTML export render on a current engine again** (#62). The bundled `carve.iife.js` was built from carve-js `d0febc95` on 14 July and was 363 commits behind. Measured through the artifact rather than the recorded commit, it rendered **140 of carve `main`'s 690 corpus documents differently**, and 110 of the 610 in this plugin's own pinned corpus. None of them threw, so the preview showed wrong HTML with nothing to indicate it. Rebuilt from `3d95e948`: 0 of 690. - - The language server bundle moved from carve-lsp `156681d1` to `14320242`, taking its engine from carve-js `e28acbf1` to the published `0.1.2` - 140 of 690 down to 91. That is not parity. carve-lsp pins the published package exactly, so the remainder needs a carve-js release and is tracked as markup-carve/carve#608. - - Two documents still differ from this repo's pinned corpus, both recorded by name: one whose golden changed upstream after the spec pin (the engine is right, the pin is old), and one with 100 nested containers that overflows the GraalJS host stack - the same bundle renders it correctly under Node, so the limit is the plugin's JS host rather than the engine. - -- **A bullet glued to an attribute block is a marker, and both marker rules validate the payload** (markup-carve/carve-grammars#126). The ordered rule learned the glued form; the bundled grammar's bullet rule beside it never did, so `-{#x} item`, `*{.c} item` and `-{title="a}b"} item` went uncoloured on lines that ARE list items. Three corpus goldens pinned the wrong answer. - - Copying the ordered guard verbatim would have coloured `-{+a+} text` as a list, where it renders as a paragraph - `{+a+}` is an insertion span, not attributes. So the guard requires valid attribute syntax and both branches share it; the ordered rule had the same hole. Identifiers are strict (PART 9 §14) and admit no colon, matching carve-js and `CarveMarkerScanner`, which has validated the payload since #55. +- **The spec corpus is a declared test input** (#71). The shared-corpus tests reach `spec/tests/corpus` by file path, so moving the submodule changed nothing Gradle tracked: a 108-document pin bump left `./gradlew test` `UP-TO-DATE` in 9 seconds having run no test, while `--rerun-tasks` on the same tree failed twice. CI never saw it - a fresh checkout has no build cache - so the one place it bit was a human reviewing a bump locally. +- **The spec pin is current** (#70, #72, #78): 1131 -> 1330 corpus documents. Twenty-five new categories are classified, all SKIP - block context a line-based grammar cannot see, or render-time behavior with no token. Four of them record a MEASURED FALSE POSITIVE instead of a reason to skip, so a golden would pin the wrong answer: empty brace pairs, `{--}` and flag-shaped hyphen runs (#85), the table header marker claiming plain cells (#86), and a boolean attribute starting with an underscore (#87). Two goldens changed, both following upstream edits to the corpus input rather than a grammar regression. Two population guards that could not fail are replaced - the bundle corpus test asserted `>= 500` against 1131, and the corpus script rejected only an entirely absent corpus - and `spec-drift.yml` now gates the pin's AGE at ten days, since distance would be red every morning. - Known limitation, shared with every Carve TextMate grammar: the checkbox after a glued block (`-{.c} [x] done`) is not scoped; the bullet is. Eleven shapes are pinned in the `bullet-glued-attributes` fixture, both outcomes. +## [0.1.4] - 2026-08-11 -- **A mixed-case roman run is not an ordered marker** (markup-carve/carve-grammars#118). The bundled grammar spelled a roman run as one class, `[ivxlcdmIVXLCDM]+`, which matches any mixture of the two cases - so `Vim. text`, `Mix. text` and `Ix. text` coloured as lists where carve-js renders paragraphs. Those are the shape of a word starting a sentence, which is the risk the rule was written to avoid: it names `Note.` as the case to keep literal, and `Note` falls outside the class while `Vim` does not. Not a length rule - `mix.`, `civil.` and `did.` DO open lists, and so do `ivx.` and `IVX.` - so the fix is two classes. `CarveMarkerScanner` already used the split form (#55), so this closes the last disagreement between the two paths on roman markers. - -- **The annotator highlights a marker glued to an attribute block, the bare dot, and roman runs** (#55). `CarveMarkerScanner` is the second place this repo carries the marker rules, and its bullet and ordered patterns demanded a space straight after the marker - so `1.{#x} item` and `-{#x} [x] done` got no marker colour on a line that IS a list item, where the bundled grammar colours it. The same pattern was missing the bare dot (markup-carve/carve#472) and roman runs, both of which the grammar carries, so the two paths disagreed on `. first` and `iv. fourth`. - - The glued block must be VALID attribute syntax and must be followed by content, or the line is prose: `1.{#x}`, `1.{2=v} text` and `1.{bad!!} text` are paragraphs, while `-{not attrs} text` is a list item with two boolean attributes. Identifiers are strict (spec PART 9 §14) - `-{a:b}`, `-{--flag}` and `1.{#-id}` are paragraphs too. A roman run is case-consistent: `ivx.` and `IVX.` open lists, `Vim.` and `Mix.` do not. Every shape was run through carve-js, which is also why this does not copy the grammar on two points where the grammar is looser than the engine. +### Changed -- **An ordered marker glued to an attribute block needs content after it too** (markup-carve/carve-grammars#85). `1.{#x}` renders as a paragraph and `1.{#x} item` as a list item; the bundled grammar scoped the marker in both, because the guard was `(?= |\{)` and any brace satisfied it, so MARKER REQUIRES CONTENT never reached past the block. The fix spells the attribute block out in full rather than skipping it: the block is not brace-balanced text, so a `\{[^}]*\}` run stops at a `}` inside a quoted value and rejects `1.{title="a}b"} item`, which is a valid item. Ten shapes are pinned in the `marker-requires-content` fixture, both outcomes. Only the grammar is affected this time - `CarveMarkerScanner` never admitted the brace form at all, so it does not carry this bug (it under-highlights the valid attributed marker instead, which is its own gap). +- **The preview and HTML export render on a current engine again** (#62). The vendored `carve.iife.js` was 363 commits behind and rendered 140 of 690 corpus documents differently - none of them threw, so the preview showed wrong HTML with nothing to indicate it. Rebuilt from carve-js `3d95e948`: 0 of 690. The language server moved to carve-lsp `14320242`, taking its engine to the published 0.1.2 (91 of 690); carve-lsp pins the published package, so the rest needs a carve-js release (markup-carve/carve#608). Two documents still differ, both recorded: one whose golden changed upstream after the spec pin, and one with 100 nested containers that overflows the GraalJS host stack. +- **A bullet glued to an attribute block is a marker, and both marker rules validate the payload** (markup-carve/carve-grammars#126). `-{#x} item` and `-{title="a}b"} item` went uncolored on lines that ARE list items, and three goldens pinned it. The guard requires valid attribute syntax rather than any brace, so `-{+a+} text` stays the paragraph it renders as; identifiers are strict (PART 9 §14). Known limitation: the checkbox after a glued block is not scoped. +- **A mixed-case roman run is not an ordered marker** (markup-carve/carve-grammars#118). One class matched any mixture of cases, so `Vim.`, `Mix.` and `Ix.` colored as lists - the shape of a word starting a sentence. Not a length rule: `mix.`, `ivx.` and `IVX.` do open lists, so the fix is two classes. +- **The annotator highlights a marker glued to an attribute block, the bare dot, and roman runs** (#55). `CarveMarkerScanner` demanded a space straight after the marker and carried neither the bare dot (markup-carve/carve#472) nor roman runs, so the two highlighting paths disagreed on `1.{#x} item`, `. first` and `iv. fourth`. +- **An ordered marker glued to an attribute block needs content after it** (markup-carve/carve-grammars#85). `1.{#x}` renders as a paragraph and `1.{#x} item` as a list item; the old guard was satisfied by any brace, so MARKER REQUIRES CONTENT never reached past the block. +- **A run of spaces is not heading content** (#47). `#` followed by two spaces scoped as a heading, where the engine renders `

#

`. Found by a shared block battery, now vendored here. +- **A marker alone on its line is prose** (#44, markup-carve/carve#513). The rule was written `\s+` and `\s` matches the line's own newline, so `-`, `1.`, `::` and their spaced forms all scoped as markers. +- **A blockquote marker takes a space** (#42, markup-carve/carve#525). `>no space`, `>>x` and `>\tx` render as paragraphs, and `>>` is not a nested marker. Both the grammar and `CarveMarkerScanner` carried the old rule. +- **The spec submodule is current again** (#38): 392 -> 529 corpus documents. Fifty-five new categories classified, `symbols` and `inline-literal` COVERED and the other 47 SKIP with a reason. Three entries were upstream renames rather than removals. -- **A run of spaces is not heading content** (#47). `#` followed by two spaces scoped as a heading, because the rule's `.+` matches them; carve-rs renders it `

#

`. Found by a shared block battery, now vendored here and run against this grammar, so a rule fixed upstream and missed here fails a test instead of shipping. -- **A marker alone on its line is prose** (#44). MARKER REQUIRES CONTENT (markup-carve/carve#513) was in the rules already, written `\s+`, and `\s` matches the line's own newline - so the requirement never bit. `-`, `- `, `1.`, `1. `, `::` and `:: ` all scoped as markers where carve-rs renders every one as a paragraph. Two code paths carried it here: the bundled grammar and `CarveMarkerScanner`, which drives the annotator. The guard is a line-end lookahead rather than `(?=\S)`, because only spaces and tabs separate a marker from its content: `# Title` with a leading no-break space is still a heading. `- [ ] ` with nothing after it is a plain bullet holding the literal `[ ]`, not a checkbox. -- **A blockquote marker takes a space** (#42). markup-carve/carve#525 made the - separator mandatory, and two code paths carried the old rule: the bundled - TextMate grammar and `CarveMarkerScanner.QUOTE`, which drives the annotator - - the highlighting a user actually sees. Verified against carve-rs: `>no space`, - `>>x`, `>> x` and `>\tx` all render as paragraphs, `>>` is not a nested marker - (that is `> > x`, a space per marker), and a tab does not separate. The spec - pin moved 8 commits in the same change, which is what surfaced it. +### Added -- **The spec submodule is current again** (#38). It sat at 392 corpus documents - while the spec had 529, so the coverage matrix and the token-stream goldens - were measuring a July language. Fifty-five new categories are classified: - `symbols` and `inline-literal` are COVERED (the only ones producing - `constant.character.entity` and `markup.raw.inline.literal` scopes under this - grammar), the other 47 are SKIP with a reason naming the covered category - their tokens already come from. Three entries were upstream renames, not - removals, and each keeps its side of the matrix: `emoji` -> `symbols`, - `link-destination-stops-at-the-first-parenthesis` -> - `link-destination-parentheses-balance`, `multi-line-headings` -> - `single-line-headings`. Twenty-five goldens are new and ten changed; all ten - are upstream edits to the example text, verified file by file against the old - submodule, not grammar regressions. +- **Syntax highlighting for the inline literal.** A `!` before a verbatim backtick span (`` !`/kaet/` ``) renders its content as prose, so notation that collides with the bare emphasis delimiters needs no per-character escaping. A trailing `{...}` stays a separate attribute block. ### Fixed -- **An orphaned golden can no longer rot unnoticed.** The snapshot test only - fails on goldens it looks for, so a renamed category left its old `.tokens` - file behind with nothing reading it - three had accumulated. A new check in - the coverage-matrix test fails on any golden with no corpus file behind it. - -- **Inline footnote content is parsed as inline markup.** `^[...]` used a flat - match, so its whole body was one opaque span: nested emphasis and code inside a - note did not highlight, and a backslash-escaped bracket such as `^[a \] b]` - terminated the note early, leaving the rest of the line unstyled. The rule is - now a line-bounded `begin`/`end` whose content is inline-parsed, matching the - spec (`inline_footnote = '^[', inline_content, ']'`). The existing - `string.other.footnote.inline.carve` content scope is preserved, and the - one-line bound means an unclosed `^[` still cannot leak into later paragraphs. -- **An escaped `\^[` is no longer highlighted as a footnote.** The inline - footnote opener now refuses a backslash-escaped caret, so the documented - literal form `\^[x]` stays plain text even in a table cell, where the - top-level escape rule is not in scope. -- **Table cells highlight footnotes, citations, mentions, tags and symbols.** - The table-row pattern list omitted `#footnotes`, `#citations` and - `#mentions-tags`, so `| ^[note] |`, `| [key] |`, `| user |`, `| #tag |` and - `| :tada: |` were left unscoped inside a table even though all of them - highlight correctly elsewhere. - -- **A div fence opening on a list marker is highlighted again.** `- ::: note` is - corpus-pinned (corpus 114) but the div rule was anchored past the bullet, so the - whole opener — fence, type word and any title — fell through to plain text. The - rule now consumes an optional bullet prefix and scopes it as a list marker. -- **A definition-list term no longer swallows the rest of its line.** The term - line captured everything after `::` into one term scope, so a trailing - `%% comment` and any inline markup inside the term were absorbed and never - tokenized. Only the marker is scoped now, mirroring the single-colon rule. -- **An unquoted attribute value containing dots keeps its value scope.** In - `{k=v.w}` the `.w` was scoped as a *class* rather than part of the value — - the behaviour corpus 110 exists to pin. Unquoted values are now consumed whole. - This also fixes values that previously went entirely unscoped, such as - `{lang=en-US}`. -- Table alignment colons in a GFM delimiter row now get their own scope, so - `|:---:|` distinguishes the alignment markers from the dash run. -- **`checkGrammarDrift` reports far less noise.** It compared `comment` prose, - which cannot affect tokenization, and normalized only one of the several - scope-name conventions this grammar deliberately differs by. Comments are now - stripped before comparing and the remaining convention families are mapped, so - the report shows genuine structural drift. Divergent shared rules dropped from - 13 to 7, and the 7 that remain are real differences rather than naming noise. - The `frontmatter` rule, which must differ because IntelliJ's TextMate engine - treats `\A` like `^`, is now declared as intentional and pinned by a fixture. -- **`checkGrammarDrift` no longer reports two phantom missing features.** It - compares upstream and local rules by name, and upstream splits the braced - forced-emphasis and superscript/subscript forms into their own `forced-emphasis` - and `sup-sub` rules where this grammar folds them into `emphasis`. The - constructs were always highlighted; only the grouping differed. The check now - declares that grouping delta explicitly, so the actionable category is empty - when nothing is actually missing rather than permanently non-empty. Each - declared entry must be backed by a fixture, so the declaration cannot be used - to hide a genuine gap. -- **Unclosed inline literal and math openers no longer leak.** Both rules matched - with an open-ended begin/end pair, so typing `` !` `` or `` $` `` without its - closer highlighted every following paragraph as literal or math content until - the next backtick run anywhere in the file. Both are now closed-span match - rules, like inline code, which are line-bounded and cannot leak. -- Table cells now highlight raw inline, inline literals and math, which were - missing from the cell pattern list. -- **The `downloadGrammar` task no longer destroys the committed grammar.** It - streamed vscode-carve's grammar straight over `carve.tmLanguage.json`, but the - two copies deliberately diverge: running it rewrote all 111 `keyword.control.*` - scope names to `punctuation.definition.*`, deleted the three plugin-only rules - (`cross-reference`, `hard-break`, `thematic-break`) and clobbered 13 of the 28 - shared rules. It is replaced by a read-only `checkGrammarDrift` task that - normalizes the scope-name convention, reports plugin-only, diverged and - upstream-only rules separately, and fails only on the actionable last category. - `downloadGrammar` remains as an alias for the safe check. The intended deltas - are documented in `build.gradle.kts` and `docs/development.md`. - -### Added - -- **Syntax highlighting for the inline literal.** A `!` before a verbatim backtick span - (`` !`/kaet/` ``) renders its content as ordinary prose rather than code, so notation that - collides with the bare emphasis delimiters - phonemic transcription, glob patterns, paths - - needs no per-character escaping. The markers are highlighted like the surrounding verbatim - family, and a trailing `{…}` stays a separate attribute block. +- **An orphaned golden can no longer rot unnoticed.** The snapshot test only fails on goldens it looks for, so a renamed category left its `.tokens` file with nothing reading it - three had accumulated. The coverage-matrix test now fails on any golden with no corpus file behind it. +- **Inline footnote content is parsed as inline markup.** `^[...]` was a flat match, so nested emphasis and code did not highlight and `^[a \] b]` terminated the note early. It is a line-bounded `begin`/`end` now, so an unclosed `^[` still cannot leak. +- **An escaped `\^[` is no longer a footnote**, including in a table cell, where the top-level escape rule is not in scope. +- **Table cells highlight footnotes, citations, mentions, tags and symbols**, all of which the row pattern list omitted. +- **A div fence opening on a list marker is highlighted again.** `- ::: note` is corpus-pinned but the rule was anchored past the bullet, so the whole opener fell through to plain text. +- **A definition-list term no longer swallows the rest of its line.** Only the marker is scoped, mirroring the single-colon rule. +- **An unquoted attribute value containing dots keeps its value scope.** In `{k=v.w}` the `.w` scoped as a class; unquoted values are consumed whole, which also fixes `{lang=en-US}`. +- **Unclosed inline literal and math openers no longer leak.** Both were open-ended begin/end pairs, so an unclosed `` !` `` or `$` highlighted every following paragraph. Both are closed-span match rules now, like inline code. +- Table alignment colons in a GFM delimiter row get their own scope, and table cells highlight raw inline, inline literals and math. +- **`checkGrammarDrift` reports far less noise.** It compared prose comments and normalized only one scope-name convention; divergent shared rules dropped from 13 to 7, and the 7 are real. It also stopped reporting two phantom missing features, where upstream splits into rules this grammar folds together - each declared delta must be backed by a fixture, so the declaration cannot hide a genuine gap. +- **The `downloadGrammar` task no longer destroys the committed grammar.** It streamed vscode-carve's grammar straight over the committed copy, rewriting 111 scope names, deleting the three plugin-only rules and clobbering 13 of the 28 shared ones. It is a read-only `checkGrammarDrift` now, failing only on the actionable category. ## [0.1.3] - 2026-07-14 @@ -288,6 +199,10 @@ Initial release. carve-php (PHP CLI via markup-carve/carve-php). - Custom preview CSS, layered from file-, project-, and settings-level sources. -[Unreleased]: https://github.com/markup-carve/intellij-carve/compare/0.1.1...HEAD +[Unreleased]: https://github.com/markup-carve/intellij-carve/compare/0.1.5...HEAD +[0.1.5]: https://github.com/markup-carve/intellij-carve/compare/0.1.4...0.1.5 +[0.1.4]: https://github.com/markup-carve/intellij-carve/compare/0.1.3...0.1.4 +[0.1.3]: https://github.com/markup-carve/intellij-carve/compare/0.1.2...0.1.3 +[0.1.2]: https://github.com/markup-carve/intellij-carve/compare/0.1.1...0.1.2 [0.1.1]: https://github.com/markup-carve/intellij-carve/compare/0.1.0...0.1.1 [0.1.0]: https://github.com/markup-carve/intellij-carve/releases/tag/0.1.0 diff --git a/build.gradle.kts b/build.gradle.kts index 11fbd12..37a0b30 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "org.markupcarve" -version = "0.1.4" +version = "0.1.5" repositories { mavenCentral() diff --git a/spec b/spec index 22f7f47..b78950f 160000 --- a/spec +++ b/spec @@ -1 +1 @@ -Subproject commit 22f7f47732bd949fd21e3d6ebedfd90f3723dc80 +Subproject commit b78950f25fefc501204015e6c3f420065a87e00d diff --git a/src/main/resources/META-INF/carve-jcef.xml b/src/main/resources/META-INF/carve-jcef.xml new file mode 100644 index 0000000..a7408f5 --- /dev/null +++ b/src/main/resources/META-INF/carve-jcef.xml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 0c31575..d902419 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -38,6 +38,13 @@ to get syntax highlighting and preview. --> com.redhat.devtools.lsp4ij + + com.intellij.modules.jcef @@ -76,15 +83,6 @@ - - - - above. + in the optional carve-lsp.xml, loaded only when LSP4IJ is installed, and the + preview extension points live in carve-jcef.xml the same way. See the two + optional entries above. --> diff --git a/src/main/resources/js/carve.iife.js b/src/main/resources/js/carve.iife.js index a31a273..582c92b 100644 --- a/src/main/resources/js/carve.iife.js +++ b/src/main/resources/js/carve.iife.js @@ -1,6 +1,6 @@ // Generated by tools/build-carve-bundle.sh - do not edit by hand. -// Bundled from markup-carve/carve-js commit 7cd66e01513a16f9d1f0abf36b1a6c8d4a08c3ba -// Built (UTC): 2026-08-18T04:43:40Z +// Bundled from markup-carve/carve-js commit 5695480e97e228821590fc7180485aecdb2a8839 +// Built (UTC): 2026-08-20T23:52:43Z // Minimal TextEncoder/TextDecoder (UTF-8) polyfill for GraalJS, which does // not provide the WHATWG Encoding API that carve-js relies on. Prepended to @@ -114,6 +114,7 @@ var carve = (() => { SMART_PUNCTUATION_GLYPHS: () => SMART_PUNCTUATION_GLYPHS, SMART_QUOTE_LOCALES: () => SMART_QUOTE_LOCALES, SPEC_VERSION: () => SPEC_VERSION, + SourceUnspellableError: () => SourceUnspellableError, abc: () => abc, applyAstPatch: () => applyAstPatch, applyMigrationFixes: () => applyMigrationFixes, @@ -215,6 +216,8 @@ var carve = (() => { rightwards_arrow: "\u2192", leftwards_arrow: "\u2190", rightwards_double_arrow: "\u21D2", + leftwards_double_arrow: "\u21D0", + left_right_double_arrow: "\u21D4", less_than_or_equal: "\u2264", greater_than_or_equal: "\u2265", not_equal: "\u2260", @@ -300,6 +303,7 @@ var carve = (() => { var activeMatchers = []; var activeMatcherCtx = null; var activeDocument = null; + var probingLazyParagraph = false; var RE_HEADING = /^(#{1,6}) +((?=[ \t]*[^ \t\n\r]).+?)(?:[ \t]+\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?[ \t]*$/; var RE_HR = /^([-*_])\1{2,}[ \t]*$/; var TRAILING_WS = "[ \\t]*$"; @@ -414,8 +418,8 @@ var carve = (() => { return false; if (!/\|[ \t]*$/.test(line2) && rowAttrsFromLine(line2).attrs === void 0) return false; - const cells = splitTableRow(rowAttrsFromLine(line2).body); - return cells.some((cell) => cell.trim().length > 0) || cells.length >= 2; + const cells2 = splitTableRow(rowAttrsFromLine(line2).body); + return cells2.some((cell) => cell.trim().length > 0) || cells2.length >= 2; }; var RE_TABLE_CONT = /^\+.*\|[ \t]*$/; var RE_BARE_IMAGE = /^!\[([^\]]*)\]\(([^)\s]+)(?: "([^"]*)"| '([^']*)')?\)(?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?[ \t]*$/; @@ -470,6 +474,22 @@ var carve = (() => { * `> ` and `> ` are all valid. */ __publicField(this, "linePrefixWidths"); + /** + * The DOCUMENT's own lines, carried unchanged into every sub-lexer. + * + * A container's body reaches a sub-lexer DEDENTED, so a line's document + * column is not recoverable from the view: `* * +` / `x` and `* * +` / ` x` + * both arrive as `["* +", "x"]` and are byte-identical here. §17 L3 asks for + * the document column - a continuation marker attaches a block that begins at + * column 0 and nothing else (markup-carve/carve#1436) - so the question has to + * be asked of the original line, which `lineNumber` still names. + * + * NOT `linePrefixWidths`, which would otherwise answer this: that map is + * position bookkeeping and is allowed to DECLINE for reassembled content, so + * parsing through it would make the tree depend on whether positions could be + * anchored. + */ + __publicField(this, "rootLines"); __publicField(this, "suppressPositions", false); __publicField(this, "pos", 0); // Block-container nesting depth of this (sub-)lexer; 0 at the document top. @@ -488,6 +508,8 @@ var carve = (() => { */ __publicField(this, "atDocumentLevel", false); __publicField(this, "linkDefs", /* @__PURE__ */ new Map()); + /** Document lines admitted only as a block quote's lazy paragraph text. */ + __publicField(this, "literalLazyLinkDefLines", /* @__PURE__ */ new Set()); // Footnote definitions keyed by raw label; value is the parsed note // body (def line + indented continuation), set by parseFootnoteDef. __publicField(this, "footnoteDefs", /* @__PURE__ */ new Map()); @@ -661,9 +683,11 @@ var carve = (() => { const sub = subLexer(lines, parent.parseOptions, parent.lineNumberOffset + startLineIndex, sourceLineMap ?? Array.from({ length: mapLength }, (_l, i) => parent.lineNumber(startLineIndex + i)), parent.unclosedContainerKeys); sub.abbrDefs = parent.abbrDefs; sub.linkDefs = parent.linkDefs; + sub.literalLazyLinkDefLines = parent.literalLazyLinkDefLines; sub.footnoteDefs = parent.footnoteDefs; sub.footnoteDefPos = parent.footnoteDefPos; sub.nested = true; + sub.rootLines = parent.rootLines ?? parent.lines; sub.depth = parent.depth + 1; sub.inFigureGroup = parent.inFigureGroup; attachDocumentOffsets(sub, parent, startLineIndex); @@ -858,12 +882,12 @@ var carve = (() => { } function appendLinkReferenceDefinitions(children, lexer, source) { const authored = []; - for (const [label, def] of lexer.linkDefs) { + for (const [label2, def] of lexer.linkDefs) { if (def.line === void 0) continue; const node = { type: "link_reference_definition", - label, + label: label2, href: def.href }; if (def.title !== void 0) @@ -954,8 +978,8 @@ var carve = (() => { } return null; } - function normalizeRefLabel(label) { - return label.trim().replace(/\s+/g, " "); + function normalizeRefLabel(label2) { + return label2.trim().replace(/\s+/g, " "); } var RE_DESCRIPTION_PREFIX = /^[ \t]*:[ \t]+/; var RE_AFTER_TERM = /^[ \t]*(?:::(?!:)|:)[ \t]/; @@ -1014,6 +1038,135 @@ var carve = (() => { function prepassOpensBlock(line2) { return line2 === "" || lineOpensBlock(line2) || RE_COMMENT_LINE.test(line2) || line2.startsWith("{") || isContinuationMarker(line2) || RE_TABLE_CONT.test(line2) || RE_ABBR_DEF.test(line2); } + function composeContainerPrefix(raw, afterTerm, open) { + const peeled = []; + let pos = 0; + let depth = 0; + let handed = 0; + for (; ; ) { + const rest = raw.slice(pos); + const ind = leadingWhitespace(rest); + const col = pos + ind; + while (depth < open.length && !open[depth].quote && open[depth].col <= col) { + handed = open[depth].col; + depth++; + } + const after = rest.slice(ind); + if (after === "") + return { column: col, peeled, depth }; + if (after[0] === ">" && (after.length === 1 || after[1] === " ")) { + if (col !== handed) + return { column: col, peeled, depth }; + const content2 = col + (after.length === 1 ? 1 : 2); + const matched2 = depth < open.length && open[depth].quote && open[depth].col === content2; + if (matched2) + depth++; + peeled.push({ content: content2, quote: true, matched: matched2 }); + handed = content2; + pos = content2; + continue; + } + const desc = afterTerm ? /^:[ \t]+/.exec(after) : null; + const marker = desc ?? prepassMarker(after); + if (marker === null || !/\S/.test(after.slice(marker[0].length))) { + return { column: col, peeled, depth }; + } + const content = col + marker[0].length; + const matched = depth < open.length && !open[depth].quote && open[depth].col === content; + if (matched) + depth++; + peeled.push({ content, quote: false, matched }); + handed = content; + pos = content; + } + } + function lazyProbeFrame(blocks) { + const levels = []; + let current = blocks; + let endsInParagraph = false; + for (; ; ) { + const last = current[current.length - 1]; + if (!last) + return { levels, endsInParagraph }; + levels.push(`blocks:${last.type}:${current.length}`); + endsInParagraph = last.type === "paragraph"; + if (last.type === "block_quote" || last.type === "div" || last.type === "admonition" || last.type === "figure_group" || last.type === "line_block") { + current = last.children; + continue; + } + if (last.type === "list") { + endsInParagraph = false; + const item = last.items[last.items.length - 1]; + if (!item) + return { levels, endsInParagraph }; + levels.push(`items:${last.items.length}`); + current = item.children; + continue; + } + if (last.type === "definition_list") { + endsInParagraph = false; + const item = last.items[last.items.length - 1]; + if (!item) + return { levels, endsInParagraph }; + levels.push(`definitions:${last.items.length}`); + const definition = item.definitions[item.definitions.length - 1]; + if (!definition) + return { levels, endsInParagraph }; + current = definition; + continue; + } + return { levels, endsInParagraph }; + } + } + function lazyProbeCost(lexer, candidate) { + let start = candidate - 1; + while (start >= 0 && !isBlankLine(lexer.lines[start])) + start--; + start++; + if (start === candidate) + return null; + let runBytes = 0; + for (let i = start; i < candidate; i++) + runBytes += utf8ByteLength(lexer.lines[i]) + 1; + return { start, cost: runBytes * 2 + utf8ByteLength(lexer.lines[candidate]) }; + } + function spendLazyProbeBudget(lexer, candidate, budget) { + const priced = lazyProbeCost(lexer, candidate); + return priced && priced.cost <= budget ? budget - priced.cost : budget; + } + function lineFoldsIntoOpenParagraph(lexer, candidate, budget) { + if (probingLazyParagraph) + return false; + const priced = lazyProbeCost(lexer, candidate); + if (!priced || priced.cost > budget) + return false; + const before = lexer.lines.slice(priced.start, candidate).join("\n"); + const after = `${before} +${lexer.lines[candidate]}`; + const probe = (source) => { + const { onUnclosedContainer: _ignored, ...callerOptions } = lexer.parseOptions; + const options = { ...callerOptions, positions: false }; + const sub = new Lexer(source, options); + sub.atDocumentLevel = true; + sub.suppressPositions = true; + const previousCtx = activeMatcherCtx; + activeMatcherCtx = activeMatchers.length ? makeMatcherCtx(sub, options) : null; + try { + collectLinkDefs(sub); + return lazyProbeFrame(parseBlocks(sub, 0)); + } finally { + activeMatcherCtx = previousCtx; + } + }; + probingLazyParagraph = true; + try { + const a = probe(before); + const b = probe(after); + return b.endsInParagraph && a.levels.join("\0") === b.levels.join("\0"); + } finally { + probingLazyParagraph = false; + } + } function collectLinkDefs(lexer) { let fence = null; let verse = null; @@ -1021,13 +1174,16 @@ var carve = (() => { const commentScopeMemo = /* @__PURE__ */ new Map(); const divs = []; const listCols = []; + const openCols = []; let prevBlank = true; let inFootnoteBody = false; let plusColumn = null; let paraState = "no"; let paraLine = ""; + let paraDepth = 0; let attrRun = false; const hasBlockMatchers = activeMatchers.some((e) => e.matchBlock); + let lazyProbeBudget = utf8ByteLength(lexer.lines.join("\n")) * 4 + 4096; let prepassClosers = null; for (let idx = 0; idx < lexer.lines.length; idx++) { if (idx < lexer.pos) @@ -1058,7 +1214,7 @@ var carve = (() => { fence = null; } const marker = prepassMarker(unquoted); - const indent2 = unquoted.length - unquoted.replace(/^[ \t]+/, "").length; + const indent3 = unquoted.length - unquoted.replace(/^[ \t]+/, "").length; const rawTrimmed = raw.trim(); const startsBlock = /^#{1,6}([ \t]|$)/.test(rawTrimmed) || RE_BLOCKQUOTE.test(rawTrimmed) || /^(`{3,}|~{3,})/.test(rawTrimmed) || // A COLON FENCE ENDS THE ITEM TOO, and was the one block opener missing // from this list. A flush `:::` under an unblanked item opens a SIBLING @@ -1085,9 +1241,9 @@ var carve = (() => { m2 = prepassMarker(rest); } } else if (RE_DEFLIST_DEF.test(unquoted)) { - while (listCols.length && listCols[listCols.length - 1] > indent2) + while (listCols.length && listCols[listCols.length - 1] > indent3) listCols.pop(); - listCols.push(indent2 + DEFLIST_CONTENT_COL); + listCols.push(indent3 + DEFLIST_CONTENT_COL); } else if (!isBlankLine(raw) && // A LINK REFERENCE DEFINITION at column 0 ends the item too, so it has // to pop the stack like any other block start. It is not in // `startsBlock` because it is invisible, and being left out meant the @@ -1106,9 +1262,25 @@ var carve = (() => { // because PART 12 §7 recognizes one only as a direct child of the // document. (wasPrevBlank || startsBlock || isLinkDefLine(rawTrimmed))) { - while (listCols.length && listCols[listCols.length - 1] > indent2) + while (listCols.length && listCols[listCols.length - 1] > indent3) listCols.pop(); } + const composed = composeContainerPrefix(raw, afterTerm, openCols); + if (isBlankLine(raw)) { + const firstQuote = openCols.findIndex((e) => e.quote); + if (firstQuote >= 0) + openCols.length = firstQuote; + } else if (composed.peeled.length) { + openCols.length = composed.depth; + for (const one of composed.peeled) { + if (!one.matched) + openCols.push({ col: one.content, quote: one.quote }); + } + } else if (wasPrevBlank || startsBlock || isLinkDefLine(rawTrimmed)) { + while (openCols.length && openCols[openCols.length - 1].col > composed.column) { + openCols.pop(); + } + } const contentCol = listCols.length ? listCols[listCols.length - 1] : 0; if (commentFence !== null) { const close = RE_COMMENT_BLOCK_ANY.exec(line2); @@ -1169,9 +1341,27 @@ var carve = (() => { const paraWasOpen = paraState !== "no" && !(inFootnoteBody && !isBlankLine(raw) && leadingWhitespace(raw) === 0); const paraAsk = paraState === "ask"; const paraLineAbove = paraLine; + const paraDepthAbove = paraDepth; + let markerInterruptsParagraph = false; + let prefixOwnedByParagraph = true; + for (let depth = 0; depth < composed.peeled.length; depth++) { + const one = composed.peeled[depth]; + if (one.quote && !one.matched && prefixOwnedByParagraph) + markerInterruptsParagraph = true; + if (!one.quote && one.matched && depth < paraDepthAbove) + markerInterruptsParagraph = true; + if (!one.matched) + prefixOwnedByParagraph = false; + } + const matcherProbeCandidate = hasBlockMatchers && !probingLazyParagraph && (composed.peeled.some((one) => !one.quote) && RE_LINK_DEF.test(splitTrailingAttrBlock(line2)[0]) || RE_FENCE.test(line2) || RE_RAW_FENCE.test(line2)); + const paragraphReallyOpen = paraWasOpen && !markerInterruptsParagraph && (matcherProbeCandidate ? lineFoldsIntoOpenParagraph(lexer, idx, lazyProbeBudget) : !paraAsk || !prepassOpensBlock(paraLineAbove)); + if (matcherProbeCandidate && paraWasOpen && !markerInterruptsParagraph) { + lazyProbeBudget = spendLazyProbeBudget(lexer, idx, lazyProbeBudget); + } const inAttrRun = attrRun; attrRun = !isBlankLine(raw) && !line2.includes("}") && (attrRun || line2.startsWith("{")); paraState = isBlankLine(raw) || inAttrRun ? "no" : "ask"; + paraDepth = paraState === "no" ? 0 : paragraphReallyOpen ? paraDepthAbove : openCols.length; paraLine = line2; const quoteIndent = leadingWhitespace(raw); const quoteAtWrongColumn = quoteIndent > 0 && raw.slice(quoteIndent).startsWith(">") && !listCols.includes(quoteIndent); @@ -1194,7 +1384,7 @@ var carve = (() => { break; } } - if (!paraWasOpen || paraAsk && prepassOpensBlock(paraLineAbove) || hasBlockMatchers || codeCloserPossibleIn(prepassClosers ?? (prepassClosers = buildCodeCloserIndex(lexer.lines, RE_PREPASS_ANY_FENCE_CLOSER)), run, idx)) { + if (!paragraphReallyOpen || codeCloserPossibleIn(prepassClosers ?? (prepassClosers = buildCodeCloserIndex(lexer.lines, RE_PREPASS_ANY_FENCE_CLOSER)), run, idx)) { fence = { ch: run[0], len: run.length, @@ -1240,10 +1430,13 @@ var carve = (() => { else if (isBlankLine(raw)) plusColumn = null; const openColumn = inFootnoteBody ? FOOTNOTE_BODY_COLUMN : contentCol; - const atAnOpenContentColumn = plusColumn !== null ? rawIndent === plusColumn : listCols.length ? listCols.includes(rawIndent) : rawIndent === openColumn; - const notAtContentColumn = kept === unquoted && !atAnOpenContentColumn; + const reached = (col) => composed.peeled.some((one) => one.content === col) || openCols.some((e, i) => i < composed.depth && e.col === col); + const anyReached = composed.peeled.length > 0 || composed.depth > 0; + const stoppedAtQuote = !composed.peeled.some((one) => one.quote) && composed.depth < openCols.length && openCols[composed.depth].quote; + const atAnOpenContentColumn = stoppedAtQuote ? false : plusColumn !== null ? rawIndent === plusColumn : anyReached ? reached(composed.column) : composed.column === openColumn; + const notAtContentColumn = !atAnOpenContentColumn; const [defLine, defAttrText] = splitTrailingAttrBlock(line2); - const m = topLevelIndentedDef || notAtContentColumn ? null : RE_LINK_DEF.exec(defLine); + const m = topLevelIndentedDef || notAtContentColumn || paragraphReallyOpen && composed.peeled.some((one) => !one.quote) ? null : RE_LINK_DEF.exec(defLine); if (m) { const def = { href: m[2] }; const title = m[3] ?? m[4]; @@ -1270,8 +1463,8 @@ var carve = (() => { lexer.consume(); continue; } - const indent2 = leadingWhitespace(line2); - if (indent2 < baseIndent) + const indent3 = leadingWhitespace(line2); + if (indent3 < baseIndent) break; const ba = tryCollectBlockAttributes(lexer); if (ba) { @@ -1284,6 +1477,8 @@ var carve = (() => { if (pending && !invisible) { node.attrs = mergeAttrs(pending, node.attrs ?? {}); } + if (node.type === "table") + deriveTableMetadata(node); const cb = node.type === "code_block" ? node : node.type === "figure" && node.target.type === "code_block" ? node.target : void 0; if (cb?.header !== void 0 && node.attrs?.keyValues?.title === void 0 && cb.attrs?.keyValues?.title === void 0) { cb.attrs = { @@ -1300,6 +1495,49 @@ var carve = (() => { carry.attrs = pending; return out; } + function deriveTableMetadata(table) { + const kv = table.attrs?.keyValues; + if (!kv) + return; + const aligns = positional(kv.aligns, /* @__PURE__ */ new Set(["left", "right", "center"])); + const valigns = positional(kv.valigns, /* @__PURE__ */ new Set(["top", "middle", "bottom"])); + const widths = kv.widths?.split(",").map((raw) => { + const value = Number(raw.trim()); + return Number.isFinite(value) && value > 0 && value <= 100 ? value / 100 : void 0; + }) ?? []; + const count = Math.max(aligns.length, valigns.length, widths.length); + if (count > 0) { + table.columns = Array.from({ length: count }, (_, i) => ({ + ...aligns[i] ? { align: aligns[i] } : {}, + ...valigns[i] ? { valign: valigns[i] } : {}, + ...widths[i] ? { width: widths[i] } : {} + })); + } + const rowCount = (value) => { + if (value === void 0) + return 0; + if (value.trim() === "") + return 1; + return /^\d+$/.test(value.trim()) ? Number(value.trim()) : void 0; + }; + const headRows = rowCount(kv["header-rows"]); + const footRows = rowCount(kv["footer-rows"]); + if (headRows === void 0 || footRows === void 0 || headRows + footRows > table.rows.length) + return; + if (kv["header-rows"] !== void 0 || kv["footer-rows"] !== void 0) { + table.rowGroups = { + headRows, + bodies: [{ headRows: 0, bodyRows: table.rows.length - headRows - footRows }], + footRows + }; + } + } + function positional(value, allowed) { + return value?.split(",").map((raw) => { + const item = raw.trim(); + return allowed.has(item) ? item : void 0; + }) ?? []; + } function peekBlockAttributes(lexer, firstLine) { if (!/^\{/.test(firstLine ?? lexer.peek())) return false; @@ -1483,7 +1721,7 @@ var carve = (() => { } if (RE_FOOTNOTE_DEF.test(line2)) return parseFootnoteDef(lexer); - if (leadingWhitespace(line2) === 0 && isLinkDefLine(line2)) { + if (leadingWhitespace(line2) === 0 && isLinkDefLine(line2) && !lexer.literalLazyLinkDefLines.has(lexer.lineNumber(lexer.pos))) { lexer.consume(); return null; } @@ -1610,13 +1848,13 @@ var carve = (() => { const fenceStartIndex = lexer.pos; const open = lexer.consume(); const m = RE_FENCE.exec(open); - const indent2 = m[1].length; + const indent3 = m[1].length; const marker = m[2]; const lang = m[3] || void 0; const headerRaw = m[4] ?? m[6]; const labelRaw = m[5] ?? m[7] ?? m[8]; const header = headerRaw ? headerRaw.slice(1, -1) : void 0; - const label = labelRaw ? labelRaw.slice(1, -1) : void 0; + const label2 = labelRaw ? labelRaw.slice(1, -1) : void 0; const closeRe = fenceCloseRe(marker); const lines = []; while (!lexer.eof()) { @@ -1626,7 +1864,7 @@ var carve = (() => { break; } lexer.consume(); - lines.push(ln.slice(Math.min(indent2, leadingWhitespace(ln)))); + lines.push(ln.slice(Math.min(indent3, leadingWhitespace(ln)))); } const fenceEndIndex = lexer.pos; const cb = { type: "code_block", content: lines.join("\n") }; @@ -1634,8 +1872,8 @@ var carve = (() => { cb.lang = lang; if (header !== void 0) cb.header = header; - if (label !== void 0) - cb.label = label; + if (label2 !== void 0) + cb.label = label2; let lookahead = 0; while (!lexer.eof() && isBlankLine(lexer.peek(lookahead))) lookahead++; @@ -1670,7 +1908,8 @@ var carve = (() => { lexer.consume(); lines.push(ln); } - return { type: "raw_block", format, content: lines.join("\n") }; + const content = lines.length > 0 && lines.every((line2) => line2 === "") ? "\n".repeat(lines.length) : lines.join("\n"); + return { type: "raw_block", format, content }; } var RE_ANY_COLON_CLOSER = /^[ \t]*(:{3,})[ \t]*$/; var RE_ANY_FENCE_CLOSER = new RegExp("^[ \\t]*([`~]{3,})" + FENCE_TRAILING_WS); @@ -1911,7 +2150,7 @@ var carve = (() => { function parseFootnoteDef(lexer) { const defLineIndex = lexer.pos; const m = RE_FOOTNOTE_DEF.exec(lexer.consume()); - const label = m[1]; + const label2 = m[1]; const bodyLines = [m[2]]; const bodyLineNumbers = [lexer.lineNumber(defLineIndex)]; let pendingBlanks = 0; @@ -1953,13 +2192,13 @@ var carve = (() => { break; } } - if (!lexer.footnoteDefs.has(label)) { + if (!lexer.footnoteDefs.has(label2)) { const sub = nestedSubLexer(lexer, bodyLines, defLineIndex, bodyLineNumbers); - lexer.footnoteDefs.set(label, parseBlocks(sub, 0)); + lexer.footnoteDefs.set(label2, parseBlocks(sub, 0)); if (lexer.hasDocumentOffsets) { const lastIndex = Math.max(defLineIndex, lexer.pos - 1); const lastLine = lexer.lines[lastIndex] ?? ""; - lexer.footnoteDefPos.set(label, { + lexer.footnoteDefPos.set(label2, { startLine: lexer.lineNumber(defLineIndex), endLine: lexer.lineNumber(lastIndex), startColumn: lexer.lineStartColumn(defLineIndex), @@ -1979,7 +2218,7 @@ var carve = (() => { const kind2 = m[2]; const isFigureGroup = kind2 === "figure" && m[3] === void 0 && m[4] === void 0 && !lexer.inFigureGroup; const titleText = m[3] !== void 0 ? m[3].slice(1, -1) : void 0; - const label = m[4] !== void 0 ? m[4].slice(1, -1) : void 0; + const label2 = m[4] !== void 0 ? m[4].slice(1, -1) : void 0; const inner = collectColonFenceBody(lexer, { kind: "admonition", lineIndex: openLineIndex, @@ -2015,8 +2254,8 @@ var carve = (() => { startColumn: lexer.lineStartColumn(openLineIndex) + titleStart }); } - if (label !== void 0) { - node.label = label; + if (label2 !== void 0) { + node.label = label2; } return node; } @@ -2209,7 +2448,8 @@ var carve = (() => { stanzas.push(stanza); const children = stanzas.map((lines) => { const anchorable = lexer.hasDocumentOffsets && lines.every((l) => l.aligned); - const joined = lines.map((line2) => line2.text).join("\n"); + const terminalCommentGuard = lines.at(-1)?.comment ? "\uE001" : ""; + const joined = lines.map((line2) => line2.text).join("\n") + terminalCommentGuard; const firstLineNumber = lexer.lineNumber(lines[0].lineIndex); const breakPos = (index2) => { if (!lexer.hasDocumentOffsets) @@ -2244,6 +2484,30 @@ var carve = (() => { column: lexer.lineStartColumn(line2.lineIndex) })) }) : inlineSource({ anchored: false })); + if (terminalCommentGuard) { + const removeGuard = (nodes) => { + for (let index2 = 0; index2 < nodes.length; index2++) { + const node2 = nodes[index2]; + const record = node2; + for (const key2 of ["value", "content"]) { + const value = record[key2]; + if (typeof value === "string" && value.endsWith(terminalCommentGuard)) { + record[key2] = value.slice(0, -terminalCommentGuard.length); + if (node2.type === "text" && record.value === "") + nodes.splice(index2, 1); + return true; + } + } + for (const key2 of ["children", "inline", "content"]) { + const value = record[key2]; + if (Array.isArray(value) && removeGuard(value)) + return true; + } + } + return false; + }; + removeGuard(parsed); + } const breakIndex = /* @__PURE__ */ new Map(); const boundaryLines = /* @__PURE__ */ new Set(); const INLINE_SLOTS = ["children", "inline", "content"]; @@ -2414,7 +2678,7 @@ var carve = (() => { const openLineIndex = lexer.pos; const m = RE_DIV_OPEN.exec(lexer.consume()); const fence = m[1].length; - const label = m[2] !== void 0 ? m[2].slice(1, -1) : void 0; + const label2 = m[2] !== void 0 ? m[2].slice(1, -1) : void 0; const inner = collectColonFenceBody(lexer, { kind: "div", lineIndex: openLineIndex, @@ -2422,8 +2686,8 @@ var carve = (() => { }); const subLexer2 = nestedSubLexer(lexer, inner.map((line2) => line2.text), openLineIndex + 1); const node = { type: "div", children: parseBlocks(subLexer2, 0) }; - if (label !== void 0) { - node.label = label; + if (label2 !== void 0) { + node.label = label2; } return node; } @@ -2442,6 +2706,7 @@ var carve = (() => { openedCommentAtColumn: false, inTable: false, invisibleAtColumn: false, + commentAtColumn: false, inFootnoteBody: false, quoteInner: null, absorbingFence: false, @@ -2679,6 +2944,10 @@ var carve = (() => { closeBlockQuoteParagraph(state); return null; } + if (RE_COMMENT_LINE.test(content) && commentFenceRun(content) === void 0) { + closeBlockQuoteParagraph(state); + return null; + } if (RE_HEADING.test(content) || isTableRow(content) || RE_HR.test(content)) { state.inTable = isTableRow(content); closeBlockQuoteParagraph(state); @@ -2779,6 +3048,10 @@ var carve = (() => { break; const lineIndex = lexer.pos; lexer.consume(); + const lazyLinkDef = isLinkDefLine(ln); + if (lazyLinkDef) { + lexer.literalLazyLinkDefLines.add(lexer.lineNumber(lineIndex)); + } inner.push(ln); innerLineNumbers.push(lexer.lineNumber(lineIndex)); trackBlockQuoteLazyState(ln, state, (fence) => quotedCommentHasCloser(lexer, fence, lineIndex), (marker) => quotedFenceHasCloser(lexer, marker, lineIndex, fenceCloserMemo)); @@ -3020,6 +3293,9 @@ var carve = (() => { function insideOpenFence(state) { return state.inFence || state.inComment || state.divDepth > 0; } + function insideOpenQuoteParagraph(state) { + return state.quoteInner !== null && blockQuoteParagraphOpen(state.quoteInner); + } function opaqueSpanEnd(scan, i) { const line2 = scan.at(i); if (line2 === void 0) @@ -3131,6 +3407,22 @@ var carve = (() => { } return Math.min(Math.max(probe.pos, 1), limit); } + function attachesAtDocumentColumnZero(lexer) { + const root = lexer.rootLines; + if (!root) + return true; + const line2 = root[lexer.lineNumber(lexer.pos) - 1]; + if (line2 === void 0) + return true; + let rest = line2; + for (; ; ) { + const m = /^[ \t]*>[ \t]?/.exec(rest); + if (!m) + break; + rest = rest.slice(m[0].length); + } + return leadingWhitespace(rest) === 0; + } function collectAttachedBlock(lexer, isBoundary, transform) { const fenced = fencedBlockEnd({ at: (offset) => { @@ -3229,6 +3521,11 @@ var carve = (() => { return { leavesParagraphOpen: bottomBlockLeavesParagraphOpen(bottom), endsOnTableRow: quote === null && isTableRow(bottom), + // A bare `+` at the bottom of the marker line is the CONTINUATION MARKER + // (§17 L3), and what it names is a document-column-0 block. It is not + // prose, so it opens no paragraph an INDENTED line could fold into - see + // the fold branch that reads this (markup-carve/carve#1436). + bottomIsContinuationMarker: quote === null && isContinuationMarker(bottom), quote }; } @@ -3282,11 +3579,14 @@ ${content}`; state.quoteInner = null; const wasInvisibleAtColumn = state.invisibleAtColumn; state.invisibleAtColumn = false; + const wasCommentAtColumn = state.commentAtColumn; + state.commentAtColumn = false; if (state.inFootnoteBody && !isBlankLine(content) && indentColumns(content, FOOTNOTE_BODY_COLUMN) < FOOTNOTE_BODY_COLUMN) { state.inFootnoteBody = false; } if (state.inFootnoteBody) { state.invisibleAtColumn = wasInvisibleAtColumn; + state.commentAtColumn = wasCommentAtColumn; state.lazyFoldable = false; state.inDefList = false; return; @@ -3297,6 +3597,7 @@ ${content}`; state.inComment = false; state.lazyFoldable = state.lazyFoldableBeforeComment && !state.openedCommentAtColumn; state.invisibleAtColumn = state.openedCommentAtColumn; + state.commentAtColumn = state.openedCommentAtColumn; } else { state.lazyFoldable = false; } @@ -3351,7 +3652,7 @@ ${content}`; return; } if (RE_HEADING.test(content)) { - state.lazyFoldable = true; + state.lazyFoldable = false; state.inDefList = false; return; } @@ -3370,6 +3671,7 @@ ${content}`; if (atContentColumn && RE_INVISIBLE_BLOCK_LEAD.test(content) && (RE_COMMENT_LINE.test(content) || RE_FOOTNOTE_DEF.test(content) || isLinkDefLine(content))) { state.inFootnoteBody = RE_FOOTNOTE_DEF.test(content); state.invisibleAtColumn = true; + state.commentAtColumn = RE_COMMENT_LINE.test(content); state.lazyFoldable = false; state.inDefList = false; return; @@ -3501,10 +3803,13 @@ ${content}`; const contentCol = isTask ? baseIndent + 2 + (la ? line2.length - mline.length : 0) : baseIndent + (line2.length - leadingWhitespace(line2) - content.length); lexer.consume(); if (isContinuationMarker(content)) { - const { lines: attached, lineNumbers: attachedLineNumbers, startLineIndex: attachedStartLineIndex } = collectAttachedBlock(lexer, isItemAttachBoundary, (a) => sliceColumns(a, baseIndent)); + const attachesHere = attachesAtDocumentColumnZero(lexer); + const { lines: attached, lineNumbers: attachedLineNumbers, startLineIndex: attachedStartLineIndex } = attachesHere ? collectAttachedBlock(lexer, isItemAttachBoundary, (a) => sliceColumns(a, baseIndent)) : { lines: [], lineNumbers: [], startLineIndex: lexer.pos }; while (!lexer.eof() && isContinuationMarker(lexer.peek())) { const plusLineIndex = lexer.pos; lexer.consume(); + if (!attachesAtDocumentColumnZero(lexer)) + break; const more = collectAttachedBlock(lexer, isItemAttachBoundary, (a) => sliceColumns(a, baseIndent)); if (more.lines.length === 0) break; @@ -3540,6 +3845,7 @@ ${content}`; lazyFoldableBeforeComment: false, openedCommentAtColumn: false, invisibleAtColumn: false, + commentAtColumn: false, inFootnoteBody: false, absorbingFence: false, divDepth: 0, @@ -3580,6 +3886,8 @@ ${content}`; lexer.consume(); pendingBlanks = 0; pendingBlankLineNumbers = []; + if (!attachesAtDocumentColumnZero(lexer)) + continue; plusSeparators.add(nested.length); nested.push(""); nestedLineNumbers.push(plusLineNumber); @@ -3602,7 +3910,7 @@ ${content}`; } pendingBlanks = 0; pendingBlankLineNumbers = []; - const isMarker = !insideOpenFence(lazyState) && (RE_ORDERED.test(l) || RE_UNORDERED.test(l) || RE_TASK.test(l) || // An abutting-attr bullet (`-{.x} item`) is a marker too. It no + const isMarker = !insideOpenFence(lazyState) && !insideOpenQuoteParagraph(lazyState) && (RE_ORDERED.test(l) || RE_UNORDERED.test(l) || RE_TASK.test(l) || // An abutting-attr bullet (`-{.x} item`) is a marker too. It no // longer reaches here via §10 interruption (bullets do not // interrupt), so the sub-list nesting path must recognize it // directly to keep nesting. @@ -3639,13 +3947,21 @@ ${content}`; // and nowhere else, so a column-0 line below it reaches no container // (§24 C3) and ends the item, the same answer `- %% c` gives one // spelling over (PART 1 S4, markup-carve/carve#1280). - ((lazyState.lazyFoldable || lazyState.inComment && lazyState.lazyFoldableBeforeComment || // AN INVISIBLE BLOCK AT THE COLUMN ENDED THE PARAGRAPH, NOT THE ITEM + // A BARE CONTINUATION MARKER FOLDS ONLY COLUMN 0 (§17 L3, + // markup-carve/carve#1436). While the item has collected nothing, its + // lead is an empty first-block item waiting for a flush-left block: a + // column-0 line is the block the marker names and belongs here, and an + // INDENTED line is not attached at all - it falls through to the + // ordinary column rules. `* * +` / ` x` folded a column-1 line into the + // outer item, which is below that item's content column and reaches no + // container. + !(leadState.bottomIsContinuationMarker && nested.length === 0 && leadingWhitespace(l) > 0) && ((lazyState.lazyFoldable || lazyState.inComment && lazyState.lazyFoldableBeforeComment || // AN INVISIBLE BLOCK AT THE COLUMN ENDED THE PARAGRAPH, NOT THE ITEM // (markup-carve/carve#1364). The item goes on collecting, so a line // still indented belongs to it and starts a paragraph of its own // there (corpus 197, 277-3, 358). The container ends at document // column 0, which is the line this test excludes and which is all // that separates 358 from 357-2. - lazyState.invisibleAtColumn && indentColumns(l, contentCol) > 0) && !lazyContinuationEndsList(l, lexer) || // A list marker indented past the base column but BELOW the content + lazyState.commentAtColumn && indentColumns(l, contentCol) > 0) && !lazyContinuationEndsList(l, lexer) || // A list marker indented past the base column but BELOW the content // column folds into the lead text rather than ending the list. Under // symmetric §10 no list marker interrupts a paragraph, so on the // recursive reparse it stays folded: `1. a`/` 1. b`, `- a`/` - b`, @@ -3654,7 +3970,9 @@ ${content}`; // a sibling list, §11 -- so only a below-content indented one folds.) indentColumns(l, baseIndent + 1) > baseIndent && (RE_TASK.test(l) || RE_UNORDERED.test(l) || RE_ORDERED.test(l) || extractItemAttr(l) !== null))) { let lazyLine = l; - if (lazyState.inDefList && indentColumns(l, contentCol) < contentCol) { + if (lexer.literalLazyLinkDefLines.has(lexer.lineNumber(lexer.pos))) { + lazyLine = l.replace(/^[ \t]+/, ""); + } else if (lazyState.inDefList && indentColumns(l, contentCol) < contentCol) { lazyLine = l.replace(/^[ \t]+/, ""); } else if (indentColumns(l, contentCol) < contentCol && lineOpensBlock(l.replace(/^[ \t]+/, ""))) { lazyLine = " " + l.replace(/^[ \t]+/, ""); @@ -3875,19 +4193,64 @@ ${content}`; header = true; i++; } - const align = TABLE_ALIGNMENT_MARKERS.get(src[i] ?? ""); - if (align !== void 0) + const markerStart = i; + let align; + let valign; + let inheritedHorizontal = false; + let invalidAxis = src[i] === "^" || src[i] === "v" || src[i] === "~" && (src[i + 1] === "<" || src[i + 1] === ">"); + if (src[i] === "?" && src[i + 1] !== void 0 && "^~v".includes(src[i + 1])) { + inheritedHorizontal = true; + valign = src[i + 1] === "^" ? "top" : src[i + 1] === "~" ? "middle" : "bottom"; + i += 2; + } + while (!inheritedHorizontal && src[i] !== void 0 && "<>~^v?".includes(src[i])) { + const marker = src[i]; + if (marker === "?") { + invalidAxis = true; + break; + } else if (marker === "<" || marker === ">" || marker === "~") { + if (align === void 0) { + align = marker === "<" ? "left" : marker === ">" ? "right" : "center"; + } else if (marker === "~" && valign === void 0) { + valign = "middle"; + } else { + invalidAxis = true; + break; + } + } else { + if (valign !== void 0) { + invalidAxis = true; + break; + } + valign = marker === "^" ? "top" : "bottom"; + } i++; + } + const validRun = i > markerStart && !invalidAxis && (align !== void 0 || inheritedHorizontal) && (src[i] === " " || src[i] === "{" || !inheritedHorizontal && src[i] !== void 0 && "<>~^v?".includes(src[i])); + if (!validRun) { + i = markerStart; + align = void 0; + valign = void 0; + inheritedHorizontal = false; + } const block = readCellAttributeBlock(src, i); - const attrs = block?.attrs; + let attrs = block?.attrs; if (block) i += block.length; + if (i > 0 && src[i] !== " ") { + i = 0; + header = false; + align = void 0; + valign = void 0; + inheritedHorizontal = false; + attrs = void 0; + } if (i > 0) { const content = trimCellPadding(src.slice(i)); - if (align !== void 0 && attrs !== void 0) - return { header, align, attrs, content }; - if (align !== void 0) - return { header, align, content }; + if ((align !== void 0 || valign !== void 0) && attrs !== void 0) + return { header, ...align ? { align } : {}, ...valign ? { valign } : {}, attrs, content }; + if (align !== void 0 || valign !== void 0) + return { header, ...align ? { align } : {}, ...valign ? { valign } : {}, content }; if (attrs !== void 0) return { header, attrs, content }; return { header, content }; @@ -3990,12 +4353,14 @@ ${content}`; const lineNo = lexer.lineNumber(lineIndex); const lineCol = lexer.lineStartColumn(lineIndex); const raw = splitTableRowSpans(rowBody).map(({ text: src, start }) => { - const { header, span: span2, align, attrs, content } = parseCellMarkers(src); + const { header, span: span2, align, valign, attrs, content } = parseCellMarkers(src); const c = { header, raw: content, openRun: openVerbatimRun(content) }; if (span2) c.span = span2; if (align) c.align = align; + if (valign) + c.valign = valign; if (attrs) c.attrs = attrs; if (canPosition) { @@ -4069,6 +4434,8 @@ ${content}`; cell.span = c.span; if (c.align) cell.align = c.align; + if (c.valign) + cell.valign = c.valign; if (c.attrs) cell.attrs = c.attrs; if (c.pos) @@ -4131,7 +4498,7 @@ ${content}`; return table; } function splitTableRowSpans(line2, carried) { - const cells = []; + const cells2 = []; let buf = ""; let cellIndex = 0; let openRun = carried?.[0] ?? 0; @@ -4161,7 +4528,7 @@ ${content}`; continue; } if (ch === "|" && openRun === 0) { - cells.push({ text: buf, start: cellStart }); + cells2.push({ text: buf, start: cellStart }); buf = ""; cellStart = i + 1; cellIndex++; @@ -4171,8 +4538,8 @@ ${content}`; buf += ch; } if (scanEnd < line2.length || trimStructural(buf) !== "") - cells.push({ text: buf, start: cellStart }); - return cells; + cells2.push({ text: buf, start: cellStart }); + return cells2; } function splitTableRow(line2) { return splitTableRowSpans(line2).map((cell) => cell.text); @@ -4293,7 +4660,7 @@ ${content}`; const ln = lexer.peek(); if (isBlankLine(ln)) break; - if (!flattened && lines.length > 0 && startsInterruptingBlock(lexer) && !(RE_ADMONITION_CLOSE.test(ln) && lines.some((line2) => isLiteralColonFenceLine(line2)))) + if (!flattened && lines.length > 0 && !lexer.literalLazyLinkDefLines.has(lexer.lineNumber(lexer.pos)) && startsInterruptingBlock(lexer) && !(RE_ADMONITION_CLOSE.test(ln) && lines.some((line2) => isLiteralColonFenceLine(line2)))) break; lexer.consume(); lines.push(ln); @@ -4549,11 +4916,12 @@ ${content}`; } return true; } - var RE_CRITIC_INS = /^\{\+((?:[^+]|\+(?!\}))*)\+\}/; - var RE_CRITIC_DEL = /^\{-((?:[^-]|-(?!\}))*)-\}/; + var RE_CRITIC_INS = /^\{\+((?:[^+]|\+(?!\}))+)\+\}/; + var RE_CRITIC_DEL = /^\{-((?:[^-]|-(?!\}))+)-\}/; var RE_CRITIC_SUB = /^\{~([^}]*)~>([^}]*)~\}/; - var RE_CRITIC_CMT = /^\{#([^}]*)#\}/; - var RE_FORCED_EMPHASIS = /^\{([/*_^,~=])([\s\S]+?)\1\}/; + var RE_CRITIC_CMT = /^\{#([^}]+)#\}/; + var RE_BRACED_EN_DASH = /^\{--\}/; + var RE_FORCED_EMPHASIS = /^\{([/*_^,~=])(?!\1\})([\s\S]+?)\1\}/; var FORCED_TYPE = { "/": "emphasis", "*": "strong", @@ -4566,12 +4934,17 @@ ${content}`; var RE_MENTION = /^@([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/; var RE_TAG = /^#([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/; var SMART_TOKENS = [ + ["<-->", "\u2194", "left_right_arrow"], ["<->", "\u2194", "left_right_arrow"], + ["-->", "\u2192", "rightwards_arrow"], + ["<--", "\u2190", "leftwards_arrow"], + ["<=>", "\u21D4", "left_right_double_arrow"], + ["==>", "\u21D2", "rightwards_double_arrow"], + ["<==", "\u21D0", "leftwards_double_arrow"], ["(tm)", "\u2122", "trademark"], ["...", "\u2026", "ellipsis"], ["->", "\u2192", "rightwards_arrow"], ["<-", "\u2190", "leftwards_arrow"], - ["=>", "\u21D2", "rightwards_double_arrow"], ["<=", "\u2264", "less_than_or_equal"], [">=", "\u2265", "greater_than_or_equal"], ["!=", "\u2260", "not_equal"], @@ -4595,6 +4968,7 @@ ${content}`; return "\u2014".repeat(em) + "\u2013".repeat(en); } var isAlnum = (ch) => /[A-Za-z0-9]/.test(ch); + var isFlankSpace = (ch) => /[ \t\n\r\u00a0\ue000]/.test(ch); var isQuoteOpenContext = (prev) => prev === "" || // `=` opens a quote so an attribute-like `key="value"` / `="x"` gets an // opening curly quote; `:` opens too (`:"q"` -> `:“q”`), matching carve-rs. // PART 7's four characters PLUS the NO-BREAK SPACE, not `\s`. @@ -4635,6 +5009,14 @@ ${content}`; let n = 0; while (text[i + n] === "-") n++; + let start = i; + while (start > 0 && text[start - 1] === "-") + start--; + const before = start > 0 ? text[start - 1] : ""; + const after = text[i + n] ?? ""; + if ((before === "" || isFlankSpace(before)) && after !== "" && !isFlankSpace(after)) { + return { out: text.slice(i, i + n), len: n, kind: "literal_hyphen_run" }; + } return { out: allocateDashes(n), len: n, kind: "dash_run" }; } const c = text[i]; @@ -4654,8 +5036,8 @@ ${content}`; } return null; } - function parseRefLabelInlines(label) { - return scanInline(label, inlineSource(), false); + function parseRefLabelInlines(label2) { + return scanInline(label2, inlineSource(), false); } function parseInline(text, abbrDefs, linkDefs = /* @__PURE__ */ new Map(), source = inlineSource(), captionContext = false) { const nodes = applyAbbreviations(scanInline(text, source, false, captionContext), abbrDefs); @@ -4741,6 +5123,25 @@ ${content}`; }; while (i < text.length) { const c = text[i]; + const code = text.charCodeAt(i); + if (activeMatchers.length === 0 && (code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 32 || code === 9)) { + const start = i; + do { + i++; + if (i >= text.length) + break; + const next = text.charCodeAt(i); + if (!(next >= 48 && next <= 57 || next >= 65 && next <= 90 || next >= 97 && next <= 122 || next === 32 || next === 9)) { + break; + } + } while (true); + const value = text.slice(start, i); + if (!buf) + bufStart = start; + buf += value; + bufLast = value[value.length - 1]; + continue; + } const rest = text.slice(i); if (c === "\\" && text[i + 1] === "\n") { flush(); @@ -4774,6 +5175,12 @@ ${content}`; { const prevForQuote = buf.length ? bufLast : out.length ? lastEmittedGlyph(out) : ""; const st = smartToken(text, i, prevForQuote); + if (st && st.kind === "literal_hyphen_run") { + buf += st.out; + bufLast = st.out[st.out.length - 1]; + i += st.len; + continue; + } if (st) { flush(); if (st.kind === "dash_run") { @@ -4870,13 +5277,11 @@ ${content}`; } if (c === "!" && text[i + 1] === "`") { const { end, closed, openLen } = verbatimSpanEnd(text, i + 1); - if (closed) { - flush(); - const content = stripVerbatimPadding(text.slice(i + 1 + openLen, end - openLen)); - out.push(withPos({ type: "literal_inline", content }, source, text, i, end)); - i = end; - continue; - } + flush(); + const content = closed ? stripVerbatimPadding(text.slice(i + 1 + openLen, end - openLen)) : text.slice(i + 1 + openLen).replace(/[ \t\n\r]+$/, ""); + out.push(withPos({ type: "literal_inline", content }, source, text, i, end)); + i = end; + continue; } if (c === "!" && text[i + 1] === "[") { const closeAbs = bracketClose[i + 1]; @@ -5136,6 +5541,12 @@ ${content}`; i += del[0].length; continue; } + if (hasBrace && RE_BRACED_EN_DASH.test(rest)) { + flush(); + out.push(withPos({ type: "smart_punctuation", kind: "en_dash", value: "{--}" }, source, text, i, i + 4)); + i += 4; + continue; + } const cmt = hasBrace ? RE_CRITIC_CMT.exec(rest) : null; if (cmt) { flush(); @@ -5269,6 +5680,8 @@ ${content}`; continue; if (before && /[A-Za-z0-9_]/.test(before)) continue; + if (delim === "=" && after === ">") + continue; if ((delim === "/" || delim === "_") && before === "/") continue; const close = cachedFindEmphasisClose(text, i + 1, delim, noClose); @@ -5586,7 +5999,7 @@ ${content}`; return false; return ATTR_PAYLOAD.test(inner); } - var ATTR_ITEM_SRC = `(?:#[a-zA-Z_][\\w-]*)|(?:\\.[a-zA-Z_][\\w-]*)|(?:[a-zA-Z_][\\w-]*=(?:"(?:[^"\\\\]|\\\\.)*"|'(?:[^'\\\\]|\\\\.)*'|[^ \\t\\n\\r]+))|(?::(?:[A-Za-z0-9]{1,8}(?:-[A-Za-z0-9]{1,8})*)?)|(?:[a-zA-Z_][\\w-]*)`; + var ATTR_ITEM_SRC = `(?:#[a-zA-Z_][\\w-]*)|(?:\\.[a-zA-Z_][\\w-]*)|(?:[a-zA-Z_][\\w-]*=(?:"(?:[^"\\\\]|\\\\.)*"|'(?:[^'\\\\]|\\\\.)*'|[^ \\t\\n\\r]+))|(?::(?:[A-Za-z0-9]{1,8}(?:-[A-Za-z0-9]{1,8})*)?)|(?:[a-zA-Z][\\w-]*)`; var ATTR_PAYLOAD = new RegExp(`^[ \\t\\n\\r]*(?:(?:${ATTR_ITEM_SRC})(?:[ \\t\\n\\r]+(?:${ATTR_ITEM_SRC}))*[ \\t\\n\\r]*)?$`); function isValidInlineAttrPayload(inner) { return isValidAttrPayload(inner) && !inlineAttrPayloadHasTab(inner); @@ -5614,7 +6027,7 @@ ${content}`; if (!order.includes(slot)) order.push(slot); }; - const re = /(?:#([a-zA-Z_][\w-]*))|(?:\.([a-zA-Z_][\w-]*))|(?:([a-zA-Z_][\w-]*)=(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)'|([^ \t\n\r]+)))|(?:(?<=^|[ \t\n\r]):((?:[A-Za-z0-9]{1,8}(?:-[A-Za-z0-9]{1,8})*)?)(?=[ \t\n\r]|$))|(?:([a-zA-Z_][\w-]*))/g; + const re = /(?:#([a-zA-Z_][\w-]*))|(?:\.([a-zA-Z_][\w-]*))|(?:([a-zA-Z_][\w-]*)=(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)'|([^ \t\n\r]+)))|(?:(?<=^|[ \t\n\r]):((?:[A-Za-z0-9]{1,8}(?:-[A-Za-z0-9]{1,8})*)?)(?=[ \t\n\r]|$))|(?:([a-zA-Z][\w-]*))/g; let m; while (m = re.exec(src)) { if (m[1]) { @@ -6606,14 +7019,14 @@ ${content}`; } // dist/heading-ids.js - function normalizeHeadingRefLabel(label) { - return normalizeRefLabel(label).normalize("NFC").toLowerCase(); + function normalizeHeadingRefLabel(label2) { + return normalizeRefLabel(label2).normalize("NFC").toLowerCase(); } - function headingRefKeyFromLabel(label) { - return normalizeHeadingRefLabel(derivedRefLabel(label)); + function headingRefKeyFromLabel(label2) { + return normalizeHeadingRefLabel(derivedRefLabel(label2)); } - function derivedRefLabel(label) { - return inlineText(parseRefLabelInlines(label)); + function derivedRefLabel(label2) { + return inlineText(parseRefLabelInlines(label2)); } function deepCloneInlines(nodes) { return JSON.parse(JSON.stringify(nodes)); @@ -6715,12 +7128,17 @@ ${content}`; return out; } var SMART_TO_ASCII = { - "\u2194": "<->", + // The canonical spellings, not the deprecated ones: `=>` no longer parses + // as an arrow at all, so recovering it would produce ASCII that does not + // round-trip (markup-carve/carve#1442). + "\u2194": "<-->", "\u2122": "(tm)", "\u2026": "...", - "\u2192": "->", - "\u2190": "<-", - "\u21D2": "=>", + "\u2192": "-->", + "\u2190": "<--", + "\u21D4": "<=>", + "\u21D2": "==>", + "\u21D0": "<==", "\u2264": "<=", "\u2265": ">=", "\u2260": "!=", @@ -6838,7 +7256,7 @@ ${content}`; } return out; } - function resolveHeadingIds(doc, opts = {}) { + function resolveHeadingIdsImpl(doc, opts = {}, documentIds) { const used = /* @__PURE__ */ new Set(); const nextCounters = /* @__PURE__ */ new Map(); const targets = /* @__PURE__ */ new Map(); @@ -6850,6 +7268,7 @@ ${content}`; if (heading.attrs?.id !== void 0) { id = heading.attrs.id; used.add(id); + documentIds?.reserve(id); } else { const base = slugify(inlineText(heading.children), opts); if (!used.has(base)) { @@ -6863,6 +7282,7 @@ ${content}`; nextCounters.set(base, n + 1); } used.add(id); + documentIds?.reserve(id); heading.attrs = { ...heading.attrs, id }; } if (!targets.has(id)) @@ -6915,8 +7335,10 @@ ${content}`; if (!node || typeof node !== "object") return; const id = node.attrs?.id; - if (typeof id === "string") + if (typeof id === "string") { used.add(id); + documentIds?.reserve(id); + } for (const key2 of Object.keys(node)) { if (key2 === "pos") continue; @@ -7158,6 +7580,12 @@ ${content}`; promoteBlockImages(body); return doc; } + function resolveHeadingIds(doc, opts = {}) { + return resolveHeadingIdsImpl(doc, opts); + } + function resolveHeadingIdsWithRegistry(doc, opts, documentIds) { + return resolveHeadingIdsImpl(doc, opts, documentIds); + } var RE_HAS_CONTENT = /[^ \t\n\r]/; var RE_TRAILING_LABEL_WS = /[ \t\n\r]+$/; function captionFirstLineHasContent(children) { @@ -7272,9 +7700,9 @@ ${content}`; if (idx === -1) return void 0; const labelNodes = caption.slice(0, idx); - const label = inlineText(labelNodes).replace(RE_TRAILING_LABEL_WS, ""); - const next = (counters.get(label) ?? 0) + 1; - counters.set(label, next); + const label2 = inlineText(labelNodes).replace(RE_TRAILING_LABEL_WS, ""); + const next = (counters.get(label2) ?? 0) + 1; + counters.set(label2, next); caption[idx].n = next; onNumbered?.(labelNodes, next, attrs); return idx; @@ -7369,28 +7797,28 @@ ${content}`; function parseLocator(loc) { const s = loc.replace(/^\s+/, ""); const lower = s.toLowerCase(); - let label; + let label2; let rest = s; for (const [m, canon] of FLAT_TERMS) { if (lower.startsWith(m.toLowerCase()) && isLabelBoundary(s[m.length])) { - label = canon; + label2 = canon; rest = s.slice(m.length).replace(/^[ \t]+/, ""); break; } } - if (label === void 0) { + if (label2 === void 0) { const c = rest[0]; if (c !== void 0 && c >= "0" && c <= "9") - label = "page"; + label2 = "page"; } - if (label === void 0) + if (label2 === void 0) return s === "" ? {} : { suffixText: s }; let i = 0; while (i < rest.length && VALUE_CHAR.test(rest[i])) i++; const value = rest.slice(0, i).replace(/[ ,&\-.]+$/, ""); const suffixText = rest.slice(i).replace(/^[ \t]+/, ""); - const out = { label }; + const out = { label: label2 }; if (value !== "") out.value = value; if (suffixText !== "") @@ -7850,8 +8278,8 @@ ${content}`; if (mode === "author-date") { const parts2 = node.items.map((it) => { const d = defs.get(it.key); - const label = it.suppressAuthor ? d.year ?? String(it.number ?? "") : `${d.author ?? ""} ${d.year ?? ""}`.trim() || String(it.number ?? ""); - return `${pre(it)}${ctx.escapeHtml(label)}${loc(it)}`; + const label2 = it.suppressAuthor ? d.year ?? String(it.number ?? "") : `${d.author ?? ""} ${d.year ?? ""}`.trim() || String(it.number ?? ""); + return `${pre(it)}${ctx.escapeHtml(label2)}${loc(it)}`; }); const out2 = `(${parts2.join("; ")})`; return wrap(out2); @@ -8064,10 +8492,10 @@ ${pad}`; for (const b of ast.children) walkBlockInlines(b, (xs) => visitInlineTree(xs, onNode)); for (let k = 0; k < order.length; k++) { - const label = order[k].label; - if (label === void 0) + const label2 = order[k].label; + if (label2 === void 0) continue; - for (const b of ownValue(defs, label) ?? []) + for (const b of ownValue(defs, label2) ?? []) walkBlockInlines(b, (xs) => visitInlineTree(xs, onNode)); } return { order, refs }; @@ -8156,11 +8584,11 @@ ${pad}`; if (!isDef(child)) return true; const def = child; - const label = def.label; - if (label === void 0 || !Array.isArray(def.children)) + const label2 = def.label; + if (label2 === void 0 || !Array.isArray(def.children)) return false; - if (ownValue(defs, label) === void 0) - setOwn(defs, label, def.children); + if (ownValue(defs, label2) === void 0) + setOwn(defs, label2, def.children); return false; }); return { ...ast, children, footnoteDefs: defs }; @@ -8280,7 +8708,7 @@ ${pad}`; return opts.sourceLine && line2 !== void 0 && !hasAuthoredSourceLine(attrs) ? ` data-source-line="${line2}"` : ""; } var RENDER_MODES = /* @__PURE__ */ new Set(["interactive", "static"]); - function renderHtml(ast, opts = {}) { + function renderHtml(ast, opts = {}, seededDocumentIds) { const declared = opts.extensions?.flatMap((e) => e.semanticSpanNames ?? []) ?? []; if (declared.length > 0 && opts.semanticSpanNames === void 0) { opts = { @@ -8295,7 +8723,7 @@ ${pad}`; const prevDocIds = docIds; const prevOptions = activeRenderOptions; abbrBudget2 = budgetForDocument(ast); - docIds = collectDocumentIds(ast); + docIds = seededDocumentIds ?? collectDocumentIds(ast); activeRenderOptions = opts; try { return renderDocumentBody(ast, opts); @@ -8399,6 +8827,10 @@ ${pad}`; function renderFootnoteSection(ast, st, opts) { return outsideLink(() => renderFootnoteSectionInner(ast, st, opts)); } + var LABEL_DEFAULTS = { + footnoteBacklink: "Back to reference" + }; + var label = (opts, key2) => opts.labels?.[key2] ?? LABEL_DEFAULTS[key2]; function renderFootnoteSectionInner(ast, st, opts) { const defs = ast.footnoteDefs ?? {}; const lines = ['
', `${indent(1)}
`, `${indent(1)}
    `]; @@ -8406,7 +8838,11 @@ ${pad}`; const number = idx + 1; const body = entry.inline ? [`${indent(3)}

    ${renderInlines(entry.inline, opts)}

    `] : (ownValue(defs, entry.label) ?? []).map((b) => renderBlock(b, opts, 3)); const multiRef = entry.backrefs.length > 1; - const blink = entry.backrefs.map((rid, k) => `\u21A9${multiRef ? `${k + 1}` : ""}`).join(multiRef ? " " : ""); + const backlinkLabel = label(opts, "footnoteBacklink"); + const blink = entry.backrefs.map((rid, k) => { + const name = escapeAttr(multiRef ? `${backlinkLabel} ${k + 1}` : backlinkLabel); + return `\u21A9${multiRef ? `${k + 1}` : ""}`; + }).join(multiRef ? " " : ""); const last = body.length - 1; if (last >= 0 && /<\/p>\s*$/.test(body[last])) { body[last] = body[last].replace(/<\/p>(\s*)$/, `${blink}

    $1`); @@ -8818,12 +9254,25 @@ ${pad}`; } function renderTable(node, opts, level) { const pad = indent(level); + const tableAttrs = node.attrs ? { + ...node.attrs, + keyValues: Object.fromEntries(Object.entries(node.attrs.keyValues ?? {}).filter(([key2]) => !["aligns", "valigns", "widths", "header-rows", "footer-rows"].includes(key2))), + ...node.attrs.order ? { order: node.attrs.order.filter((key2) => !["aligns", "valigns", "widths", "header-rows", "footer-rows"].includes(key2)) } : {} + } : void 0; const lines = [ - `${pad}` + `${pad}` ]; if (node.caption) { lines.push(`${pad} ${renderInlines(node.caption, opts)}`); } + if (node.columns?.some((column) => column.width !== void 0)) { + lines.push(`${pad} `); + for (const column of node.columns) { + const style2 = column.width === void 0 ? "" : ` style="width: ${column.width * 100}%;"`; + lines.push(`${pad} `); + } + lines.push(`${pad} `); + } const grid = []; for (let r = 0; r < node.rows.length; r++) { const row = node.rows[r]; @@ -8861,11 +9310,15 @@ ${pad}`; base[c] = r; } } - let headerEnd = 0; - while (headerEnd < grid.length && grid[headerEnd].some((e) => !e.skip) && grid[headerEnd].every((e) => e.cell.header || e.skip)) { - headerEnd++; + const sourcePartition = node.attrs?.keyValues?.["header-rows"] !== void 0 || node.attrs?.keyValues?.["footer-rows"] !== void 0; + let headerEnd = sourcePartition && node.rowGroups ? node.rowGroups.headRows : 0; + if (!sourcePartition || !node.rowGroups) { + while (headerEnd < grid.length && grid[headerEnd].some((e) => !e.skip) && grid[headerEnd].every((e) => e.cell.header || e.skip)) + headerEnd++; } + const footerStart = sourcePartition && node.rowGroups ? grid.length - node.rowGroups.footRows : grid.length; const columnAlign = []; + const columnValign = []; for (let r = 0; r < headerEnd; r++) { const hr = grid[r]; for (let c = 0; c < hr.length; c++) { @@ -8875,25 +9328,45 @@ ${pad}`; for (let k = c; k < c + entry.colspan; k++) columnAlign[k] = entry.cell.align; } + for (let c = 0; c < hr.length; c++) { + const entry = hr[c]; + if (entry.skip || !entry.cell.valign) + continue; + for (let k = c; k < c + entry.colspan; k++) + columnValign[k] = entry.cell.valign; + } } for (let r = 0; r < grid.length; r++) { for (let c = 0; c < grid[r].length; c++) { - const a = grid[r][c].cell.align ?? columnAlign[c]; + const a = grid[r][c].cell.align ?? columnAlign[c] ?? node.columns?.[c]?.align; if (a) grid[r][c].align = a; + const v = grid[r][c].cell.valign ?? columnValign[c] ?? node.columns?.[c]?.valign; + if (v) + grid[r][c].valign = v; } } if (headerEnd > 0) { - const rows = grid.slice(0, headerEnd).map((r) => renderTableRowFlat(r, opts, true)); - lines.push(`${pad} ${rows.join("")}`); + lines.push(`${pad} `); + for (let r = 0; r < headerEnd; r++) { + lines.push(`${pad} ${renderTableRowFlat(grid[r], opts, true, true)}`); + } + lines.push(`${pad} `); } - if (headerEnd < grid.length) { + if (headerEnd < footerStart) { lines.push(`${pad} `); - for (let r = headerEnd; r < grid.length; r++) { + for (let r = headerEnd; r < footerStart; r++) { lines.push(`${pad} ${renderTableRowFlat(grid[r], opts)}`); } lines.push(`${pad} `); } + if (footerStart < grid.length) { + lines.push(`${pad} `); + for (let r = footerStart; r < grid.length; r++) { + lines.push(`${pad} ${renderTableRowFlat(grid[r], opts)}`); + } + lines.push(`${pad} `); + } lines.push(`${pad}`); return lines.join("\n"); } @@ -8917,12 +9390,12 @@ ${pad}`; return ""; return ` scope="${inHeaderRun ? "col" : "row"}"`; } - function renderTableRowFlat(cells, opts, inHeaderRun = false) { - const parts = [``]; - for (const entry of cells) { + function renderTableRowFlat(cells2, opts, inHeaderRun = false, promoteToHeader = false) { + const parts = [``]; + for (const entry of cells2) { if (entry.skip) continue; - const tag = entry.cell.header ? "th" : "td"; + const tag = entry.cell.header || promoteToHeader ? "th" : "td"; const attrs = []; const emitted = /* @__PURE__ */ new Set(); if (entry.rowspan > 1) { @@ -8933,8 +9406,9 @@ ${pad}`; attrs.push(`colspan="${entry.colspan}"`); emitted.add("colspan"); } - if (entry.align) { - attrs.push(`style="text-align: ${entry.align};"`); + if (entry.align || entry.valign) { + const styles = `${entry.align ? `text-align: ${entry.align};` : ""}${entry.align && entry.valign ? " " : ""}${entry.valign ? `vertical-align: ${entry.valign};` : ""}`; + attrs.push(`style="${styles}"`); emitted.add("style"); } const attrStr = cellScopeAttr(entry.cell, tag === "th", inHeaderRun) + renderAttrs(stripStructuralAttrs(entry.cell.attrs, emitted)) + (attrs.length ? " " + attrs.join(" ") : ""); @@ -8943,10 +9417,10 @@ ${pad}`; parts.push(""); return parts.join(""); } - function labelFloor(label, level) { - if (label === void 0 || label === "") + function labelFloor(label2, level) { + if (label2 === void 0 || label2 === "") return ""; - return `${indent(level)}

    ${escapeHtml(label)}

    `; + return `${indent(level)}

    ${escapeHtml(label2)}

    `; } function renderAdmonition(node, opts, level) { const pad = indent(level); @@ -9037,9 +9511,9 @@ ${pad} `; return `${escapeAttr(img.alt)}`; } var insideLink = false; - function chargeCrossrefLabel(label, target) { - if (abbrBudget2?.charge(utf8ByteLength(label)) ?? true) - return label; + function chargeCrossrefLabel(label2, target) { + if (abbrBudget2?.charge(utf8ByteLength(label2)) ?? true) + return label2; return escapeHtml(target); } function withinLink(fn) { @@ -9107,8 +9581,8 @@ ${pad} `; return renderInlines(node.children, opts); const titleAttr = node.title !== void 0 ? ` title="${escapeAttr(node.title)}"` : ""; const href = escapeAttr(sanitizeUrl(node.href, opts)); - const label = withinLink(() => renderInlines(node.children, opts)); - return `${label}`; + const label2 = withinLink(() => renderInlines(node.children, opts)); + return `${label2}`; } case "image": return renderImage(node, opts); @@ -9230,8 +9704,8 @@ ${pad} `; return chargeCrossrefLabel(renderInlines(node.resolvedText ?? [], opts), node.target); if (node.href) { const crossrefHref = escapeAttr(sanitizeUrl(node.href, opts)); - const label = chargeCrossrefLabel(withinLink(() => renderInlines(node.resolvedText ?? [], opts)), node.target); - return `${label}`; + const label2 = chargeCrossrefLabel(withinLink(() => renderInlines(node.resolvedText ?? [], opts)), node.target); + return `${label2}`; } return `</#${escapeHtml(node.target)}>`; case "caption_number": @@ -10553,10 +11027,10 @@ ${pad} `; const rows = []; for (const row of node["rows"] ?? []) { if (row.type === "table_row") { - const cells = []; + const cells2 = []; for (const cell of row["cells"] ?? []) - cells.push(extractTextContent(cell)); - rows.push(cells.join(" | ")); + cells2.push(extractTextContent(cell)); + rows.push(cells2.join(" | ")); } } return rows.join("\n"); @@ -10924,11 +11398,11 @@ ${renderBlocks2(node.children, ctx)}` : renderBlocks2(node.children, ctx); const rows = []; const aligns = []; for (const row of node.rows) { - const cells = row.cells.map((cell) => trimNonNbsp(renderInlines2(cell.children, ctx))); - const rendered = `| ${cells.join(" | ")} |`; + const cells2 = row.cells.map((cell) => trimNonNbsp(renderInlines2(cell.children, ctx))); + const rendered = `| ${cells2.join(" | ")} |`; if (row.cells.every((cell) => cell.header)) { header = rendered; - headerColumns = cells.length; + headerColumns = cells2.length; row.cells.forEach((cell, i) => { if (aligns[i] === void 0) aligns[i] = cell.align; @@ -10991,8 +11465,8 @@ ${trimNonNbsp(renderInlines2(node.caption, ctx))} if (!ast.footnoteDefs) return ""; let out = ""; - for (const [label, blocks] of Object.entries(ast.footnoteDefs)) { - out += `${withMarker(`[^${escapeMdHtml(stripControls(label))}]: `, containerContent(ctx, () => outsideLink2(() => renderBlocks2(blocks, ctx))))} + for (const [label2, blocks] of Object.entries(ast.footnoteDefs)) { + out += `${withMarker(`[^${escapeMdHtml(stripControls(label2))}]: `, containerContent(ctx, () => outsideLink2(() => renderBlocks2(blocks, ctx))))} `; } return out; @@ -11074,12 +11548,12 @@ ${trimNonNbsp(renderInlines2(node.caption, ctx))} case "symbol": return `:${stripControls(node.name)}:`; case "autolink": { - const label = stripControls(node.text ?? node.href); + const label2 = stripControls(node.text ?? node.href); if (insideLink2) { - const display = node.href.startsWith("mailto:") ? node.href.slice(7) : label; + const display = node.href.startsWith("mailto:") ? node.href.slice(7) : label2; return escapeText(stripControls(display)); } - return `[${label}](${markdownDestination(node.href)})`; + return `[${label2}](${markdownDestination(node.href)})`; } case "mention": return `@${stripControls(node.user)}`; @@ -11177,10 +11651,10 @@ ${trimNonNbsp(renderInlines2(node.caption, ctx))} const alt = escapeMarkdownLabel(node.alt); return node.title === void 0 ? `![${alt}](${src})` : `![${alt}](${src} "${escapeMdTitle(node.title)}")`; } - function markdownFenceInfo(lang, header, label) { + function markdownFenceInfo(lang, header, label2) { const rawToken = lang === void 0 ? "" : stripControls(lang).split(/[ \t\n\r]/)[0] ?? ""; const token = rawToken.includes("`") ? "" : rawToken; - const grouping = label === void 0 || label === "" ? "" : ` [${stripControls(label).replace(/[[\]`]/g, "")}]`; + const grouping = label2 === void 0 || label2 === "" ? "" : ` [${stripControls(label2).replace(/[[\]`]/g, "")}]`; if (header === void 0 || token === "") return `${token}${grouping}`; return `${token} "${escapeMdTitle(header)}"${grouping}`; @@ -11469,6 +11943,18 @@ ${trimNonNbsp(renderInlines2(node.caption, ctx))} return override ?? (authored ?? "-").repeat(3); } + // dist/source-unspellable-error.js + var SourceUnspellableError = class extends Error { + constructor(nodeType, reason) { + super(`renderCarve cannot spell ${nodeType}: ${reason}`); + __publicField(this, "nodeType"); + __publicField(this, "reason"); + this.nodeType = nodeType; + this.reason = reason; + this.name = "SourceUnspellableError"; + } + }; + // dist/render-carve.js function isWsNonNbsp(ch) { return ch === " " || ch === " " || ch === "\n" || ch === "\r"; @@ -11498,10 +11984,10 @@ ${trimNonNbsp(renderInlines2(node.caption, ctx))} } footnoteDefsByLine = /* @__PURE__ */ new Map(); documentFootnoteDefs = ast.footnoteDefs; - for (const [label, pos] of Object.entries(ast.footnoteDefPos ?? {})) { + for (const [label2, pos] of Object.entries(ast.footnoteDefPos ?? {})) { const line2 = pos?.startLine; if (line2 !== void 0 && !footnoteDefsByLine.has(line2)) - footnoteDefsByLine.set(line2, label); + footnoteDefsByLine.set(line2, label2); } const minimal = withFreshWriteBackState(() => renderWithEscapes(ast, "minimal")); const conservative = withFreshWriteBackState(() => renderWithEscapes(ast, "conservative")); @@ -11790,13 +12276,13 @@ ${body}` : body; case "thematic_break": return withAttrs(thematicBreakSpelling(node.marker, thematicBreakMarker)); case "table": - return withAttrs(renderTable3(node, ctx)); + return renderTableWithColumns(node, ctx); case "admonition": { const title = node.title !== void 0 ? ` "${renderInlines3(node.title, ctx)}"` : ""; - const label = node.label !== void 0 ? ` [${writeFlatBracketRun(node.label)}]` : ""; + const label2 = node.label !== void 0 ? ` [${writeFlatBracketRun(node.label)}]` : ""; const fence = colonFenceFor(ctx); const body = renderColonFenceBody(node.children, ctx); - return withAttrs(`${fence} ${node.kind}${title}${label} + return withAttrs(`${fence} ${node.kind}${title}${label2} ${body} ${fence}`); } @@ -11815,10 +12301,10 @@ ${fence}`); return withAttrs(fence + " |\n" + layout + (layout.endsWith("\n") ? "" : "\n") + fence); } case "div": { - const label = node.label !== void 0 ? ` [${writeFlatBracketRun(node.label)}]` : ""; + const label2 = node.label !== void 0 ? ` [${writeFlatBracketRun(node.label)}]` : ""; const fence = colonFenceFor(ctx); const body = renderColonFenceBody(node.children, ctx); - return withAttrs(`${fence}${label} + return withAttrs(`${fence}${label2} ${body} ${fence}`); } @@ -11839,9 +12325,10 @@ ${fence}${caption}`); return renderImage3(node); case "raw_block": { const fence = safeFence2(node.content, 3); + const content = protectVerbatim(node.content); + const closerSeparator = node.content === "" || /^\n+$/.test(node.content) ? "" : "\n"; return withAttrs(`${fence}=${escapeFormat(node.format)} -${protectVerbatim(node.content)} -${fence}`); +${content}${closerSeparator}${fence}`); } case "abbreviation_def": return `*[${escapeAbbr(node.abbr)}]: ${escapePlainLine(node.expansion)}`; @@ -11866,6 +12353,28 @@ ${fence}`); } } } + function renderTableWithColumns(node, ctx) { + if (!node.columns?.length) { + const attrs2 = renderBlockAttrs(node.attrs); + const body = renderTable3(node, ctx); + return attrs2 ? `${attrs2} +${body}` : body; + } + const keyValues = { ...node.attrs?.keyValues ?? {} }; + const join = (field, key2) => { + if (keyValues[key2] === void 0 && node.columns.some((column) => column[field] !== void 0)) { + keyValues[key2] = node.columns.map((column) => column[field] ?? "").join(","); + } + }; + join("align", "aligns"); + join("valign", "valigns"); + if (keyValues.widths === void 0 && node.columns.some((column) => column.width !== void 0)) { + keyValues.widths = node.columns.map((column) => column.width === void 0 ? "" : String(column.width * 100)).join(","); + } + const attrs = renderBlockAttrs({ ...node.attrs ?? {}, keyValues }); + return `${attrs} +${renderTable3(node, ctx)}`; + } function renderList3(node, ctx) { ctx.listDepth++; try { @@ -11875,7 +12384,7 @@ ${fence}`); const bullet = node.bulletChar ?? "-"; const bareDot = node.ordered && node.bareMarker === true && delim === "." && node.olType === void 0 && (node.start ?? 1) === 1; node.items.forEach((item, idx) => { - const indent2 = ""; + const indent3 = ""; let prefix; if (node.ordered) { prefix = bareDot ? `${delim} ` : `${orderedMarker(counter, node.olType)}${delim} `; @@ -11892,16 +12401,16 @@ ${fence}`); let content = trimNonNbsp2(renderListItem3(item, ctx, node.tight)); const lines = content ? content.split("\n") : [""]; const first = lines.shift() ?? ""; - out += `${indent2}${prefix}${first || "+"} + out += `${indent3}${prefix}${first || "+"} `; const continuation = " ".repeat(prefix.length); for (const line2 of lines) { if (line2.startsWith(MARKER_COLUMN)) { - out += `${indent2}${line2.slice(MARKER_COLUMN.length)} + out += `${indent3}${line2.slice(MARKER_COLUMN.length)} `; continue; } - out += line2 ? `${indent2}${continuation}${line2} + out += line2 ? `${indent3}${continuation}${line2} ` : "\n"; } if (!node.tight && idx < node.items.length - 1) @@ -11929,13 +12438,13 @@ ${fence}`); return written; } } - for (const [line2, label] of footnoteDefsByLine) { - if (line2 > from && line2 < to && !footnotesWrittenInPlace.has(label)) { - const blocks = ownValue(documentFootnoteDefs, label); + for (const [line2, label2] of footnoteDefsByLine) { + if (line2 > from && line2 < to && !footnotesWrittenInPlace.has(label2)) { + const blocks = ownValue(documentFootnoteDefs, label2); if (blocks === void 0) continue; - const written = renderOneFootnoteDef(label, blocks, ctx); - footnotesWrittenInPlace.add(label); + const written = renderOneFootnoteDef(label2, blocks, ctx); + footnotesWrittenInPlace.add(label2); return written; } } @@ -11975,6 +12484,29 @@ ${fence}`); } } function renderListItemBody(item, ctx, tight) { + if (ctx.listDepth > 1 && item.children.length === 0) { + const from = item.pos?.startLine; + const to = item.pos?.endLine; + if (from !== void 0 && to !== void 0) { + for (const [line2, definition] of definitionsByLine) { + if (line2 >= from && line2 <= to && !definitionsWrittenInPlace.has(definition)) { + const written = renderBlock3(definition, ctx); + definitionsWrittenInPlace.add(definition); + return written; + } + } + for (const [line2, label2] of footnoteDefsByLine) { + if (line2 < from || line2 > to || footnotesWrittenInPlace.has(label2)) + continue; + const blocks = ownValue(documentFootnoteDefs, label2); + if (blocks === void 0) + continue; + const written = renderOneFootnoteDef(label2, blocks, ctx); + footnotesWrittenInPlace.add(label2); + return written; + } + } + } if (!tight) return renderBlocks3(item.children, ctx); if (ctx.blockDepth >= MAX_RENDER_DEPTH) @@ -12067,11 +12599,11 @@ ${fence}`); out.push(`: ${written}`); return; } - const label = line2 === void 0 ? void 0 : footnoteDefsByLine.get(line2); - const blocks = label === void 0 ? void 0 : ownValue(documentFootnoteDefs, label); - if (label !== void 0 && blocks !== void 0) { - const written = renderOneFootnoteDef(label, blocks, ctx); - footnotesWrittenInPlace.add(label); + const label2 = line2 === void 0 ? void 0 : footnoteDefsByLine.get(line2); + const blocks = label2 === void 0 ? void 0 : ownValue(documentFootnoteDefs, label2); + if (label2 !== void 0 && blocks !== void 0) { + const written = renderOneFootnoteDef(label2, blocks, ctx); + footnotesWrittenInPlace.add(label2); const [first, ...rest] = written.split("\n"); out.push(`: ${first}`); for (const l of rest) @@ -12113,12 +12645,12 @@ ${fence}`); const headerRow = first !== void 0 && first.cells.length > 0 && first.cells.every((c) => c.header); const needsDelimiter = headerRow && first.cells.some((c) => c.span !== void 0); node.rows.forEach((row, rowIndex) => { - const cells = []; + const cells2 = []; for (const cell of row.cells) { const asHeader = !(needsDelimiter && rowIndex === 0); - cells.push(renderTableCell(cell, ctx, asHeader)); + cells2.push(renderTableCell(cell, ctx, asHeader)); } - rows.push(renderTableRow(cells, renderAttrs3(row.attrs))); + rows.push(renderTableRow(cells2, renderAttrs3(row.attrs))); }); if (needsDelimiter) { rows.splice(1, 0, `|${Array.from({ length: first.cells.length }, () => "---").join("|")}|`); @@ -12130,8 +12662,8 @@ ${fence}`); function padCell(prefix, content) { return content === "" ? `${prefix} ` : `${prefix} ${content} `; } - function renderTableRow(cells, attrs) { - return `|${cells.join("|")}|${attrs}`; + function renderTableRow(cells2, attrs) { + return `|${cells2.join("|")}|${attrs}`; } function renderTableCell(cell, ctx, markHeader = true) { const attrs = renderAttrs3(cell.attrs); @@ -12140,7 +12672,9 @@ ${fence}`); return padCell(attrs, spanMarker); } const align = alignMarker(cell.align); - const prefix = `${cell.header && markHeader ? "=" : ""}${align}${attrs}`; + const valign = cell.valign === "top" ? "^" : cell.valign === "middle" ? "~" : cell.valign === "bottom" ? "v" : ""; + const inheritedHorizontal = !align && valign ? "?" : ""; + const prefix = `${cell.header && markHeader ? "=" : ""}${align}${inheritedHorizontal}${valign}${attrs}`; return padCell(prefix, renderInlines3(cell.children, ctx)); } function renderFigure3(node, ctx) { @@ -12149,14 +12683,14 @@ ${fence}`); ^ ${renderInlines3(node.caption, ctx)}`; } var EMPTY_FOOTNOTE_BODY = "{empty}"; - function renderOneFootnoteDef(label, blocks, ctx) { + function renderOneFootnoteDef(label2, blocks, ctx) { const rawBody = renderBlocks3(blocks, ctx); const body = trimNonNbsp2(blocks.length === 1 ? rawBody.replace(/\n\n/g, "\n") : rawBody); if (body === "") { - return `[^${writeFlatBracketRun(label)}]: ${EMPTY_FOOTNOTE_BODY}`; + return `[^${writeFlatBracketRun(label2)}]: ${EMPTY_FOOTNOTE_BODY}`; } const lines = body.split("\n"); - const defLines = [`[^${writeFlatBracketRun(label)}]: ${lines.shift() ?? ""}`]; + const defLines = [`[^${writeFlatBracketRun(label2)}]: ${lines.shift() ?? ""}`]; for (const line2 of lines) defLines.push(` ${line2}`); return defLines.join("\n"); @@ -12177,12 +12711,12 @@ ${fence}`); at: child.pos?.startOffset, text: renderBlockAtTop(child, ctx) })); - for (const [label, blocks] of Object.entries(ast.footnoteDefs ?? {})) { - if (footnotesWrittenInPlace.has(label)) + for (const [label2, blocks] of Object.entries(ast.footnoteDefs ?? {})) { + if (footnotesWrittenInPlace.has(label2)) continue; definitions.push({ - at: ownValue(ast.footnoteDefPos, label)?.startOffset, - text: renderOneFootnoteDef(label, blocks, ctx) + at: ownValue(ast.footnoteDefPos, label2)?.startOffset, + text: renderOneFootnoteDef(label2, blocks, ctx) }); } const ordered = definitions.every((piece) => piece.at !== void 0) ? definitions.map((piece, index2) => ({ piece, index: index2 })).sort((a, b) => a.piece.at - b.piece.at || a.index - b.index).map(({ piece }) => piece) : definitions; @@ -12284,6 +12818,9 @@ ${fence}`); case "math": return withAttrs(renderMath(node.display, node.content)); case "raw_inline": + if (node.content === "") { + throw new SourceUnspellableError("raw_inline", "an empty raw inline has no Carve source spelling"); + } return `${renderCode2(node.content)}{=${escapeFormat(node.format)}}`; case "literal_inline": return `!${renderCode2(node.content)}${renderAttrs3(node.attrs)}`; @@ -12384,14 +12921,14 @@ ${fence}`; const needsPad = content.startsWith("`") || content.endsWith("`") || content.startsWith(" ") && content.endsWith(" ") && !isCarveBlank(content); return needsPad ? `${fence} ${content} ${fence}` : `${fence}${content}${fence}`; } - function codeFenceInfo(lang, header, label) { + function codeFenceInfo(lang, header, label2) { const parts = []; if (lang) parts.push(escapeFenceToken(lang)); if (header !== void 0) parts.push(`"${header}"`); - if (label !== void 0) - parts.push(`[${writeFlatBracketRun(label)}]`); + if (label2 !== void 0) + parts.push(`[${writeFlatBracketRun(label2)}]`); return parts.join(" "); } function safeFence2(content, min) { @@ -12428,7 +12965,7 @@ ${fence}`; const value = kv[key2]; if (key2 === "lang" && isLanguageTag(value)) parts.push(`:${value}`); - else if (value === "" && isAttrIdentifier(key2)) + else if (value === "" && isBooleanAttrName(key2)) parts.push(escapeAttrKey(key2)); else parts.push(`${escapeAttrKey(key2)}=${quoteAttrValue(value)}`); @@ -12678,6 +13215,9 @@ ${fence}`; function isAttrIdentifier(text) { return /^[A-Za-z_][\w-]*$/.test(text); } + function isBooleanAttrName(text) { + return /^[A-Za-z][\w-]*$/.test(text); + } function escapeAutolinkHref(text) { return text.replace(/[\\<>]/g, "\\$&"); } @@ -12824,10 +13364,10 @@ ${fence}`; const header = node.header ? `${stripControls2(node.header)} ` : ""; - const label = node.label ? `${stripControls2(node.label)} + const label2 = node.label ? `${stripControls2(node.label)} ` : ""; - return `${header}${label}${stripControls2(node.content)} + return `${header}${label2}${stripControls2(node.content)} `; } @@ -12902,9 +13442,9 @@ ${renderBlocks4(node.children, ctx)}` : renderBlocks4(node.children, ctx); ctx.listDepth++; let out = ""; let counter = node.start ?? 1; - const indent2 = " ".repeat(ctx.listDepth - 1); + const indent3 = " ".repeat(ctx.listDepth - 1); for (const item of node.items) { - out += indent2 + (node.ordered ? `${counter}. ` : "- "); + out += indent3 + (node.ordered ? `${counter}. ` : "- "); counter++; let content = trimNonNbsp(renderBlocks4(item.children, ctx)); if (node.tight) { @@ -12935,13 +13475,13 @@ ${renderBlocks4(node.children, ctx)}` : renderBlocks4(node.children, ctx); const cols = node.rows.reduce((max, row) => Math.max(max, row.cells.length), 0); let out = ""; for (const row of node.rows) { - const cells = []; + const cells2 = []; for (let i = 0; i < cols; i++) { - cells.push(i < row.cells.length ? trimNonNbsp(renderInlines4(row.cells[i].children, ctx)) : ""); + cells2.push(i < row.cells.length ? trimNonNbsp(renderInlines4(row.cells[i].children, ctx)) : ""); } - while (cells.length > row.cells.length && cells[cells.length - 1] === "") - cells.pop(); - out += `${cells.join(" | ")} + while (cells2.length > row.cells.length && cells2[cells2.length - 1] === "") + cells2.pop(); + out += `${cells2.join(" | ")} `; } if (node.caption) @@ -12969,8 +13509,8 @@ ${target} if (!ast.footnoteDefs) return ""; let out = ""; - for (const [label, blocks] of Object.entries(ast.footnoteDefs)) { - out += `[^${stripControls2(label)}]: ${trimNonNbsp(outsideLink3(() => renderBlocks4(blocks, ctx)))} + for (const [label2, blocks] of Object.entries(ast.footnoteDefs)) { + out += `[^${stripControls2(label2)}]: ${trimNonNbsp(outsideLink3(() => renderBlocks4(blocks, ctx)))} `; } return out; @@ -13101,8 +13641,8 @@ ${target} return stripControls2(node.text); case "heading_ref": if (node.href) { - const label = renderInlines4(node.resolvedText ?? [], ctx); - return ctx.abbrBudget.charge(utf8ByteLength(label)) ? label : stripControls2(node.target); + const label2 = renderInlines4(node.resolvedText ?? [], ctx); + return ctx.abbrBudget.charge(utf8ByteLength(label2)) ? label2 : stripControls2(node.target); } return ``; case "caption_number": @@ -13177,8 +13717,8 @@ ${target} const footnotes = renderFootnoteDefs3(ast, ctx); return { text: stripBidiControls(normalize4(`${out}${footnotes}`)), expanded: ctx.expanded }; } - function chargeCrossrefLabel2(label, target, ctx) { - return ctx.abbrBudget.charge(utf8ByteLength(label)) ? label : stripControls3(target); + function chargeCrossrefLabel2(label2, target, ctx) { + return ctx.abbrBudget.charge(utf8ByteLength(label2)) ? label2 : stripControls3(target); } function style(text, codes) { return `${codes}${text}${RESET}`; @@ -13300,14 +13840,14 @@ ${style(char.repeat(width(content)), color)}`; `; } - function renderCodeBlock(content, lang, header, label) { + function renderCodeBlock(content, lang, header, label2) { let out = ""; if (header) out += `${style(header, BOLD)} `; - if (label) - out += `${style(label, BOLD)} + if (label2) + out += `${style(label2, BOLD)} `; if (lang) @@ -13331,7 +13871,7 @@ ${style(char.repeat(width(content)), color)}`; if (node.ordered) ctx.ordered[ctx.listDepth] = node.start ?? 1; const out = node.items.map((item) => { - const indent2 = " ".repeat(ctx.listDepth - 1); + const indent3 = " ".repeat(ctx.listDepth - 1); let marker; if (node.ordered) { const n = ctx.ordered[ctx.listDepth] ?? 1; @@ -13342,7 +13882,7 @@ ${style(char.repeat(width(content)), color)}`; } else { marker = style("\u2022", FG_CYAN); } - return `${indent2}${marker} ${trimNonNbsp(renderBlocks5(item.children, ctx))} + return `${indent3}${marker} ${trimNonNbsp(renderBlocks5(item.children, ctx))} `; }).join(""); ctx.listDepth--; @@ -13403,9 +13943,9 @@ ${style(char.repeat(width(content)), color)}`; return `${style(left + widths.map((w) => "\u2500".repeat(w + 2)).join(cross) + right, DIM)} `; } - function tableRow(cells, widths) { + function tableRow(cells2, widths) { const sep = style("\u2502", DIM); - const parts = cells.map((cell, i) => { + const parts = cells2.map((cell, i) => { const padding = (widths[i] ?? 0) - width(cell.plain); const content = cell.isHeader ? style(cell.content + " ".repeat(padding), BOLD) : cell.content + " ".repeat(padding); return ` ${content} `; @@ -13434,8 +13974,8 @@ ${target} if (!ast.footnoteDefs) return ""; let out = ""; - for (const [label, blocks] of Object.entries(ast.footnoteDefs)) { - out += `${style(`[^${stripControls3(label)}]`, FG_CYAN + DIM)} ${trimNonNbsp(outsideLink4(() => renderBlocks5(blocks, ctx)))} + for (const [label2, blocks] of Object.entries(ast.footnoteDefs)) { + out += `${style(`[^${stripControls3(label2)}]`, FG_CYAN + DIM)} ${trimNonNbsp(outsideLink4(() => renderBlocks5(blocks, ctx)))} `; } return out; @@ -13851,8 +14391,8 @@ ${target} "substitution": ["attrs", "newText", "oldText", "pos", "type"], "superscript": ["attrs", "children", "pos", "type"], "symbol": ["attrs", "name", "pos", "type"], - "table": ["attrs", "caption", "pos", "rowGroups", "rows", "shortCaption", "type"], - "table_cell": ["align", "attrs", "children", "header", "pos", "span", "type"], + "table": ["attrs", "caption", "columns", "pos", "rowGroups", "rows", "shortCaption", "type"], + "table_cell": ["align", "attrs", "children", "header", "pos", "span", "type", "valign"], "table_row": ["attrs", "cells", "pos", "type"], "tag": ["attrs", "name", "pos", "type"], "text": ["attrs", "pos", "type", "value"], @@ -13862,6 +14402,7 @@ ${target} var WIRE_RECORD_FIELDS = { "attrs": ["classes", "id", "keyValues", "order"], "pos": ["endColumn", "endLine", "endOffset", "startColumn", "startLine", "startOffset"], + "table.columns": ["align", "valign", "width"], "table.rowGroups": ["bodies", "footRows", "headRows"], "table.rowGroups.bodies": ["attrs", "bodyRows", "headRows", "rowHeadColumns"] }; @@ -13978,6 +14519,7 @@ ${target} "superscript": ["children", "type"], "symbol": ["name", "type"], "table": ["rows", "type"], + "table.columns": [], "table.rowGroups": ["bodies", "footRows", "headRows"], "table.rowGroups.bodies": ["bodyRows", "headRows"], "table_cell": ["children", "header", "type"], @@ -14043,10 +14585,11 @@ ${target} "substitution": { "attrs": "object", "newText": "string", "oldText": "string", "pos": "object" }, "superscript": { "attrs": "object", "children": "array", "pos": "object" }, "symbol": { "attrs": "object", "name": "string", "pos": "object" }, - "table": { "attrs": "object", "caption": "array", "pos": "object", "rowGroups": "object", "rows": "array", "shortCaption": "array" }, + "table": { "attrs": "object", "caption": "array", "columns": "array", "pos": "object", "rowGroups": "object", "rows": "array", "shortCaption": "array" }, + "table.columns": { "align": "enum:left\0right\0center", "valign": "enum:top\0middle\0bottom" }, "table.rowGroups": { "bodies": "array", "footRows": "integer>=0", "headRows": "integer>=0" }, "table.rowGroups.bodies": { "attrs": "object", "bodyRows": "integer>=0", "headRows": "integer>=0", "rowHeadColumns": "integer>=0" }, - "table_cell": { "align": "enum:left\0right\0center", "attrs": "object", "children": "array", "header": "boolean", "pos": "object", "span": "enum:rowspan\0colspan" }, + "table_cell": { "align": "enum:left\0right\0center", "attrs": "object", "children": "array", "header": "boolean", "pos": "object", "span": "enum:rowspan\0colspan", "valign": "enum:top\0middle\0bottom" }, "table_row": { "attrs": "object", "cells": "array", "pos": "object" }, "tag": { "attrs": "object", "name": "string", "pos": "object" }, "text": { "attrs": "object", "pos": "object", "value": "string" }, @@ -14146,7 +14689,7 @@ ${target} "substitution": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, "superscript": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, "symbol": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, - "table": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false }, "rowGroups": { record: "table.rowGroups", array: false } }, + "table": { "attrs": { record: "attrs", array: false }, "columns": { record: "table.columns", array: true }, "pos": { record: "pos", array: false }, "rowGroups": { record: "table.rowGroups", array: false } }, "table.rowGroups": { "bodies": { record: "table.rowGroups.bodies", array: true } }, "table.rowGroups.bodies": { "attrs": { record: "attrs", array: false } }, "table_cell": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, @@ -14265,13 +14808,13 @@ ${target} children.push(node); } children.push(...definitionListsToWire(doc.children)); - for (const [label, body] of Object.entries(doc.footnoteDefs ?? {})) { + for (const [label2, body] of Object.entries(doc.footnoteDefs ?? {})) { const node = { type: "footnote", - label, + label: label2, children: definitionListsToWire(body) }; - const pos = ownValue(doc.footnoteDefPos, label); + const pos = ownValue(doc.footnoteDefPos, label2); if (pos !== void 0) node.pos = pos; children.push(node); @@ -14664,12 +15207,12 @@ ${target} } if (child?.type === "footnote") { const node = child; - const label = typeof node.label === "string" ? node.label : node.id; - if (typeof label === "string" && Array.isArray(node.children)) { - if (ownValue(footnoteDefs, label) === void 0) { - setOwn(footnoteDefs, label, definitionListsFromWire(node.children)); + const label2 = typeof node.label === "string" ? node.label : node.id; + if (typeof label2 === "string" && Array.isArray(node.children)) { + if (ownValue(footnoteDefs, label2) === void 0) { + setOwn(footnoteDefs, label2, definitionListsFromWire(node.children)); if (node.pos !== void 0) - setOwn(footnoteDefPos, label, node.pos); + setOwn(footnoteDefPos, label2, node.pos); } continue; } @@ -14865,6 +15408,463 @@ ${target} return { version: 1, encoding: "utf-8", source, lineEndings, bom: source.startsWith("\uFEFF"), nodes }; } + // dist/fast-html.js + function accept(stats, event, start, end, activeDefinition = false) { + if (!stats) + return; + stats[event]++; + stats.consumedLines += end - start; + if (activeDefinition) + stats.activeDefinitions++; + } + function tryFastHtml(source, opts) { + return tryFastHtmlAttempt(source, opts); + } + function tryFastHtmlAttempt(source, opts, stats) { + if (opts.extensions?.length || opts.profile !== void 0 || opts.sourceLine || opts.mode !== void 0 || opts.sections === false || opts.smartTypography === false || opts.smartTypography === "source" || !isAscii(source) || /[\0\t\v\f\r]/.test(source) || source.startsWith("---") || source.includes("[^") || source.includes("^[") || source.includes("[@") || source.includes(" / +$/.test(line2))) + return void 0; + const collected = collectDefs2(lines, stats !== void 0); + if (!collected) + return void 0; + if (stats) + for (const line2 of collected.definitionLines ?? []) + accept(stats, "linkDefinitions", line2, line2 + 1, true); + return renderBlocks6(lines, collected.defs, opts, stats); + } + function isAscii(source) { + for (let i = 0; i < source.length; i++) + if (source.charCodeAt(i) > 127) + return false; + return true; + } + function collectDefs2(lines, observe) { + const defs = /* @__PURE__ */ new Map(); + const definitionLines = observe ? [] : void 0; + let last = -1; + for (let i = lines.length - 1; i >= 0; i--) { + if (lines[i].includes("]:")) { + last = i; + break; + } + } + if (last < 0) + return { defs, ...definitionLines ? { definitionLines } : {} }; + let fence; + for (let i = 0; i <= last; i++) { + const line2 = lines[i]; + if (fence) { + if (isFenceClose(line2, fence)) + fence = void 0; + continue; + } + const open = fenceOpen(line2); + if (open) { + fence = open; + continue; + } + if (!line2.includes("]:")) + continue; + const match = /^\[([^\]]+)\]:\s*(\S+?)(?:\s+"([^"]*)")?$/.exec(line2); + if (!match || match[1].startsWith("@")) + return void 0; + if (i > 0 && lines[i - 1].trim() !== "") + return void 0; + if (i + 1 < lines.length && lines[i + 1].trim() !== "") + return void 0; + defs.set(match[1], { href: match[2], ...match[3] === void 0 ? {} : { title: match[3] } }); + definitionLines?.push(i); + } + return { defs, ...definitionLines ? { definitionLines } : {} }; + } + function renderBlocks6(lines, defs, opts, stats) { + const out = []; + const sections = []; + const ids = /* @__PURE__ */ new Map(); + let i = 0; + let wrote = false; + while (i < lines.length) { + const line2 = lines[i]; + if (line2.trim() === "" || /^\[[^\]]+\]:/.test(line2)) { + i++; + continue; + } + const heading = /^(#{1,6}) +(.*)$/.exec(line2); + if (heading) { + const level = heading[1].length; + const title = heading[2].trimEnd(); + if (/[*\/`[]/.test(title) || (title.match(/:/g)?.length ?? 0) >= 2 || inlineComplex(title)) + return void 0; + while (sections.at(-1) !== void 0 && sections.at(-1) >= level) { + out.push("\n", indent2(sections.length - 1), "
"); + sections.pop(); + } + if (wrote) + out.push("\n"); + const base = slugify(title, headingIdSlugOpts(opts)); + const count = (ids.get(base) ?? 0) + 1; + ids.set(base, count); + const id = count === 1 ? base : `${base}-${count}`; + out.push(indent2(sections.length), '
\n', indent2(sections.length + 1), ``, escapeHtml(title), ``); + if (stats) + accept(stats, "headings", i, i + 1); + sections.push(level); + wrote = true; + i++; + continue; + } + if (wrote) + out.push("\n"); + const depth = sections.length; + const fence = fenceOpen(line2); + if (fence) { + if (fence.char !== "`" || line2.startsWith(" ") || line2.startsWith(">")) + return void 0; + let close = i + 1; + while (close < lines.length && !isFenceClose(lines[close], fence)) + close++; + if (close >= lines.length) + return void 0; + const infoSlot = line2.slice(fence.len); + if (infoSlot.startsWith(" ")) + return void 0; + const info = infoSlot.trim(); + if (info && !/^[A-Za-z0-9-]+$/.test(info)) + return void 0; + out.push(indent2(depth), "
");
+        for (let j = i + 1; j < close; j++)
+          out.push(escapeHtml(lines[j]), "\n");
+        out.push("
"); + if (stats) + accept(stats, "codeFences", i, close + 1); + i = close + 1; + wrote = true; + continue; + } + if (line2.startsWith("- ")) { + const rendered = renderList6(lines, i, 0, depth, defs, opts, stats); + if (!rendered) + return void 0; + out.push(rendered.html); + i = rendered.next; + wrote = true; + continue; + } + if (thematicBreak(line2)) { + out.push(indent2(depth), "
"); + if (stats) + accept(stats, "thematicBreaks", i, i + 1); + i++; + wrote = true; + continue; + } + if (decimalListItem(line2)) { + const rendered = renderOrderedList(lines, i, depth, defs, opts, stats); + if (!rendered) + return void 0; + out.push(rendered.html); + i = rendered.next; + wrote = true; + continue; + } + if (line2.startsWith("> ")) { + const start2 = i, quote = []; + while (lines[i]?.startsWith("> ")) { + const text = lines[i].slice(2); + if (blockish(text)) + return void 0; + const html = renderInline6(text, defs, opts); + if (html === void 0) + return void 0; + quote.push(html); + i++; + } + if (lines[i] !== void 0 && lines[i].trim() !== "") + return void 0; + out.push(indent2(depth), "

", quote.join("\n"), "

"); + if (stats) + accept(stats, "blockQuotes", start2, i); + wrote = true; + continue; + } + if (line2.startsWith("|")) { + const rendered = renderTable6(lines, i, depth, defs, opts, stats); + if (!rendered) + return void 0; + out.push(rendered.html); + i = rendered.next; + wrote = true; + continue; + } + if (blockish(line2)) + return void 0; + const start = i, paragraph = []; + while (lines[i] !== void 0 && lines[i].trim() !== "") { + if (blockish(lines[i])) + return void 0; + const html = renderInline6(lines[i], defs, opts); + if (html === void 0) + return void 0; + paragraph.push(html); + i++; + } + out.push(indent2(depth), "

", paragraph.join("\n"), "

"); + if (stats) + accept(stats, "paragraphs", start, i); + wrote = true; + } + while (sections.length) + out.push("\n", indent2(sections.length - 1), "
"), sections.pop(); + return out.join(""); + } + function renderInline6(text, defs, opts) { + if (inlineComplex(text)) + return void 0; + const out = []; + let i = 0, plain = 0; + while (i < text.length) { + const delimiter = text[i]; + if (!"*/`[".includes(delimiter)) { + i++; + continue; + } + out.push(escapeHtml(text.slice(plain, i))); + if (delimiter === "*" || delimiter === "/") { + const close = text.indexOf(delimiter, i + 1); + if (close <= i + 1 || /\s/.test(text[i + 1]) || /\s/.test(text[close - 1]) || i > 0 && /[A-Za-z0-9]/.test(text[i - 1]) || /[A-Za-z0-9]/.test(text[close + 1] ?? "")) + return void 0; + const inner = renderInline6(text.slice(i + 1, close), defs, opts); + if (inner === void 0) + return void 0; + const tag = delimiter === "*" ? "strong" : "em"; + out.push(`<${tag}>`, inner, ``); + i = close + 1; + } else if (delimiter === "`") { + const close = text.indexOf("`", i + 1); + if (close < 0) + return void 0; + const code = text.slice(i + 1, close); + if (/^\s|\s$/.test(code)) + return void 0; + out.push("", escapeHtml(code), ""); + i = close + 1; + } else { + const labelEnd = text.indexOf("]", i + 1); + if (labelEnd < 0) + return void 0; + const label2 = text.slice(i + 1, labelEnd); + let href, title, end; + if (text[labelEnd + 1] === "(") { + const close = text.indexOf(")", labelEnd + 2); + href = text.slice(labelEnd + 2, close); + if (close < 0 || !href || /[\s(]/.test(href)) + return void 0; + end = close + 1; + } else if (text[labelEnd + 1] === "[") { + const close = text.indexOf("]", labelEnd + 2); + if (close < 0) + return void 0; + const def = defs.get(text.slice(labelEnd + 2, close)); + if (!def) + return void 0; + href = def.href; + title = def.title; + end = close + 1; + } else + return void 0; + const inner = renderInline6(label2, defs, opts); + if (inner === void 0) + return void 0; + out.push('", inner, ""); + i = end; + } + plain = i; + } + out.push(escapeHtml(text.slice(plain))); + return out.join(""); + } + function inlineComplex(text) { + let colons = 0; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + if (`{}^\\<>_~!@$=#'"`.includes(c)) + return true; + if (c === ":" && ++colons === 2) + return true; + const tail = text.slice(i); + if (tail.startsWith("--") || tail.startsWith("...") || tail.startsWith("/*") || tail.startsWith("*/") || tail.startsWith("``") || tail.startsWith("+-") || tail.startsWith("(c)") || tail.startsWith("(r)") || tail.startsWith("(tm)")) + return true; + } + return false; + } + function renderList6(lines, start, offset, depth, defs, opts, stats) { + const out = [indent2(depth), "
    "]; + let i = start; + while (i < lines.length) { + const line2 = lines[i], leading = line2.length - line2.trimStart().length; + if (leading < offset) + break; + if (leading !== offset || !line2.slice(leading).startsWith("- ")) + return void 0; + const text = line2.slice(leading + 2); + if (!text || text.startsWith(" ") || text === "+" || blockish(text)) + return void 0; + const inline = renderInline6(text, defs, opts); + if (inline === void 0) + return void 0; + if (stats) + accept(stats, "unorderedListItems", i, i + 1); + out.push("\n", indent2(depth + 1), "
  • ", inline); + i++; + if (lines[i] !== void 0) { + const nextIndent = lines[i].length - lines[i].trimStart().length; + if (nextIndent > offset) { + if (nextIndent !== offset + 2 || !lines[i].slice(nextIndent).startsWith("- ")) + return void 0; + const nested = renderList6(lines, i, offset + 2, depth + 2, defs, opts, stats); + if (!nested) + return void 0; + out.push("\n", nested.html, "\n", indent2(depth + 1)); + i = nested.next; + } + } + out.push("
  • "); + if (i >= lines.length) + break; + if (lines[i].trim() === "") { + const next = lines.slice(i + 1).find((candidate) => candidate.trim() !== ""); + if (next && next.length - next.trimStart().length === offset && next.trimStart().startsWith("- ")) + return void 0; + break; + } + } + out.push("\n", indent2(depth), "
"); + return { html: out.join(""), next: i }; + } + function decimalListItem(line2) { + const match = /^(\d+)\. ([^ ].*)$/.exec(line2); + if (!match) + return void 0; + const number = Number(match[1]); + return Number.isSafeInteger(number) && number > 0 ? { number, text: match[2] } : void 0; + } + function renderOrderedList(lines, start, depth, defs, opts, stats) { + const first = decimalListItem(lines[start]); + if (!first) + return void 0; + const out = [indent2(depth), ""]; + let i = start, expected = first.number; + while (i < lines.length) { + const item = decimalListItem(lines[i]); + if (!item) + break; + if (item.number !== expected || blockish(item.text)) + return void 0; + const inline = renderInline6(item.text, defs, opts); + if (inline === void 0) + return void 0; + out.push("\n", indent2(depth + 1), "
  • ", inline, "
  • "); + if (stats) + accept(stats, "orderedListItems", i, i + 1); + expected++; + i++; + } + if (lines[i] !== void 0 && lines[i].trim() !== "") + return void 0; + out.push("\n", indent2(depth), ""); + return { html: out.join(""), next: i }; + } + function renderTable6(lines, start, depth, defs, opts, stats) { + const heads = cells(lines[start]), delimiter = cells(lines[start + 1] ?? ""); + if (!heads || !delimiter || !heads.length || heads.length !== delimiter.length) + return void 0; + const aligns = delimiter.map((cell) => alignment(cell)); + if (aligns.some((value) => value === false)) + return void 0; + const renderCell2 = (tag, cell, index2) => { + const inline = renderInline6(cell, defs, opts); + if (inline === void 0) + return void 0; + const scope = tag === "th" ? ' scope="col"' : ""; + const style2 = aligns[index2] ? ` style="text-align: ${aligns[index2]};"` : ""; + return `<${tag}${scope}${style2}>${inline}`; + }; + const header = heads.map((cell, index2) => renderCell2("th", cell, index2)); + if (header.some((cell) => cell === void 0)) + return void 0; + if (stats) + accept(stats, "tableRows", start, start + 2); + let i = start + 2; + const rows = []; + while (lines[i]?.trimStart().startsWith("|")) { + const row = cells(lines[i]); + if (!row || row.length !== heads.length) + return void 0; + if (stats) + accept(stats, "tableRows", i, i + 1); + rows.push(row); + i++; + } + if (!rows.length) + return void 0; + const out = [ + indent2(depth), + "\n", + indent2(depth + 1), + "\n", + indent2(depth + 2), + "", + header.join(""), + "\n", + indent2(depth + 1), + "\n", + indent2(depth + 1), + "" + ]; + for (const row of rows) { + const rendered = row.map((cell, index2) => renderCell2("td", cell, index2)); + if (rendered.some((cell) => cell === void 0)) + return void 0; + out.push("\n", indent2(depth + 2), "", rendered.join(""), ""); + } + out.push("\n", indent2(depth + 1), "\n", indent2(depth), "
    "); + return { html: out.join(""), next: i }; + } + function cells(line2) { + const trimmed = line2.trim(); + if (!trimmed.startsWith("|") || !trimmed.endsWith("|") || trimmed.includes("\\|")) + return void 0; + return trimmed.slice(1, -1).split("|").map((cell) => cell.trim()); + } + function alignment(cell) { + const left = cell.startsWith(":"), right = cell.endsWith(":"); + const core = cell.replace(/^:/, "").replace(/:$/, "").trim(); + if (core.length < 3 || !/^-+$/.test(core)) + return false; + return left && right ? "center" : right ? "right" : left ? "left" : void 0; + } + function blockish(text) { + return /^(?:\s|#|\* |\+ |- |>|\||\{|:::|```|~~~|\.{1,9} |[A-Za-z0-9]+[.)] )/.test(text) || /^(?:---+|\*\*\*+)$/.test(text); + } + function thematicBreak(line2) { + return /^(?:-{3,}|\*{3,}|_{3,})$/.test(line2); + } + function fenceOpen(line2) { + const match = /^(`{3,}|~{3,})/.exec(line2); + return match ? { char: match[1][0], len: match[1].length } : void 0; + } + function isFenceClose(line2, fence) { + const match = new RegExp(`^${fence.char}{${fence.len},}\\s*$`).exec(line2); + return match !== null; + } + function indent2(level) { + return " ".repeat(level); + } + // node_modules/parse5/dist/common/unicode.js var UNDEFINED_CODE_POINTS = /* @__PURE__ */ new Set([ 65534, @@ -23508,24 +24508,24 @@ ${target} const rows = []; built.forEach((sourceCells, r) => { const marks = new Set(carried.map((entry) => entry.index)); - const cells = []; + const cells2 = []; const opened = []; const continuation = (span2, header) => { this.enter(depth); return { type: "table_cell", header, span: span2, children: [] }; }; const fillMarks = () => { - while (marks.has(cells.length)) - cells.push(continuation("rowspan", false)); + while (marks.has(cells2.length)) + cells2.push(continuation("rowspan", false)); }; for (const { cell, colspan, rowspan } of sourceCells) { fillMarks(); - const columns = [cells.length]; - cells.push(cell); + const columns = [cells2.length]; + cells2.push(cell); for (let k = 1; k < colspan; k++) { fillMarks(); - columns.push(cells.length); - cells.push(continuation("colspan", cell.header)); + columns.push(cells2.length); + cells2.push(continuation("colspan", cell.header)); } if (rowspan > 1) for (const index2 of columns) @@ -23533,19 +24533,19 @@ ${target} } const furthest = marks.size === 0 ? -1 : Math.max(...marks); let invented = false; - while (cells.length <= furthest) { - if (marks.has(cells.length)) - cells.push(continuation("rowspan", false)); + while (cells2.length <= furthest) { + if (marks.has(cells2.length)) + cells2.push(continuation("rowspan", false)); else { this.enter(depth); - cells.push({ type: "table_cell", header: false, children: [] }); + cells2.push({ type: "table_cell", header: false, children: [] }); invented = true; } } if (invented) { this.add("table-degraded", "Filled a row that is shorter than the spans reaching into it, with a cell the source did not have", "warning", `${path}/tr[${r + 1}]`); } - rows.push({ type: "table_row", cells, ...rowAttrs[r] ? { attrs: rowAttrs[r] } : {} }); + rows.push({ type: "table_row", cells: cells2, ...rowAttrs[r] ? { attrs: rowAttrs[r] } : {} }); carried = [...carried.map((entry) => ({ ...entry, rows: entry.rows - 1 })).filter((entry) => entry.rows > 0), ...opened]; }); return rows; @@ -23589,8 +24589,8 @@ ${target} const headerCells = (row) => (row.childNodes ?? []).filter((n) => n.tagName === "td" || n.tagName === "th"); let leadingHeaderRows = 0; for (const row of tr) { - const cells = headerCells(row); - if (cells.length === 0 || !cells.every((n) => n.tagName === "th")) + const cells2 = headerCells(row); + if (cells2.length === 0 || !cells2.every((n) => n.tagName === "th")) break; leadingHeaderRows += 1; } @@ -23618,8 +24618,8 @@ ${target} const cellAttrs = this.attrs(cell, cellPath); const scope = cellAttrs?.keyValues?.scope; if (scope !== void 0) { - const positional = r < leadingHeaderRows ? "col" : "row"; - if (scope === positional) { + const positional2 = r < leadingHeaderRows ? "col" : "row"; + if (scope === positional2) { delete cellAttrs.keyValues.scope; if (Object.keys(cellAttrs.keyValues).length === 0) delete cellAttrs.keyValues; @@ -23678,8 +24678,8 @@ ${target} return void 0; const sectionOf = (row) => group.get(row)?.tagName ?? "tbody"; const isHeaderRow = (row) => { - const cells = (row.childNodes ?? []).filter((n) => n.tagName === "td" || n.tagName === "th"); - return cells.length > 0 && cells.every((n) => n.tagName === "th"); + const cells2 = (row.childNodes ?? []).filter((n) => n.tagName === "td" || n.tagName === "th"); + return cells2.length > 0 && cells2.every((n) => n.tagName === "th"); }; const sections = tr.map(sectionOf); const headRows = sections.findIndex((name) => name !== "thead") === -1 ? tr.length : sections.findIndex((name) => name !== "thead"); @@ -24181,19 +25181,19 @@ ${target} const defs = {}; const containers = /* @__PURE__ */ new Set(); definitions.forEach((definition, index2) => { - const label = String(index2 + 1); + const label2 = String(index2 + 1); const block = definition.block; if (index2 === 0) this.removeFootnoteSeparator(block); const identities = definition.refs.map((reference) => this.footnoteAnchorIdentity(reference)).filter((identity) => identity !== ""); this.stripFootnoteBacklinks(block, identities, definition.fragments); - defs[label] = this.blocks(block.childNodes ?? [], `footnote[${label}]`, 1); + defs[label2] = this.blocks(block.childNodes ?? [], `footnote[${label2}]`, 1); for (const reference of definition.refs) { const site = this.footnoteReferenceSite(reference); const replacement = { nodeName: "carve-footnote-ref", tagName: "carve-footnote-ref", - attrs: [{ name: "label", value: label }], + attrs: [{ name: "label", value: label2 }], childNodes: [] }; if (site.parentNode !== void 0) @@ -26262,14 +27262,14 @@ ${items} const rows = []; for (const [, row] of body.matchAll(/\[tr\]([\s\S]*?)\[\/tr\]/gi)) { if (/\[th\]/i.test(row)) { - const cells2 = [...row.matchAll(/\[th\]([\s\S]*?)\[\/th\]/gi)].map((m) => `|= ${m[1].trim()}`); - if (cells2.length) - rows.push(`${cells2.join(" ")} |`); + const cells3 = [...row.matchAll(/\[th\]([\s\S]*?)\[\/th\]/gi)].map((m) => `|= ${m[1].trim()}`); + if (cells3.length) + rows.push(`${cells3.join(" ")} |`); continue; } - const cells = [...row.matchAll(/\[td\]([\s\S]*?)\[\/td\]/gi)].map((m) => m[1].trim()); - if (cells.length) - rows.push(`| ${cells.join(" | ")} |`); + const cells2 = [...row.matchAll(/\[td\]([\s\S]*?)\[\/td\]/gi)].map((m) => m[1].trim()); + if (cells2.length) + rows.push(`| ${cells2.join(" | ")} |`); } return ` @@ -27013,7 +28013,7 @@ ${body.trim()} var RE_MD_INDENTED_CODE = /^(?: {4,}|\t)/; var RE_MD_LINK_REFERENCE = /^ {0,3}\[[^\]]*\]:[ \t]*\S/; function splitTableRow2(row) { - const cells = []; + const cells2 = []; let cur = ""; for (let i = 0; i < row.length; i++) { const ch = row[i]; @@ -27022,18 +28022,18 @@ ${body.trim()} continue; } if (ch === "|") { - cells.push(cur); + cells2.push(cur); cur = ""; continue; } cur += ch; } - cells.push(cur); - if (cells.length > 1 && cells[0].trim() === "") - cells.shift(); - if (cells.length > 1 && cells[cells.length - 1].trim() === "") - cells.pop(); - return cells.map((c) => c.trim()); + cells2.push(cur); + if (cells2.length > 1 && cells2[0].trim() === "") + cells2.shift(); + if (cells2.length > 1 && cells2[cells2.length - 1].trim() === "") + cells2.pop(); + return cells2.map((c) => c.trim()); } function unescapePipesInCodeSpans(row) { return protectCodeSpans(row, (span2) => span2.replace(/\\\|/g, "|")); @@ -27042,8 +28042,8 @@ ${body.trim()} const trimmed = line2.trim(); if (!trimmed.startsWith("|") || !trimmed.endsWith("|")) return false; - const cells = splitTableRow2(trimmed); - return cells.some((cell) => cell !== "") || cells.length >= 2; + const cells2 = splitTableRow2(trimmed); + return cells2.some((cell) => cell !== "") || cells2.length >= 2; } function hasFollowingSetextUnderline(lines, index2) { const underline = index2 + 1 < lines.length ? lines[index2 + 1].trim() : ""; @@ -27290,8 +28290,8 @@ ${body.trim()} const nestedOrSibling = line2.match(RE_LIST_MARKER); if (nestedOrSibling) break; - const indent2 = leadingIndentWidth(line2); - if (indent2 < contentCol) + const indent3 = leadingIndentWidth(line2); + if (indent3 < contentCol) break; if (/^[ \t]{0,3}(`{3,}|~{3,})/.test(line2.slice(contentCol))) break; @@ -27470,7 +28470,7 @@ ${body.trim()} if (!inCode) { const openCol = listCols.length ? listCols[listCols.length - 1] : 0; const marker = RE_MD_THEMATIC.test(stripColumns(line2, openCol)) ? null : line2.match(/^([ \t]*)(?:[-*+]|\d+[.)]) +/); - const indent3 = indentColumns2(line2); + const indent4 = indentColumns2(line2); const startsBlock = /^#{1,6}([ \t]|$)/.test(trimmed) || trimmed.startsWith(">") || /^(`{3,}|~{3,})/.test(trimmed) || htmlBlockAt(lines, i) !== null || /^(-{3,}|\*{3,}|_{3,})$/.test(trimmed); if (marker && /\S/.test(line2.slice(marker[0].length))) { const markerIndent = columnWidth(marker[1]); @@ -27478,7 +28478,7 @@ ${body.trim()} listCols.pop(); listCols.push(columnWidth(marker[0])); } else if (trimmed !== "" && (wasPrevBlank || startsBlock)) { - while (listCols.length && listCols[listCols.length - 1] > indent3) + while (listCols.length && listCols[listCols.length - 1] > indent4) listCols.pop(); } } @@ -27581,7 +28581,7 @@ ${body.trim()} } const isBlank = trimmed === ""; const isHeading = /^#{1,6}\s/.test(trimmed); - const indent2 = line2.length - line2.replace(/^\s+/, "").length; + const indent3 = line2.length - line2.replace(/^\s+/, "").length; const relIndent = indentColumns2(held); const isBlockquote = trimmed.startsWith(">"); const ordered = trimmed.match(/^(\d+)[.)]\s/); @@ -27596,7 +28596,7 @@ ${body.trim()} prevType = "code"; continue; } - if (prevType === "list" && indent2 >= 1) { + if (prevType === "list" && indent3 >= 1) { if (isList) { const run = collectListInlineRun(lines, i, dialect); out.push(...run.lines.map((l) => l.replace(/^(\s*)\+(\s)/, "$1-$2"))); @@ -27651,7 +28651,7 @@ ${body.trim()} if (isTopLevelList && prevType !== "blank") out.push(""); const dedent = relIndent >= 1 && relIndent <= 3 && (isHeading || isBlockquote); - let body2 = dedent ? containerPad + line2.slice(indent2) : line2; + let body2 = dedent ? containerPad + line2.slice(indent3) : line2; if (isHeading) body2 = body2.replace(/[ \t]+#+[ \t]*$/, ""); if (isList) @@ -27714,7 +28714,7 @@ ${body}`; // dist/version.js var SPEC_VERSION = "0.1"; - var LIB_VERSION = "0.1.3"; + var LIB_VERSION = "0.1.4"; // dist/stamp.js function buildMarker(generatedBy, form) { @@ -28174,19 +29174,19 @@ generated-by: ${generatedBy} const footnoteDefs = doc.footnoteDefs ?? {}; const referencedFootnotes = /* @__PURE__ */ new Set(); const defsByWhitespaceKey = /* @__PURE__ */ new Map(); - for (const label of Object.keys(footnoteDefs)) { - const key2 = whitespaceKey(label); + for (const label2 of Object.keys(footnoteDefs)) { + const key2 = whitespaceKey(label2); const bucket = defsByWhitespaceKey.get(key2); if (bucket) - bucket.push(label); + bucket.push(label2); else - defsByWhitespaceKey.set(key2, [label]); + defsByWhitespaceKey.set(key2, [label2]); } for (const { id, node } of footnoteRefs) { referencedFootnotes.add(id); if (hasOwnKey(footnoteDefs, id)) continue; - const near = (defsByWhitespaceKey.get(whitespaceKey(id)) ?? []).filter((label) => label !== id); + const near = (defsByWhitespaceKey.get(whitespaceKey(id)) ?? []).filter((label2) => label2 !== id); const hint = near.length === 1 ? ` Definition [^${near[0]}] differs only in whitespace; footnote labels are matched exactly.` : near.length > 1 ? ` ${near.length} definitions differ from it only in whitespace; footnote labels are matched exactly.` : ""; out.push({ ...locate(node, toUtf16), @@ -28278,8 +29278,8 @@ generated-by: ${generatedBy} } }); } - function whitespaceKey(label) { - return label.trim().replace(/\s+/g, " "); + function whitespaceKey(label2) { + return label2.trim().replace(/\s+/g, " "); } function collectVerbatimLines(doc) { const verbatim = /* @__PURE__ */ new Set(); @@ -28316,6 +29316,7 @@ generated-by: ${generatedBy} }; const headings = []; const paragraphs = []; + const tables = []; const walk = (value) => { if (Array.isArray(value)) { for (const item of value) @@ -28329,6 +29330,8 @@ generated-by: ${generatedBy} headings.push(node); else if (node.type === "paragraph") paragraphs.push(node); + else if (node.type === "table") + tables.push(node); for (const key2 of Object.keys(node)) { if (key2 !== "pos" && key2 !== "attrs") walk(node[key2]); @@ -28381,15 +29384,15 @@ generated-by: ${generatedBy} const trailing = fm[3]; const lm = /^(.*?)[ \t]+(\[[^\]\n]*\])$/.exec(trailing); const titlePart = lm ? lm[1] : trailing; - const label = lm ? ` ${lm[2]}` : ""; + const label2 = lm ? ` ${lm[2]}` : ""; let message; const curly = /^[“”](.*)[“”]$/.exec(titlePart); if (curly) { - message = `The title after "${type}" uses typographic quotes - usually a CMS "smart quote" filter rewrote the source before Carve parsed it. A fence title needs straight double quotes: ${fence} ${type} "${curly[1]}"${label}.`; + message = `The title after "${type}" uses typographic quotes - usually a CMS "smart quote" filter rewrote the source before Carve parsed it. A fence title needs straight double quotes: ${fence} ${type} "${curly[1]}"${label2}.`; } else if (titlePart.startsWith("{")) { message = `A "{\u2026}" on the fence line is not an attribute block - it makes the whole line plain text. Put attributes on their own line directly above the ":::" opener.`; } else if (!titlePart.startsWith('"') && !titlePart.startsWith("[")) { - message = `Text after the "${type}" fence type must be a quoted "title" or a [label] - unquoted it makes the whole line plain text. Did you mean ${fence} ${type} "${titlePart}"${label}?`; + message = `Text after the "${type}" fence type must be a quoted "title" or a [label] - unquoted it makes the whole line plain text. Did you mean ${fence} ${type} "${titlePart}"${label2}?`; } if (message) { out.push({ @@ -28433,12 +29436,22 @@ generated-by: ${generatedBy} const line2 = lines[i]; const stripped = stripContainerPrefixesKeepIndent(line2); const prefixWidth = line2.length - stripped.length; - const indent2 = stripped.length - stripped.trimStart().length; - const row = stripped.slice(indent2); + const indent3 = stripped.length - stripped.trimStart().length; + const row = stripped.slice(indent3); if (!isTableRow(row)) continue; const { body } = rowAttrsFromLine(row); for (const { text, start } of splitTableRowSpans(body)) { + const unpadded = /^(?:=)?([<>~^v?]{1,2})(?![<>~^v?\s])/.exec(text); + if (unpadded) { + const at = text.startsWith("=") ? 1 : 0; + const marksEnd = at + unpadded[1].length; + const block2 = text[marksEnd] === "{" ? readCellAttributeBlock(text, marksEnd) : void 0; + const runEnd = marksEnd + (block2?.length ?? 0); + if (text[runEnd] !== " ") { + push(i + 1, prefixWidth + indent3 + start + at + 1, unpadded[1].length, "table-alignment-run-padding", `The table alignment run "${unpadded[1]}" has no terminating space, so it is literal cell content. A cell's marker run - the kind marker, the alignment run and the attribute block - ends at a space (\xA75 T11). Add a space after the run${block2 ? " and its attribute block" : ""} to make it alignment.`); + } + } const block = readCellAttributeBlock(text); if (!block) continue; @@ -28446,7 +29459,43 @@ generated-by: ${generatedBy} if (marker === void 0 || !TABLE_ALIGNMENT_MARKERS.has(marker)) continue; const spelling = text.slice(0, block.length + 1); - push(i + 1, prefixWidth + indent2 + start + 1, block.length + 1, "table-cell-attribute-before-marker", `"${spelling}" writes a cell's attribute block before its alignment marker, which Carve no longer reads as one: the "${marker}" is literal content and the cell is not aligned. Write "${marker}${text.slice(0, block.length)}" to align it, or put a space after the block to keep the "${marker}" as content deliberately.`); + push(i + 1, prefixWidth + indent3 + start + 1, block.length + 1, "table-cell-attribute-before-marker", `"${spelling}" writes a cell's attribute block before its alignment marker, which Carve no longer reads as one. The block is part of the cell's marker run and the run ends at a space, so with the "${marker}" glued to it there is no run: the braces are content and the cell is neither attributed nor aligned. Write "${marker}${text.slice(0, block.length)} " to align it, or "${text.slice(0, block.length)} ${marker}" to keep the "${marker}" as content deliberately.`); + } + } + for (const table of tables) { + const kv = table.attrs?.keyValues ?? {}; + const widest = Math.max(0, ...table.rows.map((row) => row.cells.length)); + const lineNo = table.pos?.startLine ?? 1; + const tableStart = lineStart[lineNo - 1] ?? source.length; + const addTableWarning = (rule, key2, message) => { + const found = source.lastIndexOf(key2, tableStart); + const start = found >= 0 ? found : lineStart[lineNo - 1] ?? 0; + const before = source.slice(0, start); + const warningLine = before.split("\n").length; + const warningColumn = start - before.lastIndexOf("\n"); + out.push({ line: warningLine, column: warningColumn, rule, message, start, end: start + key2.length }); + }; + for (const key2 of ["aligns", "valigns", "widths"]) { + if (kv[key2] === void 0) + continue; + const values = kv[key2].split(","); + if (values.length < widest) { + addTableWarning("table-column-arity", key2, `${key2} supplies ${values.length} column entries for a ${widest}-column table; the unset tail is valid but may be accidental.`); + } + } + const widths = kv.widths?.split(",").map((raw) => Number(raw.trim())).filter(Number.isFinite) ?? []; + if (widths.reduce((sum, width2) => sum + width2, 0) > 100) { + addTableWarning("table-width-total", "widths", "The specified table column widths total more than 100%."); + } + const aligns = kv.aligns?.split(",") ?? []; + const valigns = kv.valigns?.split(",") ?? []; + const headerRows = table.rows.filter((row) => row.cells.some((cell) => cell.header)); + for (let column = 0; column < widest; column++) { + const markerAlign = headerRows.some((row) => row.cells[column]?.align !== void 0); + const markerValign = headerRows.some((row) => row.cells[column]?.valign !== void 0); + if (markerAlign && aligns[column]?.trim() || markerValign && valigns[column]?.trim()) { + addTableWarning("table-column-overlap", markerAlign && aligns[column]?.trim() ? "aligns" : "valigns", `Column ${column + 1} supplies the same alignment axis both in the table and in a table attribute; the in-table marker wins.`); + } } } } @@ -28468,48 +29517,48 @@ generated-by: ${generatedBy} const m = FOOTNOTE_DEF.exec(stripContainerPrefixesKeepIndent(line2, afterTerm)); if (!m) continue; - const label = m[1]; - if (!hasOwnKey(defs, label)) + const label2 = m[1]; + if (!hasOwnKey(defs, label2)) continue; const col = line2.indexOf("[^") + 1; const start = (lineStart[i] ?? 0) + (col - 1); const site = { line: i + 1, col, start, end: start + m[0].length }; - if (firstSites.has(label)) { + if (firstSites.has(label2)) { out.push({ line: site.line, column: site.col, rule: "duplicate-footnote-definition", - message: `Duplicate footnote definition [^${label}] is ignored; the first definition for a label wins.`, + message: `Duplicate footnote definition [^${label2}] is ignored; the first definition for a label wins.`, start: site.start, end: site.end }); } else { - const key2 = whitespaceKey(label); + const key2 = whitespaceKey(label2); const twin = firstByWhitespaceKey.get(key2); - if (twin !== void 0 && twin !== label) { + if (twin !== void 0 && twin !== label2) { out.push({ line: site.line, column: site.col, rule: "footnote-labels-differ-only-in-whitespace", - message: `Footnote definitions [^${twin}] and [^${label}] differ only in whitespace, so they are two separate footnotes; labels are matched exactly.`, + message: `Footnote definitions [^${twin}] and [^${label2}] differ only in whitespace, so they are two separate footnotes; labels are matched exactly.`, start: site.start, end: site.end }); } else if (twin === void 0) { - firstByWhitespaceKey.set(key2, label); + firstByWhitespaceKey.set(key2, label2); } - firstSites.set(label, site); + firstSites.set(label2, site); } } - for (const label of Object.keys(doc.footnoteDefs ?? {})) { - if (referenced.has(label)) + for (const label2 of Object.keys(doc.footnoteDefs ?? {})) { + if (referenced.has(label2)) continue; - const site = firstSites.get(label); + const site = firstSites.get(label2); out.push({ line: site?.line ?? 1, column: site?.col ?? 1, rule: "unused-footnote-definition", - message: `Footnote definition [^${label}] is never referenced, so it is omitted from the rendered document.`, + message: `Footnote definition [^${label2}] is never referenced, so it is omitted from the rendered document.`, start: site?.start ?? 0, end: site?.end ?? 0 }); @@ -28661,8 +29710,8 @@ generated-by: ${generatedBy} const m = FOOTNOTE_DEF.exec(line2); if (!m) return; - const label = m[1]; - if (hasOwnKey(defs, label) && !referencedFootnotes.has(label)) + const label2 = m[1]; + if (hasOwnKey(defs, label2) && !referencedFootnotes.has(label2)) lines.add(i + 1); }); const fmPos = doc.frontmatter?.pos; @@ -28803,33 +29852,78 @@ ${pad}`; return null; const outerList = node.children[0]; const rows = []; + const localHeaderRows = []; for (const rowItem of outerList.items) { - const cells = extractCells(rowItem); - if (cells === null) + const cells2 = extractCells(rowItem); + if (cells2 === null) + return null; + const localHeader = structuralMarker(cells2[0]?.cell.attrs, "header-row"); + if (localHeader === null || cells2.slice(1).some((entry) => structuralMarker(entry.cell.attrs, "header-row") !== false)) return null; - rows.push(cells); + rows.push(cells2); + localHeaderRows.push(localHeader); } if (rows.length === 0) return null; - for (const cells of rows) { - if (cells.length === 0) + for (const cells2 of rows) { + if (cells2.length === 0) + return null; + if (cells2.some((entry) => structuralMarker(entry.cell.attrs, "header") === null)) + return null; + if (cells2.some((entry) => !validCellAlignment(entry.cell.attrs))) return null; } - const totalCells = rows.reduce((n, cells) => n + cells.length, 0); + const totalCells = rows.reduce((n, cells2) => n + cells2.length, 0); if (rows.length > MAX_LIST_TABLE_ROWS || totalCells > MAX_LIST_TABLE_CELLS) return null; const headerRows = headerCount(node.attrs?.keyValues?.["header-rows"]); const headerCols = headerCount(node.attrs?.keyValues?.["header-cols"]); - const grid = resolveSpans(rows, headerRows); + const footerRows = headerCount(node.attrs?.keyValues?.["footer-rows"]); + if (headerRows + footerRows > rows.length) + return null; + const footerStart = rows.length - footerRows; + if (localHeaderRows.slice(footerStart).some(Boolean)) + return null; + const bodyGroups = []; + let groupStart = headerRows; + let groupHasData = false; + for (let row = headerRows; row < footerStart; row++) { + if (localHeaderRows[row] && groupHasData) { + bodyGroups.push({ start: groupStart, end: row }); + groupStart = row; + groupHasData = false; + } + if (!localHeaderRows[row]) + groupHasData = true; + } + if (groupStart < footerStart) + bodyGroups.push({ start: groupStart, end: footerStart }); + const rowGroup = rows.map((_, row) => row < headerRows ? 0 : row >= footerStart ? bodyGroups.length + 1 : 1); + bodyGroups.forEach((group, index2) => { + for (let row = group.start; row < group.end; row++) + rowGroup[row] = index2 + 1; + }); + const grid = resolveSpans(rows, rowGroup); const placement = placeColumns(grid); const columnCount = placement.columnCount; + const columns = listTableColumns(node, columnCount); + if (columns === null) + return null; const lines = []; const caption = node.title ? ctx.renderInlines(node.title).trim() : ""; if (caption !== "") { lines.push(`${pad} ${caption}`); } + if (columns.some((column) => column.width !== void 0)) { + lines.push(`${pad} `); + for (const column of columns) { + const style2 = column.width === void 0 ? "" : ` style="width: ${column.width}%;"`; + lines.push(`${pad} `); + } + lines.push(`${pad} `); + } const renderRow = (gridRow, rowIndex) => { - const isHeaderRow = rowIndex < headerRows; + const isHeaderRow = rowIndex < headerRows || localHeaderRows[rowIndex]; const cols = placement.cols[rowIndex]; let html = ""; let nextCol = 0; @@ -28837,7 +29931,7 @@ ${pad}`; if (entry.skip) return; const col2 = cols[i]; - const isHeaderCell = isHeaderRow || col2 < headerCols; + const isHeaderCell = isHeaderRow || col2 < headerCols || structuralMarker(entry.cell.attrs, "header") === true; const tag = isHeaderCell ? "th" : "td"; let attrHtml = ""; if (isHeaderCell) @@ -28846,6 +29940,7 @@ ${pad}`; attrHtml += ` rowspan="${entry.rowspan}"`; if (entry.colspan > 1) attrHtml += ` colspan="${entry.colspan}"`; + attrHtml += cellStyle(entry.cell.attrs, columns[col2]); attrHtml += renderCellAttributes(entry.cell, ctx); const content = entry.marker !== null ? "" : renderCell(entry.cell, entry.extras, ctx); html += `<${tag}${attrHtml}>${content}`; @@ -28856,27 +29951,38 @@ ${pad}`; const isPadHeader = isHeaderRow || col < headerCols; const tag = isPadHeader ? "th" : "td"; const scope = isPadHeader ? ` scope="${isHeaderRow ? "col" : "row"}"` : ""; - html += `<${tag}${scope}>`; + html += `<${tag}${scope}${columnStyle(columns[col])}>`; } return `${html}`; }; const headGrid = grid.slice(0, headerRows); - const bodyGrid = grid.slice(headerRows); + const footGrid = grid.slice(footerStart); if (headGrid.length > 0) { - let thead = ""; + const head = []; headGrid.forEach((gridRow, rowIndex) => { - thead += renderRow(gridRow, rowIndex); + head.push(`${pad} ${renderRow(gridRow, rowIndex)}`); }); - lines.push(`${pad} ${thead}`); + lines.push(`${pad} +${head.join("\n")} +${pad} `); } - if (bodyGrid.length > 0) { + for (const group of bodyGroups) { const body = []; - bodyGrid.forEach((gridRow, offset) => { - body.push(`${pad} ${renderRow(gridRow, offset + headerRows)}`); + grid.slice(group.start, group.end).forEach((gridRow, offset) => { + body.push(`${pad} ${renderRow(gridRow, group.start + offset)}`); }); lines.push(`${pad} ${body.join("\n")} ${pad} `); + } + if (footGrid.length > 0) { + const foot = []; + footGrid.forEach((gridRow, offset) => { + foot.push(`${pad} ${renderRow(gridRow, footerStart + offset)}`); + }); + lines.push(`${pad} +${foot.join("\n")} +${pad} `); } const attrs = renderTableAttributes(node, ctx); return `${pad} @@ -28919,22 +30025,22 @@ ${pad}`; return { cols, rowReach, columnCount }; } function extractCells(rowItem) { - const cells = []; + const cells2 = []; for (const child of rowItem.children) { if (child.type === "list") { for (const cellItem of child.items) { - cells.push({ cell: cellItem, extras: [] }); + cells2.push({ cell: cellItem, extras: [] }); } continue; } - if (cells.length === 0) + if (cells2.length === 0) return null; - cells[cells.length - 1].extras.push(child); + cells2[cells2.length - 1].extras.push(child); } - return cells; + return cells2; } - function resolveSpans(rows, headerRows = 0) { - const grid = rows.map((cells) => cells.map((entry) => ({ + function resolveSpans(rows, rowGroup = rows.map(() => 0)) { + const grid = rows.map((cells2) => cells2.map((entry) => ({ cell: entry.cell, extras: entry.extras, marker: markerOf(entry), @@ -28951,8 +30057,8 @@ ${pad}`; if (entry.marker === "^" && r > 0) { const up = base[c]; const src = up !== void 0 ? grid[up]?.[c] : void 0; - const crossesHeader = up !== void 0 && up < headerRows && r >= headerRows; - if (src && !crossesHeader) { + const crossesGroup = up !== void 0 && rowGroup[up] !== rowGroup[r]; + if (src && !crossesGroup) { src.rowspan++; entry.skip = true; } @@ -29008,7 +30114,69 @@ ${pad}`; function renderCellAttributes(cell, ctx) { if (!cell.attrs) return ""; - return ctx.renderAttrs(stripSpanAttrs(cell.attrs)); + return ctx.renderAttrs(stripStructuralCellAttrs(cell.attrs)); + } + function structuralMarker(attrs, key2) { + const value = attrs?.keyValues?.[key2]; + if (value === void 0) + return false; + return value === "" ? true : null; + } + function listTableColumns(node, count) { + const kv = node.attrs?.keyValues ?? {}; + const split = (key2) => kv[key2] === void 0 ? [] : kv[key2].split(",").map((v) => v.trim()); + const aligns = split("aligns"); + const valigns = split("valigns"); + const widths = split("widths"); + if ([aligns, valigns, widths].some((values) => values.length > count)) + return null; + const columns = Array.from({ length: count }, () => ({})); + for (let i = 0; i < count; i++) { + const align = aligns[i]; + if (align) { + if (align !== "left" && align !== "right" && align !== "center") + return null; + columns[i].align = align; + } + const valign = valigns[i]; + if (valign) { + if (valign !== "top" && valign !== "middle" && valign !== "bottom") + return null; + columns[i].valign = valign; + } + const rawWidth = widths[i]; + if (rawWidth) { + const width2 = Number(rawWidth); + if (!Number.isFinite(width2) || width2 <= 0 || width2 > 100) + return null; + columns[i].width = width2; + } + } + return columns; + } + function columnStyle(column) { + if (!column?.align && !column?.valign) + return ""; + const style2 = [ + column.align ? `text-align: ${column.align};` : "", + column.valign ? `vertical-align: ${column.valign};` : "" + ].filter(Boolean).join(" "); + return ` style="${style2}"`; + } + function validCellAlignment(attrs) { + const align = attrs?.keyValues?.align; + const valign = attrs?.keyValues?.valign; + return (align === void 0 || align === "left" || align === "right" || align === "center") && (valign === void 0 || valign === "top" || valign === "middle" || valign === "bottom"); + } + function cellStyle(attrs, column) { + const align = attrs?.keyValues?.align; + const valign = attrs?.keyValues?.valign; + const resolved = {}; + if (align ?? column?.align) + resolved.align = align ?? column?.align; + if (valign ?? column?.valign) + resolved.valign = valign ?? column?.valign; + return columnStyle(resolved); } function renderTableAttributes(node, ctx) { const attrs = node.attrs; @@ -29017,8 +30185,12 @@ ${pad}`; const keyValues = { ...attrs.keyValues ?? {} }; delete keyValues["header-rows"]; delete keyValues["header-cols"]; + delete keyValues["footer-rows"]; + delete keyValues.aligns; + delete keyValues.valigns; + delete keyValues.widths; const classes = (attrs.classes ?? []).filter((c) => c !== "" && c !== "list-table"); - const order = (attrs.order ?? []).filter((s) => s !== "header-rows" && s !== "header-cols" && !(s === ".class" && classes.length === 0)); + const order = (attrs.order ?? []).filter((s) => !["header-rows", "header-cols", "footer-rows", "aligns", "valigns", "widths"].includes(s) && !(s === ".class" && classes.length === 0)); const cleaned = {}; if (attrs.id !== void 0) cleaned.id = attrs.id; @@ -29030,24 +30202,24 @@ ${pad}`; cleaned.order = order; return ctx.renderAttrs(cleaned); } - function stripSpanAttrs(attrs) { + function stripStructuralCellAttrs(attrs) { if (!attrs.keyValues) return attrs; const has = Object.keys(attrs.keyValues).some((k) => { const l = k.toLowerCase(); - return l === "rowspan" || l === "colspan"; + return l === "rowspan" || l === "colspan" || l === "header" || l === "header-row" || l === "align" || l === "valign"; }); if (!has) return attrs; const keyValues = Object.fromEntries(Object.entries(attrs.keyValues).filter(([k]) => { const l = k.toLowerCase(); - return l !== "rowspan" && l !== "colspan"; + return l !== "rowspan" && l !== "colspan" && l !== "header" && l !== "header-row" && l !== "align" && l !== "valign"; })); const out = { ...attrs, keyValues }; if (attrs.order) { out.order = attrs.order.filter((s) => { const l = s.toLowerCase(); - return l !== "rowspan" && l !== "colspan"; + return l !== "rowspan" && l !== "colspan" && l !== "header" && l !== "header-row" && l !== "align" && l !== "valign"; }); } return out; @@ -29195,7 +30367,7 @@ ${ctx.indent(ctx.level + 1)}`; // dist/heading-numbers.js function headingNumbers(opts = {}) { const minLevel = opts.minLevel ?? 1; - const label = opts.label ?? "Section"; + const label2 = opts.label ?? "Section"; const crossref = opts.crossref ?? "number-title"; const processed = /* @__PURE__ */ new WeakSet(); return { @@ -29244,7 +30416,7 @@ ${ctx.indent(ctx.level + 1)}`; const entry = byId.get(ref.href.slice(1)); if (!entry) return; - const prefix = crossref === "number" ? `${label} ${entry.number}` : `${label} ${entry.number} - `; + const prefix = crossref === "number" ? `${label2} ${entry.number}` : `${label2} ${entry.number} - `; ref.resolvedText = crossref === "number" ? [{ type: "text", value: prefix }] : [ { type: "text", value: prefix }, ...deriveDisplayNodes(entry.title, true) @@ -30356,7 +31528,7 @@ ${pad}`; return `${ctx.renderInlines(node.content)}`; } function renderSwatch(nodeAttrs, ctx, value, position, shape, tint, reveal) { - const label = ctx.escapeHtml(value); + const label2 = ctx.escapeHtml(value); const chipClass = shape === "square" ? "swatch-chip" : `swatch-chip swatch-chip-${shape}`; const chipStyle = shape === "ring" ? `border-color:${value}` : `background-color:${value}`; const chip = ``; @@ -30371,11 +31543,11 @@ ${pad}`; attrs = withDefaultKeyValue(attrs, "title", value); inner = chip; } else { - let valueHtml = label; + let valueHtml = label2; if (reveal) { attrs = addClass(attrs, "swatch-reveal"); attrs = withDefaultKeyValue(attrs, "tabindex", "0"); - valueHtml = `${label}`; + valueHtml = `${label2}`; } inner = position === "after" ? `${valueHtml} ${chip}` : `${chip} ${valueHtml}`; } @@ -30902,9 +32074,9 @@ ${buildList(picked, "ul", void 0)}`; const cb = child; const language = cb.lang && cb.lang !== "" ? cb.lang : void 0; const labelText = cb.label?.trim(); - const label = labelText && labelText !== "" ? labelText : language ?? `Code ${position}`; + const label2 = labelText && labelText !== "" ? labelText : language ?? `Code ${position}`; const selected = cb.attrs?.keyValues?.selected !== void 0; - items.push({ block: cb, language, label, selected }); + items.push({ block: cb, language, label: label2, selected }); } if (items.length && !items.some((i) => i.selected)) items[0].selected = true; @@ -31043,9 +32215,9 @@ ${buildList(picked, "ul", void 0)}`; let labelCounter = 0; const explicitLabel = (tab) => tab.label ?? tab.attrs?.keyValues?.label; const extractLabel = (tab) => { - const label = explicitLabel(tab); - if (label !== void 0) - return label; + const label2 = explicitLabel(tab); + if (label2 !== void 0) + return label2; for (const child of tab.children) { if (child.type === "heading") return inlineText(child.children); @@ -31550,24 +32722,32 @@ ${tab.content} return renderAnsi(adoptBlockFootnoteDefs(ast), opts); } function resolve(doc, opts = {}) { - const resolved = resolveHeadingIds(doc, headingIdSlugOpts(opts)); + return resolveDocument(doc, opts); + } + function resolveDocument(doc, opts, documentIds) { + const slugOpts = headingIdSlugOpts(opts); + const resolved = documentIds ? resolveHeadingIdsWithRegistry(doc, slugOpts, documentIds) : resolveHeadingIds(doc, slugOpts); numberFootnotes(resolved); return coalesceTextRuns(resolved); } function carveToHtml(source, opts = {}) { enforceProfileMaxLength(source, opts); + const fast = tryFastHtml(source, opts); + if (fast !== void 0) + return fast; const exts = opts.extensions ?? []; const parseOpts = { ...opts, extensions: exts, ...opts.sourceLine ? { positions: true } : {} }; - let doc = applyTransforms(resolve(parse2(source, parseOpts), { + const documentIds = exts.length === 0 && opts.profile === void 0 ? new DocumentIdRegistry() : void 0; + let doc = applyTransforms(resolveDocument(parse2(source, parseOpts), { asciiHeadingIds: opts.asciiHeadingIds ?? false, lowercaseHeadingIds: opts.lowercaseHeadingIds ?? false - }), exts, opts, true); + }, documentIds), exts, opts, true); doc = runProfile(doc, opts); - return renderHtml2(doc, opts); + return renderHtml(adoptBlockFootnoteDefs(doc), opts, documentIds); } function applyTransforms(doc, exts, opts, targetIsHtml) { if (!exts) diff --git a/src/main/resources/lsp/VERSION b/src/main/resources/lsp/VERSION index 7a478c4..a30045e 100644 --- a/src/main/resources/lsp/VERSION +++ b/src/main/resources/lsp/VERSION @@ -1,3 +1,3 @@ -carve-lsp c08793fd48d2e6a026288b7a760e8ab2897ff428 -carve-js npm 0.1.2 -built 2026-08-07T00:41:04Z +carve-lsp ef1ca2466f66060b75d52eb2bff8806b2285dbc9 +carve-js commit 61f824d5d5724bfaa26dd07dc5c159249a66c977 +built 2026-08-20T23:53:04Z diff --git a/src/main/resources/lsp/server.js b/src/main/resources/lsp/server.js index 5487067..ac52e3b 100755 --- a/src/main/resources/lsp/server.js +++ b/src/main/resources/lsp/server.js @@ -1,7 +1,7 @@ // Generated by tools/build-lsp-bundle.sh - do not edit by hand. -// Bundled from markup-carve/carve-lsp commit c08793fd48d2e6a026288b7a760e8ab2897ff428 -// carve-js dependency npm 0.1.2 -// Built (UTC): 2026-08-07T00:41:04Z +// Bundled from markup-carve/carve-lsp commit ef1ca2466f66060b75d52eb2bff8806b2285dbc9 +// carve-js dependency commit 61f824d5d5724bfaa26dd07dc5c159249a66c977 +// Built (UTC): 2026-08-20T23:53:04Z "use strict"; var __create = Object.create; @@ -10,6 +10,14 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; +var __esm = (fn, res, err) => function __init() { + if (err) throw err[0]; + try { + return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; + } catch (e) { + throw err = [e], e; + } +}; var __commonJS = (cb, mod) => function __require() { try { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; @@ -17,11 +25,15 @@ var __commonJS = (cb, mod) => function __require() { throw mod = 0, e; } }; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { - for (let key of __getOwnPropNames(from)) - if (!__hasOwnProp.call(to, key) && key !== except) - __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + for (let key2 of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key2) && key2 !== except) + __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable }); } return to; }; @@ -161,8 +173,8 @@ var require_messages = __commonJS({ }; exports2.ResponseError = ResponseError; var ParameterStructures = class _ParameterStructures { - constructor(kind) { - this.kind = kind; + constructor(kind2) { + this.kind = kind2; } static is(value) { return value === _ParameterStructures.auto || value === _ParameterStructures.byName || value === _ParameterStructures.byPosition; @@ -358,7 +370,7 @@ var require_messages = __commonJS({ var require_linkedMap = __commonJS({ "node_modules/vscode-jsonrpc/lib/common/linkedMap.js"(exports2) { "use strict"; - var _a; + var _a2; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.LRUCache = exports2.LinkedMap = exports2.Touch = void 0; var Touch; @@ -371,7 +383,7 @@ var require_linkedMap = __commonJS({ })(Touch || (exports2.Touch = Touch = {})); var LinkedMap = class { constructor() { - this[_a] = "LinkedMap"; + this[_a2] = "LinkedMap"; this._map = /* @__PURE__ */ new Map(); this._head = void 0; this._tail = void 0; @@ -397,59 +409,59 @@ var require_linkedMap = __commonJS({ get last() { return this._tail?.value; } - has(key) { - return this._map.has(key); + has(key2) { + return this._map.has(key2); } - get(key, touch = Touch.None) { - const item = this._map.get(key); - if (!item) { + get(key2, touch = Touch.None) { + const item2 = this._map.get(key2); + if (!item2) { return void 0; } if (touch !== Touch.None) { - this.touch(item, touch); + this.touch(item2, touch); } - return item.value; + return item2.value; } - set(key, value, touch = Touch.None) { - let item = this._map.get(key); - if (item) { - item.value = value; + set(key2, value, touch = Touch.None) { + let item2 = this._map.get(key2); + if (item2) { + item2.value = value; if (touch !== Touch.None) { - this.touch(item, touch); + this.touch(item2, touch); } } else { - item = { key, value, next: void 0, previous: void 0 }; + item2 = { key: key2, value, next: void 0, previous: void 0 }; switch (touch) { case Touch.None: - this.addItemLast(item); + this.addItemLast(item2); break; case Touch.First: - this.addItemFirst(item); + this.addItemFirst(item2); break; case Touch.Last: - this.addItemLast(item); + this.addItemLast(item2); break; default: - this.addItemLast(item); + this.addItemLast(item2); break; } - this._map.set(key, item); + this._map.set(key2, item2); this._size++; } return this; } - delete(key) { - return !!this.remove(key); + delete(key2) { + return !!this.remove(key2); } - remove(key) { - const item = this._map.get(key); - if (!item) { + remove(key2) { + const item2 = this._map.get(key2); + if (!item2) { return void 0; } - this._map.delete(key); - this.removeItem(item); + this._map.delete(key2); + this.removeItem(item2); this._size--; - return item.value; + return item2.value; } shift() { if (!this._head && !this._tail) { @@ -458,11 +470,11 @@ var require_linkedMap = __commonJS({ if (!this._head || !this._tail) { throw new Error("Invalid list"); } - const item = this._head; - this._map.delete(item.key); - this.removeItem(item); + const item2 = this._head; + this._map.delete(item2.key); + this.removeItem(item2); this._size--; - return item.value; + return item2.value; } forEach(callbackfn, thisArg) { const state = this._state; @@ -545,7 +557,7 @@ var require_linkedMap = __commonJS({ }; return iterator; } - [(_a = Symbol.toStringTag, Symbol.iterator)]() { + [(_a2 = Symbol.toStringTag, Symbol.iterator)]() { return this.entries(); } trimOld(newSize) { @@ -570,60 +582,60 @@ var require_linkedMap = __commonJS({ } this._state++; } - addItemFirst(item) { + addItemFirst(item2) { if (!this._head && !this._tail) { - this._tail = item; + this._tail = item2; } else if (!this._head) { throw new Error("Invalid list"); } else { - item.next = this._head; - this._head.previous = item; + item2.next = this._head; + this._head.previous = item2; } - this._head = item; + this._head = item2; this._state++; } - addItemLast(item) { + addItemLast(item2) { if (!this._head && !this._tail) { - this._head = item; + this._head = item2; } else if (!this._tail) { throw new Error("Invalid list"); } else { - item.previous = this._tail; - this._tail.next = item; + item2.previous = this._tail; + this._tail.next = item2; } - this._tail = item; + this._tail = item2; this._state++; } - removeItem(item) { - if (item === this._head && item === this._tail) { + removeItem(item2) { + if (item2 === this._head && item2 === this._tail) { this._head = void 0; this._tail = void 0; - } else if (item === this._head) { - if (!item.next) { + } else if (item2 === this._head) { + if (!item2.next) { throw new Error("Invalid list"); } - item.next.previous = void 0; - this._head = item.next; - } else if (item === this._tail) { - if (!item.previous) { + item2.next.previous = void 0; + this._head = item2.next; + } else if (item2 === this._tail) { + if (!item2.previous) { throw new Error("Invalid list"); } - item.previous.next = void 0; - this._tail = item.previous; + item2.previous.next = void 0; + this._tail = item2.previous; } else { - const next = item.next; - const previous = item.previous; + const next = item2.next; + const previous = item2.previous; if (!next || !previous) { throw new Error("Invalid list"); } next.previous = previous; previous.next = next; } - item.next = void 0; - item.previous = void 0; + item2.next = void 0; + item2.previous = void 0; this._state++; } - touch(item, touch) { + touch(item2, touch) { if (!this._head || !this._tail) { throw new Error("Invalid list"); } @@ -631,54 +643,54 @@ var require_linkedMap = __commonJS({ return; } if (touch === Touch.First) { - if (item === this._head) { + if (item2 === this._head) { return; } - const next = item.next; - const previous = item.previous; - if (item === this._tail) { + const next = item2.next; + const previous = item2.previous; + if (item2 === this._tail) { previous.next = void 0; this._tail = previous; } else { next.previous = previous; previous.next = next; } - item.previous = void 0; - item.next = this._head; - this._head.previous = item; - this._head = item; + item2.previous = void 0; + item2.next = this._head; + this._head.previous = item2; + this._head = item2; this._state++; } else if (touch === Touch.Last) { - if (item === this._tail) { + if (item2 === this._tail) { return; } - const next = item.next; - const previous = item.previous; - if (item === this._head) { + const next = item2.next; + const previous = item2.previous; + if (item2 === this._head) { next.previous = void 0; this._head = next; } else { next.previous = previous; previous.next = next; } - item.next = void 0; - item.previous = this._tail; - this._tail.next = item; - this._tail = item; + item2.next = void 0; + item2.previous = this._tail; + this._tail.next = item2; + this._tail = item2; this._state++; } } toJSON() { const data = []; - this.forEach((value, key) => { - data.push([key, value]); + this.forEach((value, key2) => { + data.push([key2, value]); }); return data; } fromJSON(data) { this.clear(); - for (const [key, value] of data) { - this.set(key, value); + for (const [key2, value] of data) { + this.set(key2, value); } } }; @@ -703,14 +715,14 @@ var require_linkedMap = __commonJS({ this._ratio = Math.min(Math.max(0, ratio), 1); this.checkTrim(); } - get(key, touch = Touch.AsNew) { - return super.get(key, touch); + get(key2, touch = Touch.AsNew) { + return super.get(key2, touch); } - peek(key) { - return super.get(key, Touch.None); + peek(key2) { + return super.get(key2, Touch.None); } - set(key, value) { - super.set(key, value, Touch.Last); + set(key2, value) { + super.set(key2, value, Touch.Last); this.checkTrim(); return this; } @@ -1518,9 +1530,9 @@ var require_messageBuffer = __commonJS({ throw new Error(`Message header must separate key and value using ':' ${header}`); } - const key = header.substr(0, index2); + const key2 = header.substr(0, index2); const value = header.substr(index2 + 1).trim(); - result.set(lowerCaseKeys ? key.toLowerCase() : key, value); + result.set(lowerCaseKeys ? key2.toLowerCase() : key2, value); } return result; } @@ -1925,13 +1937,13 @@ var require_connection = __commonJS({ try { if (messages_1.Message.isNotification(message) && message.method === CancelNotification.type.method) { const cancelId = message.params.id; - const key = createRequestQueueKey(cancelId); - const toCancel = messageQueue.get(key); + const key2 = createRequestQueueKey(cancelId); + const toCancel = messageQueue.get(key2); if (messages_1.Message.isRequest(toCancel)) { const strategy = options?.connectionStrategy; const response = strategy && strategy.cancelUndispatched ? strategy.cancelUndispatched(toCancel, cancelUndispatched) : cancelUndispatched(toCancel); if (response && (response.error !== void 0 || response.result !== void 0)) { - messageQueue.delete(key); + messageQueue.delete(key2); requestTokens.delete(cancelId); response.id = toCancel.id; traceSendingResponse(response, message.method, Date.now()); @@ -2082,11 +2094,11 @@ ${JSON.stringify(responseMessage.error, void 0, 4)}`); logger.error(`Received response message without id. No further error information provided.`); } } else { - const key = responseMessage.id; - const responsePromise = responsePromises.get(key); + const key2 = responseMessage.id; + const responsePromise = responsePromises.get(key2); traceReceivedResponse(responseMessage, responsePromise); if (responsePromise !== void 0) { - responsePromises.delete(key); + responsePromises.delete(key2); try { if (responseMessage.error) { const error = responseMessage.error; @@ -2179,8 +2191,8 @@ ${JSON.stringify(responseMessage.error, void 0, 4)}`); ${JSON.stringify(message, null, 4)}`); const responseMessage = message; if (Is.string(responseMessage.id) || Is.number(responseMessage.id)) { - const key = responseMessage.id; - const responseHandler = responsePromises.get(key); + const key2 = responseMessage.id; + const responseHandler = responsePromises.get(key2); if (responseHandler) { responseHandler.reject(new Error("The received response has neither a result nor an error property.")); } @@ -3090,7 +3102,7 @@ var require_main = __commonJS({ exports2.createMessageConnection = exports2.createServerSocketTransport = exports2.createClientSocketTransport = exports2.createServerPipeTransport = exports2.createClientPipeTransport = exports2.generateRandomPipeName = exports2.StreamMessageWriter = exports2.StreamMessageReader = exports2.SocketMessageWriter = exports2.SocketMessageReader = exports2.PortMessageWriter = exports2.PortMessageReader = exports2.IPCMessageWriter = exports2.IPCMessageReader = void 0; var ril_1 = require_ril(); ril_1.default.install(); - var path = require("path"); + var path8 = require("path"); var os = require("os"); var crypto_1 = require("crypto"); var net_1 = require("net"); @@ -3226,9 +3238,9 @@ var require_main = __commonJS({ } let result; if (XDG_RUNTIME_DIR) { - result = path.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`); + result = path8.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`); } else { - result = path.join(os.tmpdir(), `vscode-${randomSuffix}.sock`); + result = path8.join(os.tmpdir(), `vscode-${randomSuffix}.sock`); } const limit = safeIpcPathLengths.get(process.platform); if (limit !== void 0 && result.length > limit) { @@ -3382,14 +3394,14 @@ var require_main2 = __commonJS({ })(uinteger || (exports3.uinteger = uinteger = {})); var Position; (function(Position2) { - function create(line, character) { - if (line === Number.MAX_VALUE) { - line = uinteger.MAX_VALUE; + function create(line2, character) { + if (line2 === Number.MAX_VALUE) { + line2 = uinteger.MAX_VALUE; } if (character === Number.MAX_VALUE) { character = uinteger.MAX_VALUE; } - return { line, character }; + return { line: line2, character }; } Position2.create = create; function is(value) { @@ -3496,7 +3508,7 @@ var require_main2 = __commonJS({ })(FoldingRangeKind || (exports3.FoldingRangeKind = FoldingRangeKind = {})); var FoldingRange; (function(FoldingRange2) { - function create(startLine, endLine, startCharacter, endCharacter, kind, collapsedText) { + function create(startLine, endLine, startCharacter, endCharacter, kind2, collapsedText) { var result = { startLine, endLine @@ -3507,8 +3519,8 @@ var require_main2 = __commonJS({ if (Is.defined(endCharacter)) { result.endCharacter = endCharacter; } - if (Is.defined(kind)) { - result.kind = kind; + if (Is.defined(kind2)) { + result.kind = kind2; } if (Is.defined(collapsedText)) { result.collapsedText = collapsedText; @@ -3537,13 +3549,13 @@ var require_main2 = __commonJS({ } DiagnosticRelatedInformation2.is = is; })(DiagnosticRelatedInformation || (exports3.DiagnosticRelatedInformation = DiagnosticRelatedInformation = {})); - var DiagnosticSeverity2; - (function(DiagnosticSeverity3) { - DiagnosticSeverity3.Error = 1; - DiagnosticSeverity3.Warning = 2; - DiagnosticSeverity3.Information = 3; - DiagnosticSeverity3.Hint = 4; - })(DiagnosticSeverity2 || (exports3.DiagnosticSeverity = DiagnosticSeverity2 = {})); + var DiagnosticSeverity3; + (function(DiagnosticSeverity4) { + DiagnosticSeverity4.Error = 1; + DiagnosticSeverity4.Warning = 2; + DiagnosticSeverity4.Information = 3; + DiagnosticSeverity4.Hint = 4; + })(DiagnosticSeverity3 || (exports3.DiagnosticSeverity = DiagnosticSeverity3 = {})); var DiagnosticTag; (function(DiagnosticTag2) { DiagnosticTag2.Unnecessary = 1; @@ -3577,9 +3589,9 @@ var require_main2 = __commonJS({ } Diagnostic2.create = create; function is(value) { - var _a; + var _a2; var candidate = value; - return Is.defined(candidate) && Range2.is(candidate.range) && Is.string(candidate.message) && (Is.number(candidate.severity) || Is.undefined(candidate.severity)) && (Is.integer(candidate.code) || Is.string(candidate.code) || Is.undefined(candidate.code)) && (Is.undefined(candidate.codeDescription) || Is.string((_a = candidate.codeDescription) === null || _a === void 0 ? void 0 : _a.href)) && (Is.string(candidate.source) || Is.undefined(candidate.source)) && (Is.undefined(candidate.relatedInformation) || Is.typedArray(candidate.relatedInformation, DiagnosticRelatedInformation.is)); + return Is.defined(candidate) && Range2.is(candidate.range) && Is.string(candidate.message) && (Is.number(candidate.severity) || Is.undefined(candidate.severity)) && (Is.integer(candidate.code) || Is.string(candidate.code) || Is.undefined(candidate.code)) && (Is.undefined(candidate.codeDescription) || Is.string((_a2 = candidate.codeDescription) === null || _a2 === void 0 ? void 0 : _a2.href)) && (Is.string(candidate.source) || Is.undefined(candidate.source)) && (Is.undefined(candidate.relatedInformation) || Is.typedArray(candidate.relatedInformation, DiagnosticRelatedInformation.is)); } Diagnostic2.is = is; })(Diagnostic || (exports3.Diagnostic = Diagnostic = {})); @@ -3605,10 +3617,10 @@ var require_main2 = __commonJS({ })(Command || (exports3.Command = Command = {})); var TextEdit2; (function(TextEdit3) { - function replace(range, newText) { + function replace2(range, newText) { return { range, newText }; } - TextEdit3.replace = replace; + TextEdit3.replace = replace2; function insert(position, newText) { return { range: { start: position, end: position }, newText }; } @@ -3652,10 +3664,10 @@ var require_main2 = __commonJS({ })(ChangeAnnotationIdentifier || (exports3.ChangeAnnotationIdentifier = ChangeAnnotationIdentifier = {})); var AnnotatedTextEdit; (function(AnnotatedTextEdit2) { - function replace(range, newText, annotation) { + function replace2(range, newText, annotation) { return { range, newText, annotationId: annotation }; } - AnnotatedTextEdit2.replace = replace; + AnnotatedTextEdit2.replace = replace2; function insert(position, newText, annotation) { return { range: { start: position, end: position }, newText, annotationId: annotation }; } @@ -3753,11 +3765,11 @@ var require_main2 = __commonJS({ (function(WorkspaceEdit2) { function is(value) { var candidate = value; - return candidate && (candidate.changes !== void 0 || candidate.documentChanges !== void 0) && (candidate.documentChanges === void 0 || candidate.documentChanges.every(function(change) { - if (Is.string(change.kind)) { - return CreateFile.is(change) || RenameFile.is(change) || DeleteFile.is(change); + return candidate && (candidate.changes !== void 0 || candidate.documentChanges !== void 0) && (candidate.documentChanges === void 0 || candidate.documentChanges.every(function(change2) { + if (Is.string(change2.kind)) { + return CreateFile.is(change2) || RenameFile.is(change2) || DeleteFile.is(change2); } else { - return TextDocumentEdit.is(change); + return TextDocumentEdit.is(change2); } })); } @@ -3895,16 +3907,16 @@ var require_main2 = __commonJS({ if (workspaceEdit.documentChanges) { this._changeAnnotations = new ChangeAnnotations(workspaceEdit.changeAnnotations); workspaceEdit.changeAnnotations = this._changeAnnotations.all(); - workspaceEdit.documentChanges.forEach(function(change) { - if (TextDocumentEdit.is(change)) { - var textEditChange = new TextEditChangeImpl(change.edits, _this._changeAnnotations); - _this._textEditChanges[change.textDocument.uri] = textEditChange; + workspaceEdit.documentChanges.forEach(function(change2) { + if (TextDocumentEdit.is(change2)) { + var textEditChange = new TextEditChangeImpl(change2.edits, _this._changeAnnotations); + _this._textEditChanges[change2.textDocument.uri] = textEditChange; } }); } else if (workspaceEdit.changes) { - Object.keys(workspaceEdit.changes).forEach(function(key) { - var textEditChange = new TextEditChangeImpl(workspaceEdit.changes[key]); - _this._textEditChanges[key] = textEditChange; + Object.keys(workspaceEdit.changes).forEach(function(key2) { + var textEditChange = new TextEditChangeImpl(workspaceEdit.changes[key2]); + _this._textEditChanges[key2] = textEditChange; }); } } else { @@ -3930,13 +3942,13 @@ var require_main2 = __commonJS({ enumerable: false, configurable: true }); - WorkspaceChange2.prototype.getTextEditChange = function(key) { - if (OptionalVersionedTextDocumentIdentifier.is(key)) { + WorkspaceChange2.prototype.getTextEditChange = function(key2) { + if (OptionalVersionedTextDocumentIdentifier.is(key2)) { this.initDocumentChanges(); if (this._workspaceEdit.documentChanges === void 0) { throw new Error("Workspace edit is not configured for document changes."); } - var textDocument = { uri: key.uri, version: key.version }; + var textDocument = { uri: key2.uri, version: key2.version }; var result = this._textEditChanges[textDocument.uri]; if (!result) { var edits = []; @@ -3954,12 +3966,12 @@ var require_main2 = __commonJS({ if (this._workspaceEdit.changes === void 0) { throw new Error("Workspace edit is not configured for normal text edit changes."); } - var result = this._textEditChanges[key]; + var result = this._textEditChanges[key2]; if (!result) { var edits = []; - this._workspaceEdit.changes[key] = edits; + this._workspaceEdit.changes[key2] = edits; result = new TextEditChangeImpl(edits); - this._textEditChanges[key] = result; + this._textEditChanges[key2] = result; } return result; } @@ -4118,34 +4130,34 @@ var require_main2 = __commonJS({ } MarkupContent2.is = is; })(MarkupContent || (exports3.MarkupContent = MarkupContent = {})); - var CompletionItemKind2; - (function(CompletionItemKind3) { - CompletionItemKind3.Text = 1; - CompletionItemKind3.Method = 2; - CompletionItemKind3.Function = 3; - CompletionItemKind3.Constructor = 4; - CompletionItemKind3.Field = 5; - CompletionItemKind3.Variable = 6; - CompletionItemKind3.Class = 7; - CompletionItemKind3.Interface = 8; - CompletionItemKind3.Module = 9; - CompletionItemKind3.Property = 10; - CompletionItemKind3.Unit = 11; - CompletionItemKind3.Value = 12; - CompletionItemKind3.Enum = 13; - CompletionItemKind3.Keyword = 14; - CompletionItemKind3.Snippet = 15; - CompletionItemKind3.Color = 16; - CompletionItemKind3.File = 17; - CompletionItemKind3.Reference = 18; - CompletionItemKind3.Folder = 19; - CompletionItemKind3.EnumMember = 20; - CompletionItemKind3.Constant = 21; - CompletionItemKind3.Struct = 22; - CompletionItemKind3.Event = 23; - CompletionItemKind3.Operator = 24; - CompletionItemKind3.TypeParameter = 25; - })(CompletionItemKind2 || (exports3.CompletionItemKind = CompletionItemKind2 = {})); + var CompletionItemKind3; + (function(CompletionItemKind4) { + CompletionItemKind4.Text = 1; + CompletionItemKind4.Method = 2; + CompletionItemKind4.Function = 3; + CompletionItemKind4.Constructor = 4; + CompletionItemKind4.Field = 5; + CompletionItemKind4.Variable = 6; + CompletionItemKind4.Class = 7; + CompletionItemKind4.Interface = 8; + CompletionItemKind4.Module = 9; + CompletionItemKind4.Property = 10; + CompletionItemKind4.Unit = 11; + CompletionItemKind4.Value = 12; + CompletionItemKind4.Enum = 13; + CompletionItemKind4.Keyword = 14; + CompletionItemKind4.Snippet = 15; + CompletionItemKind4.Color = 16; + CompletionItemKind4.File = 17; + CompletionItemKind4.Reference = 18; + CompletionItemKind4.Folder = 19; + CompletionItemKind4.EnumMember = 20; + CompletionItemKind4.Constant = 21; + CompletionItemKind4.Struct = 22; + CompletionItemKind4.Event = 23; + CompletionItemKind4.Operator = 24; + CompletionItemKind4.TypeParameter = 25; + })(CompletionItemKind3 || (exports3.CompletionItemKind = CompletionItemKind3 = {})); var InsertTextFormat; (function(InsertTextFormat2) { InsertTextFormat2.PlainText = 1; @@ -4157,8 +4169,8 @@ var require_main2 = __commonJS({ })(CompletionItemTag || (exports3.CompletionItemTag = CompletionItemTag = {})); var InsertReplaceEdit; (function(InsertReplaceEdit2) { - function create(newText, insert, replace) { - return { newText, insert, replace }; + function create(newText, insert, replace2) { + return { newText, insert, replace: replace2 }; } InsertReplaceEdit2.create = create; function is(value) { @@ -4196,8 +4208,8 @@ var require_main2 = __commonJS({ })(CompletionList || (exports3.CompletionList = CompletionList = {})); var MarkedString; (function(MarkedString2) { - function fromPlainText(plainText2) { - return plainText2.replace(/[\\`*_{}[\]()#+\-.!]/g, "\\$&"); + function fromPlainText(plainText3) { + return plainText3.replace(/[\\`*_{}[\]()#+\-.!]/g, "\\$&"); } MarkedString2.fromPlainText = fromPlainText; function is(value) { @@ -4241,62 +4253,62 @@ var require_main2 = __commonJS({ } SignatureInformation2.create = create; })(SignatureInformation || (exports3.SignatureInformation = SignatureInformation = {})); - var DocumentHighlightKind; - (function(DocumentHighlightKind2) { - DocumentHighlightKind2.Text = 1; - DocumentHighlightKind2.Read = 2; - DocumentHighlightKind2.Write = 3; - })(DocumentHighlightKind || (exports3.DocumentHighlightKind = DocumentHighlightKind = {})); + var DocumentHighlightKind2; + (function(DocumentHighlightKind3) { + DocumentHighlightKind3.Text = 1; + DocumentHighlightKind3.Read = 2; + DocumentHighlightKind3.Write = 3; + })(DocumentHighlightKind2 || (exports3.DocumentHighlightKind = DocumentHighlightKind2 = {})); var DocumentHighlight; (function(DocumentHighlight2) { - function create(range, kind) { + function create(range, kind2) { var result = { range }; - if (Is.number(kind)) { - result.kind = kind; + if (Is.number(kind2)) { + result.kind = kind2; } return result; } DocumentHighlight2.create = create; })(DocumentHighlight || (exports3.DocumentHighlight = DocumentHighlight = {})); - var SymbolKind2; - (function(SymbolKind3) { - SymbolKind3.File = 1; - SymbolKind3.Module = 2; - SymbolKind3.Namespace = 3; - SymbolKind3.Package = 4; - SymbolKind3.Class = 5; - SymbolKind3.Method = 6; - SymbolKind3.Property = 7; - SymbolKind3.Field = 8; - SymbolKind3.Constructor = 9; - SymbolKind3.Enum = 10; - SymbolKind3.Interface = 11; - SymbolKind3.Function = 12; - SymbolKind3.Variable = 13; - SymbolKind3.Constant = 14; - SymbolKind3.String = 15; - SymbolKind3.Number = 16; - SymbolKind3.Boolean = 17; - SymbolKind3.Array = 18; - SymbolKind3.Object = 19; - SymbolKind3.Key = 20; - SymbolKind3.Null = 21; - SymbolKind3.EnumMember = 22; - SymbolKind3.Struct = 23; - SymbolKind3.Event = 24; - SymbolKind3.Operator = 25; - SymbolKind3.TypeParameter = 26; - })(SymbolKind2 || (exports3.SymbolKind = SymbolKind2 = {})); + var SymbolKind3; + (function(SymbolKind4) { + SymbolKind4.File = 1; + SymbolKind4.Module = 2; + SymbolKind4.Namespace = 3; + SymbolKind4.Package = 4; + SymbolKind4.Class = 5; + SymbolKind4.Method = 6; + SymbolKind4.Property = 7; + SymbolKind4.Field = 8; + SymbolKind4.Constructor = 9; + SymbolKind4.Enum = 10; + SymbolKind4.Interface = 11; + SymbolKind4.Function = 12; + SymbolKind4.Variable = 13; + SymbolKind4.Constant = 14; + SymbolKind4.String = 15; + SymbolKind4.Number = 16; + SymbolKind4.Boolean = 17; + SymbolKind4.Array = 18; + SymbolKind4.Object = 19; + SymbolKind4.Key = 20; + SymbolKind4.Null = 21; + SymbolKind4.EnumMember = 22; + SymbolKind4.Struct = 23; + SymbolKind4.Event = 24; + SymbolKind4.Operator = 25; + SymbolKind4.TypeParameter = 26; + })(SymbolKind3 || (exports3.SymbolKind = SymbolKind3 = {})); var SymbolTag; (function(SymbolTag2) { SymbolTag2.Deprecated = 1; })(SymbolTag || (exports3.SymbolTag = SymbolTag = {})); var SymbolInformation; (function(SymbolInformation2) { - function create(name, kind, range, uri, containerName) { + function create(name, kind2, range, uri, containerName) { var result = { name, - kind, + kind: kind2, location: { uri, range } }; if (containerName) { @@ -4308,18 +4320,18 @@ var require_main2 = __commonJS({ })(SymbolInformation || (exports3.SymbolInformation = SymbolInformation = {})); var WorkspaceSymbol; (function(WorkspaceSymbol2) { - function create(name, kind, uri, range) { - return range !== void 0 ? { name, kind, location: { uri, range } } : { name, kind, location: { uri } }; + function create(name, kind2, uri, range) { + return range !== void 0 ? { name, kind: kind2, location: { uri, range } } : { name, kind: kind2, location: { uri } }; } WorkspaceSymbol2.create = create; })(WorkspaceSymbol || (exports3.WorkspaceSymbol = WorkspaceSymbol = {})); var DocumentSymbol; (function(DocumentSymbol2) { - function create(name, detail, kind, range, selectionRange, children) { + function create(name, detail, kind2, range, selectionRange, children) { var result = { name, detail, - kind, + kind: kind2, range, selectionRange }; @@ -4335,18 +4347,18 @@ var require_main2 = __commonJS({ } DocumentSymbol2.is = is; })(DocumentSymbol || (exports3.DocumentSymbol = DocumentSymbol = {})); - var CodeActionKind2; - (function(CodeActionKind3) { - CodeActionKind3.Empty = ""; - CodeActionKind3.QuickFix = "quickfix"; - CodeActionKind3.Refactor = "refactor"; - CodeActionKind3.RefactorExtract = "refactor.extract"; - CodeActionKind3.RefactorInline = "refactor.inline"; - CodeActionKind3.RefactorRewrite = "refactor.rewrite"; - CodeActionKind3.Source = "source"; - CodeActionKind3.SourceOrganizeImports = "source.organizeImports"; - CodeActionKind3.SourceFixAll = "source.fixAll"; - })(CodeActionKind2 || (exports3.CodeActionKind = CodeActionKind2 = {})); + var CodeActionKind3; + (function(CodeActionKind4) { + CodeActionKind4.Empty = ""; + CodeActionKind4.QuickFix = "quickfix"; + CodeActionKind4.Refactor = "refactor"; + CodeActionKind4.RefactorExtract = "refactor.extract"; + CodeActionKind4.RefactorInline = "refactor.inline"; + CodeActionKind4.RefactorRewrite = "refactor.rewrite"; + CodeActionKind4.Source = "source"; + CodeActionKind4.SourceOrganizeImports = "source.organizeImports"; + CodeActionKind4.SourceFixAll = "source.fixAll"; + })(CodeActionKind3 || (exports3.CodeActionKind = CodeActionKind3 = {})); var CodeActionTriggerKind; (function(CodeActionTriggerKind2) { CodeActionTriggerKind2.Invoked = 1; @@ -4354,8 +4366,8 @@ var require_main2 = __commonJS({ })(CodeActionTriggerKind || (exports3.CodeActionTriggerKind = CodeActionTriggerKind = {})); var CodeActionContext; (function(CodeActionContext2) { - function create(diagnostics, only, triggerKind) { - var result = { diagnostics }; + function create(diagnostics2, only, triggerKind) { + var result = { diagnostics: diagnostics2 }; if (only !== void 0 && only !== null) { result.only = only; } @@ -4373,7 +4385,7 @@ var require_main2 = __commonJS({ })(CodeActionContext || (exports3.CodeActionContext = CodeActionContext = {})); var CodeAction; (function(CodeAction2) { - function create(title, kindOrCommandOrEdit, kind) { + function create(title, kindOrCommandOrEdit, kind2) { var result = { title }; var checkKind = true; if (typeof kindOrCommandOrEdit === "string") { @@ -4384,8 +4396,8 @@ var require_main2 = __commonJS({ } else { result.edit = kindOrCommandOrEdit; } - if (checkKind && kind !== void 0) { - result.kind = kind; + if (checkKind && kind2 !== void 0) { + result.kind = kind2; } return result; } @@ -4543,15 +4555,15 @@ var require_main2 = __commonJS({ } InlineValueContext2.is = is; })(InlineValueContext || (exports3.InlineValueContext = InlineValueContext = {})); - var InlayHintKind; - (function(InlayHintKind2) { - InlayHintKind2.Type = 1; - InlayHintKind2.Parameter = 2; + var InlayHintKind2; + (function(InlayHintKind3) { + InlayHintKind3.Type = 1; + InlayHintKind3.Parameter = 2; function is(value) { return value === 1 || value === 2; } - InlayHintKind2.is = is; - })(InlayHintKind || (exports3.InlayHintKind = InlayHintKind = {})); + InlayHintKind3.is = is; + })(InlayHintKind2 || (exports3.InlayHintKind = InlayHintKind2 = {})); var InlayHintLabelPart; (function(InlayHintLabelPart2) { function create(value) { @@ -4566,17 +4578,17 @@ var require_main2 = __commonJS({ })(InlayHintLabelPart || (exports3.InlayHintLabelPart = InlayHintLabelPart = {})); var InlayHint; (function(InlayHint2) { - function create(position, label, kind) { + function create(position, label, kind2) { var result = { position, label }; - if (kind !== void 0) { - result.kind = kind; + if (kind2 !== void 0) { + result.kind = kind2; } return result; } InlayHint2.create = create; function is(value) { var candidate = value; - return Is.objectLiteral(candidate) && Position.is(candidate.position) && (Is.string(candidate.label) || Is.typedArray(candidate.label, InlayHintLabelPart.is)) && (candidate.kind === void 0 || InlayHintKind.is(candidate.kind)) && candidate.textEdits === void 0 || Is.typedArray(candidate.textEdits, TextEdit2.is) && (candidate.tooltip === void 0 || Is.string(candidate.tooltip) || MarkupContent.is(candidate.tooltip)) && (candidate.paddingLeft === void 0 || Is.boolean(candidate.paddingLeft)) && (candidate.paddingRight === void 0 || Is.boolean(candidate.paddingRight)); + return Is.objectLiteral(candidate) && Position.is(candidate.position) && (Is.string(candidate.label) || Is.typedArray(candidate.label, InlayHintLabelPart.is)) && (candidate.kind === void 0 || InlayHintKind2.is(candidate.kind)) && candidate.textEdits === void 0 || Is.typedArray(candidate.textEdits, TextEdit2.is) && (candidate.tooltip === void 0 || Is.string(candidate.tooltip) || MarkupContent.is(candidate.tooltip)) && (candidate.paddingLeft === void 0 || Is.boolean(candidate.paddingLeft)) && (candidate.paddingRight === void 0 || Is.boolean(candidate.paddingRight)); } InlayHint2.is = is; })(InlayHint || (exports3.InlayHint = InlayHint = {})); @@ -4775,8 +4787,8 @@ var require_main2 = __commonJS({ low = mid + 1; } } - var line = low - 1; - return Position.create(line, offset - lineOffsets[line]); + var line2 = low - 1; + return Position.create(line2, offset - lineOffsets[line2]); }; FullTextDocument3.prototype.offsetAt = function(position) { var lineOffsets = this.getLineOffsets(); @@ -5079,12 +5091,12 @@ var require_protocol_selectionRange = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.SelectionRangeRequest = void 0; var messages_1 = require_messages2(); - var SelectionRangeRequest; - (function(SelectionRangeRequest2) { - SelectionRangeRequest2.method = "textDocument/selectionRange"; - SelectionRangeRequest2.messageDirection = messages_1.MessageDirection.clientToServer; - SelectionRangeRequest2.type = new messages_1.ProtocolRequestType(SelectionRangeRequest2.method); - })(SelectionRangeRequest || (exports2.SelectionRangeRequest = SelectionRangeRequest = {})); + var SelectionRangeRequest2; + (function(SelectionRangeRequest3) { + SelectionRangeRequest3.method = "textDocument/selectionRange"; + SelectionRangeRequest3.messageDirection = messages_1.MessageDirection.clientToServer; + SelectionRangeRequest3.type = new messages_1.ProtocolRequestType(SelectionRangeRequest3.method); + })(SelectionRangeRequest2 || (exports2.SelectionRangeRequest = SelectionRangeRequest2 = {})); } }); @@ -5363,12 +5375,12 @@ var require_protocol_inlayHint = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.InlayHintRefreshRequest = exports2.InlayHintResolveRequest = exports2.InlayHintRequest = void 0; var messages_1 = require_messages2(); - var InlayHintRequest; - (function(InlayHintRequest2) { - InlayHintRequest2.method = "textDocument/inlayHint"; - InlayHintRequest2.messageDirection = messages_1.MessageDirection.clientToServer; - InlayHintRequest2.type = new messages_1.ProtocolRequestType(InlayHintRequest2.method); - })(InlayHintRequest || (exports2.InlayHintRequest = InlayHintRequest = {})); + var InlayHintRequest2; + (function(InlayHintRequest3) { + InlayHintRequest3.method = "textDocument/inlayHint"; + InlayHintRequest3.messageDirection = messages_1.MessageDirection.clientToServer; + InlayHintRequest3.type = new messages_1.ProtocolRequestType(InlayHintRequest3.method); + })(InlayHintRequest2 || (exports2.InlayHintRequest = InlayHintRequest2 = {})); var InlayHintResolveRequest; (function(InlayHintResolveRequest2) { InlayHintResolveRequest2.method = "inlayHint/resolve"; @@ -5401,11 +5413,11 @@ var require_protocol_diagnostic = __commonJS({ } DiagnosticServerCancellationData2.is = is; })(DiagnosticServerCancellationData || (exports2.DiagnosticServerCancellationData = DiagnosticServerCancellationData = {})); - var DocumentDiagnosticReportKind; - (function(DocumentDiagnosticReportKind2) { - DocumentDiagnosticReportKind2.Full = "full"; - DocumentDiagnosticReportKind2.Unchanged = "unchanged"; - })(DocumentDiagnosticReportKind || (exports2.DocumentDiagnosticReportKind = DocumentDiagnosticReportKind = {})); + var DocumentDiagnosticReportKind2; + (function(DocumentDiagnosticReportKind3) { + DocumentDiagnosticReportKind3.Full = "full"; + DocumentDiagnosticReportKind3.Unchanged = "unchanged"; + })(DocumentDiagnosticReportKind2 || (exports2.DocumentDiagnosticReportKind = DocumentDiagnosticReportKind2 = {})); var DocumentDiagnosticRequest; (function(DocumentDiagnosticRequest2) { DocumentDiagnosticRequest2.method = "textDocument/diagnostic"; @@ -5475,8 +5487,8 @@ var require_protocol_notebook = __commonJS({ })(ExecutionSummary || (exports2.ExecutionSummary = ExecutionSummary = {})); var NotebookCell; (function(NotebookCell2) { - function create(kind, document) { - return { kind, document }; + function create(kind2, document) { + return { kind: kind2, document }; } NotebookCell2.create = create; function is(value) { @@ -5970,12 +5982,12 @@ var require_protocol = __commonJS({ ExitNotification2.messageDirection = messages_1.MessageDirection.clientToServer; ExitNotification2.type = new messages_1.ProtocolNotificationType0(ExitNotification2.method); })(ExitNotification || (exports2.ExitNotification = ExitNotification = {})); - var DidChangeConfigurationNotification; - (function(DidChangeConfigurationNotification2) { - DidChangeConfigurationNotification2.method = "workspace/didChangeConfiguration"; - DidChangeConfigurationNotification2.messageDirection = messages_1.MessageDirection.clientToServer; - DidChangeConfigurationNotification2.type = new messages_1.ProtocolNotificationType(DidChangeConfigurationNotification2.method); - })(DidChangeConfigurationNotification || (exports2.DidChangeConfigurationNotification = DidChangeConfigurationNotification = {})); + var DidChangeConfigurationNotification2; + (function(DidChangeConfigurationNotification3) { + DidChangeConfigurationNotification3.method = "workspace/didChangeConfiguration"; + DidChangeConfigurationNotification3.messageDirection = messages_1.MessageDirection.clientToServer; + DidChangeConfigurationNotification3.type = new messages_1.ProtocolNotificationType(DidChangeConfigurationNotification3.method); + })(DidChangeConfigurationNotification2 || (exports2.DidChangeConfigurationNotification = DidChangeConfigurationNotification2 = {})); var MessageType; (function(MessageType2) { MessageType2.Error = 1; @@ -6069,18 +6081,18 @@ var require_protocol = __commonJS({ WillSaveTextDocumentWaitUntilRequest2.messageDirection = messages_1.MessageDirection.clientToServer; WillSaveTextDocumentWaitUntilRequest2.type = new messages_1.ProtocolRequestType(WillSaveTextDocumentWaitUntilRequest2.method); })(WillSaveTextDocumentWaitUntilRequest || (exports2.WillSaveTextDocumentWaitUntilRequest = WillSaveTextDocumentWaitUntilRequest = {})); - var DidChangeWatchedFilesNotification; - (function(DidChangeWatchedFilesNotification2) { - DidChangeWatchedFilesNotification2.method = "workspace/didChangeWatchedFiles"; - DidChangeWatchedFilesNotification2.messageDirection = messages_1.MessageDirection.clientToServer; - DidChangeWatchedFilesNotification2.type = new messages_1.ProtocolNotificationType(DidChangeWatchedFilesNotification2.method); - })(DidChangeWatchedFilesNotification || (exports2.DidChangeWatchedFilesNotification = DidChangeWatchedFilesNotification = {})); - var FileChangeType; - (function(FileChangeType2) { - FileChangeType2.Created = 1; - FileChangeType2.Changed = 2; - FileChangeType2.Deleted = 3; - })(FileChangeType || (exports2.FileChangeType = FileChangeType = {})); + var DidChangeWatchedFilesNotification2; + (function(DidChangeWatchedFilesNotification3) { + DidChangeWatchedFilesNotification3.method = "workspace/didChangeWatchedFiles"; + DidChangeWatchedFilesNotification3.messageDirection = messages_1.MessageDirection.clientToServer; + DidChangeWatchedFilesNotification3.type = new messages_1.ProtocolNotificationType(DidChangeWatchedFilesNotification3.method); + })(DidChangeWatchedFilesNotification2 || (exports2.DidChangeWatchedFilesNotification = DidChangeWatchedFilesNotification2 = {})); + var FileChangeType2; + (function(FileChangeType3) { + FileChangeType3.Created = 1; + FileChangeType3.Changed = 2; + FileChangeType3.Deleted = 3; + })(FileChangeType2 || (exports2.FileChangeType = FileChangeType2 = {})); var RelativePattern; (function(RelativePattern2) { function is(value) { @@ -6149,12 +6161,12 @@ var require_protocol = __commonJS({ ReferencesRequest3.messageDirection = messages_1.MessageDirection.clientToServer; ReferencesRequest3.type = new messages_1.ProtocolRequestType(ReferencesRequest3.method); })(ReferencesRequest2 || (exports2.ReferencesRequest = ReferencesRequest2 = {})); - var DocumentHighlightRequest; - (function(DocumentHighlightRequest2) { - DocumentHighlightRequest2.method = "textDocument/documentHighlight"; - DocumentHighlightRequest2.messageDirection = messages_1.MessageDirection.clientToServer; - DocumentHighlightRequest2.type = new messages_1.ProtocolRequestType(DocumentHighlightRequest2.method); - })(DocumentHighlightRequest || (exports2.DocumentHighlightRequest = DocumentHighlightRequest = {})); + var DocumentHighlightRequest2; + (function(DocumentHighlightRequest3) { + DocumentHighlightRequest3.method = "textDocument/documentHighlight"; + DocumentHighlightRequest3.messageDirection = messages_1.MessageDirection.clientToServer; + DocumentHighlightRequest3.type = new messages_1.ProtocolRequestType(DocumentHighlightRequest3.method); + })(DocumentHighlightRequest2 || (exports2.DocumentHighlightRequest = DocumentHighlightRequest2 = {})); var DocumentSymbolRequest2; (function(DocumentSymbolRequest3) { DocumentSymbolRequest3.method = "textDocument/documentSymbol"; @@ -6173,12 +6185,12 @@ var require_protocol = __commonJS({ CodeActionResolveRequest2.messageDirection = messages_1.MessageDirection.clientToServer; CodeActionResolveRequest2.type = new messages_1.ProtocolRequestType(CodeActionResolveRequest2.method); })(CodeActionResolveRequest || (exports2.CodeActionResolveRequest = CodeActionResolveRequest = {})); - var WorkspaceSymbolRequest; - (function(WorkspaceSymbolRequest2) { - WorkspaceSymbolRequest2.method = "workspace/symbol"; - WorkspaceSymbolRequest2.messageDirection = messages_1.MessageDirection.clientToServer; - WorkspaceSymbolRequest2.type = new messages_1.ProtocolRequestType(WorkspaceSymbolRequest2.method); - })(WorkspaceSymbolRequest || (exports2.WorkspaceSymbolRequest = WorkspaceSymbolRequest = {})); + var WorkspaceSymbolRequest2; + (function(WorkspaceSymbolRequest3) { + WorkspaceSymbolRequest3.method = "workspace/symbol"; + WorkspaceSymbolRequest3.messageDirection = messages_1.MessageDirection.clientToServer; + WorkspaceSymbolRequest3.type = new messages_1.ProtocolRequestType(WorkspaceSymbolRequest3.method); + })(WorkspaceSymbolRequest2 || (exports2.WorkspaceSymbolRequest = WorkspaceSymbolRequest2 = {})); var WorkspaceSymbolResolveRequest; (function(WorkspaceSymbolResolveRequest2) { WorkspaceSymbolResolveRequest2.method = "workspaceSymbol/resolve"; @@ -6203,12 +6215,12 @@ var require_protocol = __commonJS({ CodeLensRefreshRequest2.messageDirection = messages_1.MessageDirection.serverToClient; CodeLensRefreshRequest2.type = new messages_1.ProtocolRequestType0(CodeLensRefreshRequest2.method); })(CodeLensRefreshRequest || (exports2.CodeLensRefreshRequest = CodeLensRefreshRequest = {})); - var DocumentLinkRequest; - (function(DocumentLinkRequest2) { - DocumentLinkRequest2.method = "textDocument/documentLink"; - DocumentLinkRequest2.messageDirection = messages_1.MessageDirection.clientToServer; - DocumentLinkRequest2.type = new messages_1.ProtocolRequestType(DocumentLinkRequest2.method); - })(DocumentLinkRequest || (exports2.DocumentLinkRequest = DocumentLinkRequest = {})); + var DocumentLinkRequest2; + (function(DocumentLinkRequest3) { + DocumentLinkRequest3.method = "textDocument/documentLink"; + DocumentLinkRequest3.messageDirection = messages_1.MessageDirection.clientToServer; + DocumentLinkRequest3.type = new messages_1.ProtocolRequestType(DocumentLinkRequest3.method); + })(DocumentLinkRequest2 || (exports2.DocumentLinkRequest = DocumentLinkRequest2 = {})); var DocumentLinkResolveRequest; (function(DocumentLinkResolveRequest2) { DocumentLinkResolveRequest2.method = "documentLink/resolve"; @@ -6221,24 +6233,24 @@ var require_protocol = __commonJS({ DocumentFormattingRequest3.messageDirection = messages_1.MessageDirection.clientToServer; DocumentFormattingRequest3.type = new messages_1.ProtocolRequestType(DocumentFormattingRequest3.method); })(DocumentFormattingRequest2 || (exports2.DocumentFormattingRequest = DocumentFormattingRequest2 = {})); - var DocumentRangeFormattingRequest; - (function(DocumentRangeFormattingRequest2) { - DocumentRangeFormattingRequest2.method = "textDocument/rangeFormatting"; - DocumentRangeFormattingRequest2.messageDirection = messages_1.MessageDirection.clientToServer; - DocumentRangeFormattingRequest2.type = new messages_1.ProtocolRequestType(DocumentRangeFormattingRequest2.method); - })(DocumentRangeFormattingRequest || (exports2.DocumentRangeFormattingRequest = DocumentRangeFormattingRequest = {})); + var DocumentRangeFormattingRequest2; + (function(DocumentRangeFormattingRequest3) { + DocumentRangeFormattingRequest3.method = "textDocument/rangeFormatting"; + DocumentRangeFormattingRequest3.messageDirection = messages_1.MessageDirection.clientToServer; + DocumentRangeFormattingRequest3.type = new messages_1.ProtocolRequestType(DocumentRangeFormattingRequest3.method); + })(DocumentRangeFormattingRequest2 || (exports2.DocumentRangeFormattingRequest = DocumentRangeFormattingRequest2 = {})); var DocumentRangesFormattingRequest; (function(DocumentRangesFormattingRequest2) { DocumentRangesFormattingRequest2.method = "textDocument/rangesFormatting"; DocumentRangesFormattingRequest2.messageDirection = messages_1.MessageDirection.clientToServer; DocumentRangesFormattingRequest2.type = new messages_1.ProtocolRequestType(DocumentRangesFormattingRequest2.method); })(DocumentRangesFormattingRequest || (exports2.DocumentRangesFormattingRequest = DocumentRangesFormattingRequest = {})); - var DocumentOnTypeFormattingRequest; - (function(DocumentOnTypeFormattingRequest2) { - DocumentOnTypeFormattingRequest2.method = "textDocument/onTypeFormatting"; - DocumentOnTypeFormattingRequest2.messageDirection = messages_1.MessageDirection.clientToServer; - DocumentOnTypeFormattingRequest2.type = new messages_1.ProtocolRequestType(DocumentOnTypeFormattingRequest2.method); - })(DocumentOnTypeFormattingRequest || (exports2.DocumentOnTypeFormattingRequest = DocumentOnTypeFormattingRequest = {})); + var DocumentOnTypeFormattingRequest2; + (function(DocumentOnTypeFormattingRequest3) { + DocumentOnTypeFormattingRequest3.method = "textDocument/onTypeFormatting"; + DocumentOnTypeFormattingRequest3.messageDirection = messages_1.MessageDirection.clientToServer; + DocumentOnTypeFormattingRequest3.type = new messages_1.ProtocolRequestType(DocumentOnTypeFormattingRequest3.method); + })(DocumentOnTypeFormattingRequest2 || (exports2.DocumentOnTypeFormattingRequest = DocumentOnTypeFormattingRequest2 = {})); var PrepareSupportDefaultBehavior; (function(PrepareSupportDefaultBehavior2) { PrepareSupportDefaultBehavior2.Identifier = 1; @@ -6255,12 +6267,12 @@ var require_protocol = __commonJS({ PrepareRenameRequest3.messageDirection = messages_1.MessageDirection.clientToServer; PrepareRenameRequest3.type = new messages_1.ProtocolRequestType(PrepareRenameRequest3.method); })(PrepareRenameRequest2 || (exports2.PrepareRenameRequest = PrepareRenameRequest2 = {})); - var ExecuteCommandRequest; - (function(ExecuteCommandRequest2) { - ExecuteCommandRequest2.method = "workspace/executeCommand"; - ExecuteCommandRequest2.messageDirection = messages_1.MessageDirection.clientToServer; - ExecuteCommandRequest2.type = new messages_1.ProtocolRequestType(ExecuteCommandRequest2.method); - })(ExecuteCommandRequest || (exports2.ExecuteCommandRequest = ExecuteCommandRequest = {})); + var ExecuteCommandRequest2; + (function(ExecuteCommandRequest3) { + ExecuteCommandRequest3.method = "workspace/executeCommand"; + ExecuteCommandRequest3.messageDirection = messages_1.MessageDirection.clientToServer; + ExecuteCommandRequest3.type = new messages_1.ProtocolRequestType(ExecuteCommandRequest3.method); + })(ExecuteCommandRequest2 || (exports2.ExecuteCommandRequest = ExecuteCommandRequest2 = {})); var ApplyWorkspaceEditRequest; (function(ApplyWorkspaceEditRequest2) { ApplyWorkspaceEditRequest2.method = "workspace/applyEdit"; @@ -6814,7 +6826,7 @@ var require_semanticTokens = __commonJS({ } }; exports2.SemanticTokensDiff = SemanticTokensDiff; - var SemanticTokensBuilder = class { + var SemanticTokensBuilder3 = class { constructor() { this._prevData = void 0; this.initialize(); @@ -6826,8 +6838,8 @@ var require_semanticTokens = __commonJS({ this._data = []; this._dataLen = 0; } - push(line, char, length, tokenType, tokenModifiers) { - let pushLine = line; + push(line2, char, length, tokenType, tokenModifiers) { + let pushLine = line2; let pushChar = char; if (this._dataLen > 0) { pushLine -= this._prevLine; @@ -6840,7 +6852,7 @@ var require_semanticTokens = __commonJS({ this._data[this._dataLen++] = length; this._data[this._dataLen++] = tokenType; this._data[this._dataLen++] = tokenModifiers; - this._prevLine = line; + this._prevLine = line2; this._prevChar = char; } get id() { @@ -6873,7 +6885,7 @@ var require_semanticTokens = __commonJS({ } } }; - exports2.SemanticTokensBuilder = SemanticTokensBuilder; + exports2.SemanticTokensBuilder = SemanticTokensBuilder3; } }); @@ -7385,8 +7397,8 @@ var require_notebook = __commonJS({ return value && value[0]; } findNotebookDocumentForCell(cell) { - const key = typeof cell === "string" ? cell : cell.document; - const value = this.notebookCellMap.get(key); + const key2 = typeof cell === "string" ? cell : cell.document; + const value = this.notebookCellMap.get(key2); return value && value[1]; } get onDidOpen() { @@ -7432,17 +7444,17 @@ var require_notebook = __commonJS({ notebookDocument.version = params.notebookDocument.version; const oldMetadata = notebookDocument.metadata; let metadataChanged = false; - const change = params.change; - if (change.metadata !== void 0) { + const change2 = params.change; + if (change2.metadata !== void 0) { metadataChanged = true; - notebookDocument.metadata = change.metadata; + notebookDocument.metadata = change2.metadata; } const opened = []; const closed = []; const data = []; const text = []; - if (change.cells !== void 0) { - const changedCells = change.cells; + if (change2.cells !== void 0) { + const changedCells = change2.cells; if (changedCells.structure !== void 0) { const array = changedCells.structure.array; notebookDocument.cells.splice(array.start, array.deleteCount, ...array.cells !== void 0 ? array.cells : []); @@ -7462,11 +7474,11 @@ var require_notebook = __commonJS({ if (changedCells.data !== void 0) { const cellUpdates = new Map(changedCells.data.map((cell) => [cell.document, cell])); for (let i = 0; i <= notebookDocument.cells.length; i++) { - const change2 = cellUpdates.get(notebookDocument.cells[i].document); - if (change2 !== void 0) { - const old = notebookDocument.cells.splice(i, 1, change2); - data.push({ old: old[0], new: change2 }); - cellUpdates.delete(change2.document); + const change3 = cellUpdates.get(notebookDocument.cells[i].document); + if (change3 !== void 0) { + const old = notebookDocument.cells.splice(i, 1, change3); + data.push({ old: old[0], new: change3 }); + cellUpdates.delete(change3.document); if (cellUpdates.size === 0) { break; } @@ -7494,8 +7506,8 @@ var require_notebook = __commonJS({ removed.push(this.getNotebookCell(close)); } const textContent = []; - for (const change2 of text) { - textContent.push(this.getNotebookCell(change2)); + for (const change3 of text) { + textContent.push(this.getNotebookCell(change3)); } if (added.length > 0 || removed.length > 0 || data.length > 0 || textContent.length > 0) { changeEvent.cells = { added, removed, changed: { data, textContent } }; @@ -8318,7 +8330,7 @@ var require_files = __commonJS({ Object.defineProperty(exports2, "__esModule", { value: true }); exports2.resolveModulePath = exports2.FileSystem = exports2.resolveGlobalYarnPath = exports2.resolveGlobalNodePath = exports2.resolve = exports2.uriToFilePath = void 0; var url = require("url"); - var path = require("path"); + var path8 = require("path"); var fs = require("fs"); var child_process_1 = require("child_process"); function uriToFilePath(uri) { @@ -8337,7 +8349,7 @@ var require_files = __commonJS({ segments.shift(); } } - return path.normalize(segments.join("/")); + return path8.normalize(segments.join("/")); } exports2.uriToFilePath = uriToFilePath; function isWindows() { @@ -8365,10 +8377,10 @@ var require_files = __commonJS({ return new Promise((resolve3, reject) => { let env = process.env; let newEnv = /* @__PURE__ */ Object.create(null); - Object.keys(env).forEach((key) => newEnv[key] = env[key]); + Object.keys(env).forEach((key2) => newEnv[key2] = env[key2]); if (nodePath && fs.existsSync(nodePath)) { if (newEnv[nodePathKey]) { - newEnv[nodePathKey] = nodePath + path.delimiter + newEnv[nodePathKey]; + newEnv[nodePathKey] = nodePath + path8.delimiter + newEnv[nodePathKey]; } else { newEnv[nodePathKey] = nodePath; } @@ -8414,7 +8426,7 @@ var require_files = __commonJS({ function resolveGlobalNodePath(tracer) { let npmCommand = "npm"; const env = /* @__PURE__ */ Object.create(null); - Object.keys(process.env).forEach((key) => env[key] = process.env[key]); + Object.keys(process.env).forEach((key2) => env[key2] = process.env[key2]); env["NO_UPDATE_NOTIFIER"] = "true"; const options = { encoding: "utf8", @@ -8441,9 +8453,9 @@ var require_files = __commonJS({ } if (prefix.length > 0) { if (isWindows()) { - return path.join(prefix, "node_modules"); + return path8.join(prefix, "node_modules"); } else { - return path.join(prefix, "lib", "node_modules"); + return path8.join(prefix, "lib", "node_modules"); } } return void 0; @@ -8479,11 +8491,11 @@ var require_files = __commonJS({ return void 0; } let lines = stdout.trim().split(/\r?\n/); - for (let line of lines) { + for (let line2 of lines) { try { - let yarn = JSON.parse(line); + let yarn = JSON.parse(line2); if (yarn.type === "log") { - return path.join(yarn.data, "node_modules"); + return path8.join(yarn.data, "node_modules"); } } catch (e) { } @@ -8513,17 +8525,17 @@ var require_files = __commonJS({ FileSystem2.isCaseSensitive = isCaseSensitive; function isParent(parent, child) { if (isCaseSensitive()) { - return path.normalize(child).indexOf(path.normalize(parent)) === 0; + return path8.normalize(child).indexOf(path8.normalize(parent)) === 0; } else { - return path.normalize(child).toLowerCase().indexOf(path.normalize(parent).toLowerCase()) === 0; + return path8.normalize(child).toLowerCase().indexOf(path8.normalize(parent).toLowerCase()) === 0; } } FileSystem2.isParent = isParent; })(FileSystem || (exports2.FileSystem = FileSystem = {})); function resolveModulePath(workspaceRoot, moduleName, nodePath, tracer) { if (nodePath) { - if (!path.isAbsolute(nodePath)) { - nodePath = path.join(workspaceRoot, nodePath); + if (!path8.isAbsolute(nodePath)) { + nodePath = path8.join(workspaceRoot, nodePath); } return resolve2(moduleName, nodePath, nodePath, tracer).then((value) => { if (FileSystem.isParent(nodePath, value)) { @@ -8819,7 +8831,7 @@ var require_main4 = __commonJS({ return (0, server_1.createConnection)(connectionFactory, watchDog, factories); } function patchConsole(logger) { - function serialize(args) { + function serialize2(args) { return args.map((arg) => typeof arg === "string" ? arg : (0, node_util_1.inspect)(arg)).join(" "); } const counters = /* @__PURE__ */ new Map(); @@ -8831,7 +8843,7 @@ var require_main4 = __commonJS({ logger.error("Assertion failed"); } else { const [message, ...rest] = args; - logger.error(`Assertion failed: ${message} ${serialize(rest)}`); + logger.error(`Assertion failed: ${message} ${serialize2(rest)}`); } }; console.count = function count(label = "default") { @@ -8849,28 +8861,28 @@ var require_main4 = __commonJS({ } }; console.debug = function debug(...args) { - logger.log(serialize(args)); + logger.log(serialize2(args)); }; console.dir = function dir(arg, options) { logger.log((0, node_util_1.inspect)(arg, options)); }; console.log = function log(...args) { - logger.log(serialize(args)); + logger.log(serialize2(args)); }; console.error = function error(...args) { - logger.error(serialize(args)); + logger.error(serialize2(args)); }; console.trace = function trace(...args) { const stack = new Error().stack.replace(/(.+\n){2}/, ""); let message = "Trace"; if (args.length !== 0) { - message += `: ${serialize(args)}`; + message += `: ${serialize2(args)}`; } logger.log(`${message} ${stack}`); }; - console.warn = function warn(...args) { - logger.warn(serialize(args)); + console.warn = function warn2(...args) { + logger.warn(serialize2(args)); }; } } @@ -8884,438 +8896,441 @@ var require_node3 = __commonJS({ } }); -// dist/server.js -var import_node5 = __toESM(require_node3(), 1); - -// node_modules/vscode-languageserver-textdocument/lib/esm/main.js -var FullTextDocument = class _FullTextDocument { - constructor(uri, languageId, version, content) { - this._uri = uri; - this._languageId = languageId; - this._version = version; - this._content = content; - this._lineOffsets = void 0; - } - get uri() { - return this._uri; - } - get languageId() { - return this._languageId; - } - get version() { - return this._version; - } - getText(range) { - if (range) { - const start = this.offsetAt(range.start); - const end = this.offsetAt(range.end); - return this._content.substring(start, end); - } - return this._content; - } - update(changes, version) { - for (const change of changes) { - if (_FullTextDocument.isIncremental(change)) { - const range = getWellformedRange(change.range); - const startOffset = this.offsetAt(range.start); - const endOffset = this.offsetAt(range.end); - this._content = this._content.substring(0, startOffset) + change.text + this._content.substring(endOffset, this._content.length); - const startLine = Math.max(range.start.line, 0); - const endLine = Math.max(range.end.line, 0); - let lineOffsets = this._lineOffsets; - const addedLineOffsets = computeLineOffsets(change.text, false, startOffset); - if (endLine - startLine === addedLineOffsets.length) { - for (let i = 0, len = addedLineOffsets.length; i < len; i++) { - lineOffsets[i + startLine + 1] = addedLineOffsets[i]; - } - } else { - if (addedLineOffsets.length < 1e4) { - lineOffsets.splice(startLine + 1, endLine - startLine, ...addedLineOffsets); - } else { - this._lineOffsets = lineOffsets = lineOffsets.slice(0, startLine + 1).concat(addedLineOffsets, lineOffsets.slice(endLine + 1)); - } - } - const diff = change.text.length - (endOffset - startOffset); - if (diff !== 0) { - for (let i = startLine + 1 + addedLineOffsets.length, len = lineOffsets.length; i < len; i++) { - lineOffsets[i] = lineOffsets[i] + diff; - } - } - } else if (_FullTextDocument.isFull(change)) { - this._content = change.text; - this._lineOffsets = void 0; - } else { - throw new Error("Unknown change event received"); - } - } - this._version = version; - } - getLineOffsets() { - if (this._lineOffsets === void 0) { - this._lineOffsets = computeLineOffsets(this._content, true); - } - return this._lineOffsets; - } - positionAt(offset) { - offset = Math.max(Math.min(offset, this._content.length), 0); - const lineOffsets = this.getLineOffsets(); - let low = 0, high = lineOffsets.length; - if (high === 0) { - return { line: 0, character: offset }; - } - while (low < high) { - const mid = Math.floor((low + high) / 2); - if (lineOffsets[mid] > offset) { - high = mid; - } else { - low = mid + 1; - } - } - const line = low - 1; - offset = this.ensureBeforeEOL(offset, lineOffsets[line]); - return { line, character: offset - lineOffsets[line] }; - } - offsetAt(position) { - const lineOffsets = this.getLineOffsets(); - if (position.line >= lineOffsets.length) { - return this._content.length; - } else if (position.line < 0) { - return 0; - } - const lineOffset = lineOffsets[position.line]; - if (position.character <= 0) { - return lineOffset; - } - const nextLineOffset = position.line + 1 < lineOffsets.length ? lineOffsets[position.line + 1] : this._content.length; - const offset = Math.min(lineOffset + position.character, nextLineOffset); - return this.ensureBeforeEOL(offset, lineOffset); - } - ensureBeforeEOL(offset, lineOffset) { - while (offset > lineOffset && isEOL(this._content.charCodeAt(offset - 1))) { - offset--; - } - return offset; - } - get lineCount() { - return this.getLineOffsets().length; - } - static isIncremental(event) { - const candidate = event; - return candidate !== void 0 && candidate !== null && typeof candidate.text === "string" && candidate.range !== void 0 && (candidate.rangeLength === void 0 || typeof candidate.rangeLength === "number"); - } - static isFull(event) { - const candidate = event; - return candidate !== void 0 && candidate !== null && typeof candidate.text === "string" && candidate.range === void 0 && candidate.rangeLength === void 0; - } -}; -var TextDocument; -(function(TextDocument2) { - function create(uri, languageId, version, content) { - return new FullTextDocument(uri, languageId, version, content); - } - TextDocument2.create = create; - function update(document, changes, version) { - if (document instanceof FullTextDocument) { - document.update(changes, version); - return document; - } else { - throw new Error("TextDocument.update: document must be created by TextDocument.create"); - } +// node_modules/@markup-carve/carve/dist/ast.js +var CANONICAL_ADMONITION_KINDS, SMART_PUNCTUATION_GLYPHS; +var init_ast = __esm({ + "node_modules/@markup-carve/carve/dist/ast.js"() { + CANONICAL_ADMONITION_KINDS = /* @__PURE__ */ new Set([ + "note", + "tip", + "warning", + "danger", + "info", + "success", + "example", + "quote" + ]); + SMART_PUNCTUATION_GLYPHS = { + ellipsis: "\u2026", + em_dash: "\u2014", + en_dash: "\u2013", + left_right_arrow: "\u2194", + rightwards_arrow: "\u2192", + leftwards_arrow: "\u2190", + rightwards_double_arrow: "\u21D2", + less_than_or_equal: "\u2264", + greater_than_or_equal: "\u2265", + not_equal: "\u2260", + plus_minus: "\xB1", + copyright: "\xA9", + registered: "\xAE", + trademark: "\u2122" + }; } - TextDocument2.update = update; - function applyEdits(document, edits) { - const text = document.getText(); - const sortedEdits = mergeSort(edits.map(getWellformedEdit), (a, b) => { - const diff = a.range.start.line - b.range.start.line; - if (diff === 0) { - return a.range.start.character - b.range.start.character; - } - return diff; - }); - let lastModifiedOffset = 0; - const spans = []; - for (const e of sortedEdits) { - const startOffset = document.offsetAt(e.range.start); - if (startOffset < lastModifiedOffset) { - throw new Error("Overlapping edit"); - } else if (startOffset > lastModifiedOffset) { - spans.push(text.substring(lastModifiedOffset, startOffset)); +}); + +// node_modules/@markup-carve/carve/dist/abbr-budget.js +function utf8ByteLength(s) { + return UTF8_ENCODER.encode(s).length; +} +function abbrBudget(srcByteLength) { + return Math.max(ABBR_BUDGET_BASE, ABBR_BUDGET_FACTOR * (srcByteLength ?? 0)); +} +function budgetForDocument(ast) { + return new AbbrBudget(expansionBudgetLength(ast)); +} +function recordIngestPayloadLength(doc, bytes) { + ingestPayloadLength.set(doc, bytes); +} +function expansionBudgetLength(ast) { + const claimed = ast.srcByteLength ?? 0; + const measured = ingestPayloadLength.get(ast); + return measured === void 0 ? claimed : Math.min(claimed, measured); +} +var UTF8_ENCODER, ABBR_BUDGET_BASE, ABBR_BUDGET_FACTOR, ingestPayloadLength, AbbrBudget; +var init_abbr_budget = __esm({ + "node_modules/@markup-carve/carve/dist/abbr-budget.js"() { + UTF8_ENCODER = new TextEncoder(); + ABBR_BUDGET_BASE = 1e6; + ABBR_BUDGET_FACTOR = 8; + ingestPayloadLength = /* @__PURE__ */ new WeakMap(); + AbbrBudget = class { + remaining; + constructor(srcByteLength) { + this.remaining = abbrBudget(srcByteLength); } - if (e.newText.length) { - spans.push(e.newText); + /** + * Try to spend `cost` bytes of budget. Returns true if it fit (and the + * budget was decremented); false if it would overflow (budget untouched, so + * a later shorter expansion could still fit - though in practice all + * occurrences share one expansion, this keeps the bound monotonic). + */ + charge(cost) { + if (cost > this.remaining) + return false; + this.remaining -= cost; + return true; } - lastModifiedOffset = document.offsetAt(e.range.end); - } - spans.push(text.substr(lastModifiedOffset)); - return spans.join(""); - } - TextDocument2.applyEdits = applyEdits; -})(TextDocument || (TextDocument = {})); -function mergeSort(data, compare) { - if (data.length <= 1) { - return data; - } - const p = data.length / 2 | 0; - const left = data.slice(0, p); - const right = data.slice(p); - mergeSort(left, compare); - mergeSort(right, compare); - let leftIdx = 0; - let rightIdx = 0; - let i = 0; - while (leftIdx < left.length && rightIdx < right.length) { - const ret = compare(left[leftIdx], right[rightIdx]); - if (ret <= 0) { - data[i++] = left[leftIdx++]; - } else { - data[i++] = right[rightIdx++]; - } - } - while (leftIdx < left.length) { - data[i++] = left[leftIdx++]; - } - while (rightIdx < right.length) { - data[i++] = right[rightIdx++]; + }; } - return data; +}); + +// node_modules/@markup-carve/carve/dist/trim-non-nbsp.js +function isTrimmable(text, index2) { + const code = text.charCodeAt(index2); + return code === 32 || code === 9 || code === 10 || code === 13; } -function computeLineOffsets(text, isAtLineStart, textOffset = 0) { - const result = isAtLineStart ? [textOffset] : []; - for (let i = 0; i < text.length; i++) { - const ch = text.charCodeAt(i); - if (isEOL(ch)) { - if (ch === 13 && i + 1 < text.length && text.charCodeAt(i + 1) === 10) { - i++; - } - result.push(textOffset + i + 1); - } - } - return result; +function isCarveWhitespace(ch) { + if (ch === void 0) + return false; + const code = ch.charCodeAt(0); + return code === 32 || code === 9 || code === 10 || code === 13; } -function isEOL(char) { - return char === 13 || char === 10; +function trimNonNbsp(text) { + let start = 0; + let end = text.length; + while (start < end && isTrimmable(text, start)) + start++; + while (end > start && isTrimmable(text, end - 1)) + end--; + if (start === 0 && end === text.length) + return text; + return text.slice(start, end); } -function getWellformedRange(range) { - const start = range.start; - const end = range.end; - if (start.line > end.line || start.line === end.line && start.character > end.character) { - return { start: end, end: start }; - } - return range; +function trimEndNonNbsp(text) { + let end = text.length; + while (end > 0 && isTrimmable(text, end - 1)) + end--; + if (end === text.length) + return text; + return text.slice(0, end); } -function getWellformedEdit(textEdit) { - const range = getWellformedRange(textEdit.range); - if (range !== textEdit.range) { - return { newText: textEdit.newText, range }; +var init_trim_non_nbsp = __esm({ + "node_modules/@markup-carve/carve/dist/trim-non-nbsp.js"() { } - return textEdit; -} - -// dist/analyze.js -var import_node = __toESM(require_node3(), 1); - -// node_modules/@markup-carve/carve/dist/abbr-budget.js -var UTF8_ENCODER = new TextEncoder(); -function utf8ByteLength(s) { - return UTF8_ENCODER.encode(s).length; -} +}); // node_modules/@markup-carve/carve/dist/parse.js -var activeMatchers = []; -var activeMatcherCtx = null; -var RE_HEADING = /^(#{1,6}) +(.+?)(?:\s+\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?\s*$/; -var RE_HR = /^([-*_])\1{2,}[ \t]*$/; -var RE_FENCE = /^()(`{3,}|~{3,})\s*(?:([a-zA-Z0-9_+#/.-]+)(?:\s+("[^"]*"))?(?:\s+(\[[^\]]*\]))?|("[^"]*")(?:\s+(\[[^\]]*\]))?|(\[[^\]]*\]))?\s*$/; -var RE_UNORDERED = /^([^\S\u00a0]*)[-*] +([\S\u00a0].*)$/; -var RE_ORDERED = /^([^\S\u00a0]*)([0-9]+|[ivxlcdm]+|[IVXLCDM]+|[a-z]|[A-Z])([.)]) +([\S\u00a0].*)$/; -var RE_TASK = /^([^\S\u00a0]*)[-*] +\[([ xX\-_>?])\] +([\S\u00a0].*)$/; -var RE_ITEM_ATTR = /^([^\S\u00a0]*)((?:[-*])|(?:[0-9]+|[ivxlcdm]+|[IVXLCDM]+|[a-z]|[A-Z])[.)])\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')*)\}( +[\S\u00a0].*)$/; -function extractItemAttr(line) { - const m = RE_ITEM_ATTR.exec(line); +function fenceCloseRe(marker) { + return new RegExp(`^${marker[0]}{${marker.length},}${FENCE_TRAILING_WS}`); +} +function extractItemAttr(line2) { + const m = RE_ITEM_ATTR.exec(line2); if (!m) return null; - if (!isValidAttrPayload(m[3])) + if (!isValidInlineAttrPayload(m[3])) return null; - return { stripped: m[1] + m[2] + m[4], attrs: parseAttrs(m[3]) }; + const attrs = parseAttrs(m[3]); + return { stripped: m[1] + m[2] + m[4], attrs: isEmptyAttrs(attrs) ? void 0 : attrs }; } -var TRIM_STRUCTURAL_RE = /^[^\S\u00a0]+|[^\S\u00a0]+$/g; function trimStructural(text) { - if (!text.includes("\xA0")) - return text.trim(); return text.replace(TRIM_STRUCTURAL_RE, ""); } -function isBlankLine(line) { - return line !== void 0 && trimStructural(line) === ""; -} -var RE_BLOCKQUOTE = /^>[^\S ]?(.*)$/; -var RE_ADMONITION_OPEN = /^(:{3,})\s*([a-zA-Z_][\w-]*)(?:\s+("[^"]*"))?(?:\s+(\[[^\]]*\]))?\s*$/; -var RE_ADMONITION_CLOSE = /^(:{3,})\s*$/; -var RE_LINE_BLOCK_OPEN = /^(:{3,})[ \t]+\|[ \t]*$/; -var RE_HARDBREAKS_OPEN = /^(:{3,})[ \t]+\\[ \t]*$/; -var RE_DIV_OPEN = /^(:{3,})\s*(\[[^\]]*\])?\s*$/; -var RE_DEFLIST_TERM = /^::(?!:)\s+(.+)$/; -var RE_DEFLIST_DEF = /^: {2,}(.+)$/; -var RE_ABBR_DEF = /^\*\[([A-Z][A-Z0-9]*)\]: \s*(.+)$/; -var RE_LINK_DEF = /^[^\S ]*\[(?!@)([^\]]+)\]: [^\S ]*(\S+)(?:\s+(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)'))?.*$/; -var RE_FOOTNOTE_DEF = /^\[\^([^\]]+)\]: \s*(.+)$/; -var RE_CAPTION = /^\^ +(.*[^ \t\n\r\f].*)$/; -var RE_TRAILING_WS = /[ \t\f\r]+$/; -var RE_TABLE_ROW = /^\|/; -var isTableRow = (line) => { - if (!RE_TABLE_ROW.test(line)) - return false; - if (!/\|[ \t]*$/.test(line) && rowAttrsFromLine(line).attrs === void 0) - return false; - const cells = splitTableRow(rowAttrsFromLine(line).body); - return cells.some((cell) => cell.length > 0) || cells.length >= 2; -}; -var RE_TABLE_CONT = /^\+.*\|\s*$/; -var RE_BARE_IMAGE = /^!\[([^\]]*)\]\(([^)\s]+)(?:\s+"([^"]*)"|\s+'([^']*)')?\)(?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?\s*$/; -var RE_FRONTMATTER_OPEN = /^---[ \t]*(\w*)\s*$/; -var RE_FRONTMATTER_CLOSE = /^---\s*$/; -var RE_RAW_FENCE = /^(`{3,}|~{3,})\s*=([a-zA-Z][\w-]*)\s*$/; -var RE_COMMENT_BLOCK = /^%{3,}\s*$/; -var RE_COMMENT_LINE = /^[ \t]*%%/; -var RE_FENCE_CLOSER = /^(`{3,}|~{3,})\s*$/; -var MAX_NESTING_DEPTH = 200; -var Lexer = class { - lines; - lineOffsets; - lineNumberOffset; - sourceLineMap; - suppressPositions = false; - pos = 0; - // Block-container nesting depth of this (sub-)lexer; 0 at the document top. - depth = 0; - frontmatter; - /** Format applied to a bare `---` fence; set from ParseOptions. */ - defaultFrontmatterFormat = "yaml"; - abbrDefs = /* @__PURE__ */ new Map(); - linkDefs = /* @__PURE__ */ new Map(); - // Footnote definitions keyed by raw label; value is the parsed note - // body (def line + indented continuation), set by parseFootnoteDef. - footnoteDefs = /* @__PURE__ */ new Map(); - // True for sub-lexers over already-nested block content (list item / - // blockquote / admonition bodies). Informational only: under the §10 - // Markdown-like rule a visible block interrupts a paragraph at EVERY level - // (top and nested) — startsInterruptingBlock no longer branches on this — - // but sub-lexers still set it to mark their context. - nested = false; - // Negative cache for divHasCloser: the smallest line index from which - // NO bare colon-fence closer of ANY length exists onward. Once a scan - // proves that, every later bare opener (pos only advances) is O(1), - // keeping pathological "many unclosed `:::`" input linear. - divNoCloserFrom = Infinity; - // Negative cache for divHasCloser keyed by fence length: fenceLen → smallest - // line index from which no bare closer of >= that length exists onward. Keeps - // "many `:::: word` openers + one too-short closer" input linear instead of - // O(n²) (the any-length cache above never trips when a too-short closer is - // present). pos only advances, so the stored start is a monotone frontier. - divNoCloserOfLenFrom = /* @__PURE__ */ new Map(); - // Negative cache for lineBlockHasCloser, mirroring divHasCloser for the - // `::: |` opener. Without it, many unclosed line-block openers rescan to EOF. - lineBlockNoCloserFrom = Infinity; - lineBlockNoCloserOfLenFrom = /* @__PURE__ */ new Map(); - // Negative cache for fenceHasCloser (paragraph-interruption closer - // lookahead): the smallest line index from which NO bare fence-closer - // line exists onward. Once proven, every later fence opener (pos only - // advances) short-circuits, keeping "many unclosed fences" input linear. - noFenceCloserFrom = Infinity; - constructor(source, opts = {}, lineNumberOffset = 0) { - this.lineNumberOffset = lineNumberOffset; - this.defaultFrontmatterFormat = opts.defaultFrontmatterFormat ?? "yaml"; - this.lines = source.replace(/\r\n?/g, "\n").split("\n"); - if (this.lines.length && this.lines[this.lines.length - 1] === "") { - this.lines.pop(); - } - this.lineOffsets = []; - let offset = 0; - for (const line of this.lines) { - this.lineOffsets.push(offset); - offset += line.length + 1; - } - } - consumeFrontmatter() { - if (this.lines.length < 2) - return; - const open = RE_FRONTMATTER_OPEN.exec(this.lines[0]); - if (!open) - return; - for (let i = 1; i < this.lines.length; i++) { - if (RE_FRONTMATTER_CLOSE.test(this.lines[i])) { - const content = this.lines.slice(1, i).join("\n"); - const format = open[1] !== "" ? open[1] : this.defaultFrontmatterFormat; - this.frontmatter = { format, content }; - this.pos = i + 1; - return; - } +function isBlankLine(line2) { + return line2 !== void 0 && RE_BLANK_LINE.test(line2); +} +function isContinuationMarker(line2) { + return RE_CONTINUATION_MARKER.test(line2); +} +function splitTrailingAttrBlock(line2) { + const end = line2.replace(/[ \t]+$/, ""); + if (!end.endsWith("}")) + return [line2, null]; + let quote = null; + let open = -1; + for (let i = 0; i < end.length; i++) { + const c = end[i]; + if (quote) { + if (c === "\\") + i++; + else if (c === quote) + quote = null; + continue; + } + if (c === '"' || c === "'") { + quote = c; + continue; + } + if (c === "{") { + if (open === -1) + open = i; + continue; + } + if (c === "}" && open !== -1 && i === end.length - 1) { + const pad = end[open - 1]; + const before = end[open - 2]; + if (pad !== " " || before === void 0 || before === " " || before === " ") { + return [line2, null]; + } + const inner = end.slice(open + 1, end.length - 1); + if (inlineAttrPayloadHasTab(inner)) + return [line2, null]; + if (!isValidInlineAttrPayload(inner) || isEmptyAttrs(parseAttrs(inner))) { + return [line2, null]; + } + return [end.slice(0, open - 1), inner]; } } - peek(offset = 0) { - return this.lines[this.pos + offset]; - } - consume() { - return this.lines[this.pos++]; - } - eof() { - return this.pos >= this.lines.length; - } - lineOffset(lineIndex) { - return this.lineOffsets[lineIndex] ?? 0; - } - lineNumber(lineIndex) { - return this.sourceLineMap?.[lineIndex] ?? this.lineNumberOffset + lineIndex + 1; - } -}; + return [line2, null]; +} +function isLinkDefLine(line2) { + return RE_LINK_DEF.test(splitTrailingAttrBlock(line2)[0]); +} +function dropTrailingWhitespace(text) { + return text.replace(/[ \t]+(?=\n|$)/g, ""); +} +function normalizeNewlines(source) { + return source.replace(/\r\n?/g, "\n"); +} function normalizedSourceLines(source) { - const lines = source.replace(/\r\n?/g, "\n").split("\n"); + if (layoutWork.on) + layoutWork.seam += source.length; + const lines = normalizeNewlines(source).split("\n"); if (lines.length && lines[lines.length - 1] === "") lines.pop(); return lines; } -function subLexer(source, opts, lineNumberOffset, sourceLineMap) { - const sub = new Lexer(source, opts, lineNumberOffset); +function subLexer(source, opts, lineNumberOffset, sourceLineMap, unclosedContainerKeys) { + const sub = new Lexer(source, opts, lineNumberOffset, unclosedContainerKeys); if (sourceLineMap) sub.sourceLineMap = sourceLineMap; return sub; } -function nestedSubLexer(parent, source, startLineIndex, sourceLineMap) { - const sub = subLexer(source, {}, parent.lineNumberOffset + startLineIndex, sourceLineMap ?? normalizedSourceLines(source).map((_line, i) => parent.lineNumber(startLineIndex + i))); +function nestedSubLexer(parent, lines, startLineIndex, sourceLineMap) { + const mapLength = lines.length; + const sub = subLexer(lines, parent.parseOptions, parent.lineNumberOffset + startLineIndex, sourceLineMap ?? Array.from({ length: mapLength }, (_l, i) => parent.lineNumber(startLineIndex + i)), parent.unclosedContainerKeys); sub.abbrDefs = parent.abbrDefs; sub.linkDefs = parent.linkDefs; + sub.literalLazyLinkDefLines = parent.literalLazyLinkDefLines; sub.footnoteDefs = parent.footnoteDefs; + sub.footnoteDefPos = parent.footnoteDefPos; sub.nested = true; sub.depth = parent.depth + 1; + sub.inFigureGroup = parent.inFigureGroup; + attachDocumentOffsets(sub, parent, startLineIndex); return sub; } +function attachDocumentOffsets(sub, parent, startLineIndex) { + if (!parent.hasDocumentOffsets) + return; + const offsets = []; + const widths = []; + let previousIndex = -1; + const parentIndicesOf = sub.sourceLineMap ? parentLineIndices(parent) : EMPTY_LINE_INDICES; + for (let i = 0; i < sub.lines.length; i++) { + const mapped = sub.sourceLineMap?.[i]; + const subLine = sub.lines[i]; + if (subLine === void 0) + return; + let literalSuffix; + const anchorsTo = (candidate) => { + const parentLine2 = parent.lines[candidate] ?? ""; + literalSuffix = parentLine2.endsWith(subLine); + return literalSuffix || parentLine2.endsWith(withoutSyntheticIndent(subLine)); + }; + const parentIndex = mapped === void 0 ? startLineIndex + i : (parentIndicesOf.get(mapped) ?? []).find((candidate) => candidate >= previousIndex && anchorsTo(candidate)); + if (parentIndex === void 0) + return declinePositions(sub); + if (i > 0 && parentIndex < previousIndex) + return declinePositions(sub); + previousIndex = parentIndex; + const parentLine = parent.lines[parentIndex]; + if (parentLine === void 0) + return; + let prefix = parentLine.length - subLine.length; + if (!(literalSuffix ?? parentLine.endsWith(subLine))) { + const trimmed = withoutSyntheticIndent(subLine); + const synthetic = subLine.length - trimmed.length; + if (synthetic === 0 || !parentLine.endsWith(trimmed)) + return declinePositions(sub); + prefix = parentLine.length - trimmed.length - synthetic; + } + const offset = parent.lineOffset(parentIndex) + prefix; + const width2 = parent.lineStartColumn(parentIndex) - 1 + prefix; + if (offset < 0) + return declinePositions(sub); + offsets.push(offset); + widths.push(width2); + } + sub.sourceOffsetMap = offsets; + sub.linePrefixWidths = widths; +} +function parentLineIndices(lexer) { + const cached = lexer.lineIndicesByNumber; + if (cached !== void 0) + return cached; + const built = /* @__PURE__ */ new Map(); + for (let i = 0; i < lexer.lines.length; i++) { + const number = lexer.lineNumber(i); + const bucket = built.get(number); + if (bucket) + bucket.push(i); + else + built.set(number, [i]); + } + lexer.lineIndicesByNumber = built; + return built; +} +function withoutSyntheticIndent(line2) { + return line2.replace(/^[ \t]+/, ""); +} +function declinePositions(sub) { + sub.suppressPositions = true; +} +function toCodepointPositions(doc, source) { + let hasAstral = false; + for (let i = 0; i < source.length; i++) { + const code = source.charCodeAt(i); + if (code >= 55296 && code <= 56319) { + hasAstral = true; + break; + } + } + if (!hasAstral) + return; + const codepointAt = new Uint32Array(source.length + 1); + let count = 0; + for (let i = 0; i < source.length; i++) { + codepointAt[i] = count; + const code = source.charCodeAt(i); + if (code >= 55296 && code <= 56319 && i + 1 < source.length) { + codepointAt[i + 1] = count; + i++; + } + count++; + } + codepointAt[source.length] = count; + const map = (offset) => codepointAt[Math.min(offset, source.length)] ?? count; + const lineStartCodepoint = [0]; + for (let i = 0; i < source.length; i++) { + if (source.charCodeAt(i) === 10) + lineStartCodepoint.push(map(i + 1)); + } + const convert = (pos) => { + const startOffset = pos.startOffset; + const endOffset = pos.endOffset; + if (typeof startOffset === "number") { + pos.startOffset = map(startOffset); + const lineStart = lineStartCodepoint[pos.startLine - 1]; + if (lineStart !== void 0 && pos.startColumn !== void 0) { + pos.startColumn = pos.startOffset - lineStart + 1; + } + } + if (typeof endOffset === "number") { + pos.endOffset = map(endOffset); + const lineStart = lineStartCodepoint[pos.endLine - 1]; + if (lineStart !== void 0 && pos.endColumn !== void 0) { + pos.endColumn = pos.endOffset - lineStart + 1; + } + } + }; + const seen = /* @__PURE__ */ new Set(); + const walk2 = (value) => { + if (!value || typeof value !== "object") + return; + if (seen.has(value)) + return; + seen.add(value); + if (Array.isArray(value)) { + for (const item2 of value) + walk2(item2); + return; + } + const record = value; + if (typeof record["startLine"] === "number" && typeof record["endLine"] === "number") { + convert(record); + return; + } + for (const key2 of Object.keys(record)) + walk2(record[key2]); + }; + walk2(doc); +} +function opensFrontmatter(source, opts = {}) { + if (!source.startsWith("---")) + return false; + const lexer = new Lexer(source, opts); + lexer.consumeFrontmatter(); + return lexer.frontmatter !== void 0; +} function parse(source, opts = {}) { newlineIndexCache.clear(); - if (source.charCodeAt(0) === 65279) + const previousQuoteCharacters = activeQuoteCharacters; + activeQuoteCharacters = opts.extensions?.map((extension) => extension.quoteCharacters).filter((quotes) => quotes !== void 0).at(-1) ?? previousQuoteCharacters; + const strippedBom = source.charCodeAt(0) === 65279; + if (strippedBom) source = source.slice(1); if (source.includes("\0")) source = source.replace(/\0/g, "\uFFFD"); - const lexer = new Lexer(source, opts); + const lexer = new Lexer(source, opts, 0, opts.onUnclosedContainer ? /* @__PURE__ */ new Set() : void 0); + if (strippedBom) { + lexer.sourceOffsetMap = lexer.lineOffsets.map((offset) => offset + 1); + lexer.linePrefixWidths = lexer.lineOffsets.map((_offset, index2) => index2 === 0 ? 1 : 0); + } + lexer.atDocumentLevel = true; lexer.consumeFrontmatter(); - collectAbbrDefs(lexer); - collectLinkDefs(lexer); const prevMatchers = activeMatchers; const prevCtx = activeMatcherCtx; + const prevDocument = activeDocument; + activeDocument = strippedBom ? "\uFEFF" + source : source; activeMatchers = (opts.extensions ?? []).filter((e) => e.matchInline || e.matchBlock); activeMatcherCtx = activeMatchers.length ? makeMatcherCtx(lexer, opts) : null; try { + collectLinkDefs(lexer); const children = parseBlocks(lexer, 0); + appendLinkReferenceDefinitions(children, lexer, source); const doc = { type: "document", children }; doc.srcByteLength = utf8ByteLength(source); if (lexer.frontmatter) doc.frontmatter = lexer.frontmatter; if (lexer.footnoteDefs.size) doc.footnoteDefs = Object.fromEntries(lexer.footnoteDefs); + if (lexer.footnoteDefPos.size) + doc.footnoteDefPos = Object.fromEntries(lexer.footnoteDefPos); + toCodepointPositions(doc, source); return doc; } finally { activeMatchers = prevMatchers; activeMatcherCtx = prevCtx; + activeDocument = prevDocument; + activeQuoteCharacters = previousQuoteCharacters; } } +function appendLinkReferenceDefinitions(children, lexer, source) { + const authored = []; + for (const [label, def] of lexer.linkDefs) { + if (def.line === void 0) + continue; + const node = { + type: "link_reference_definition", + label, + href: def.href + }; + if (def.title !== void 0) + node.title = def.title; + if (def.attrs) + node.attrs = def.attrs; + node.pos = wholeLinePos(lexer, def.line, source); + authored.push(node); + } + authored.sort((a, b) => (a.pos?.startOffset ?? 0) - (b.pos?.startOffset ?? 0)); + children.push(...authored); +} +function wholeLinePos(lexer, line2, source) { + const text = lexer.lines[line2] ?? ""; + let offset = 0; + for (let i = 0; i < line2; i++) + offset += (lexer.lines[i] ?? "").length + 1; + const startOffset = Math.min(offset, source.length); + return { + startLine: line2 + 1, + endLine: line2 + 1, + startColumn: 1, + endColumn: text.length + 1, + startOffset, + endOffset: Math.min(startOffset + text.length, source.length) + }; +} function makeMatcherCtx(lexer, opts) { return { parseInlines: (t) => parseInline(t, lexer.abbrDefs, lexer.linkDefs), @@ -9327,8 +9342,8 @@ function makeMatcherCtx(lexer, opts) { function parseBlockSource(source, opts, root) { const sourceLines2 = normalizedSourceLines(source); const anchor = root.pos + 1; - const sourceLineMap = sourceLines2.length > 0 && sourceLines2.every((line, i) => root.lines[anchor + i] === line) ? sourceLines2.map((_line, i) => root.lineNumber(anchor + i)) : void 0; - const sub = subLexer(source, opts, root.lineNumberOffset + anchor, sourceLineMap); + const sourceLineMap = sourceLines2.length > 0 && sourceLines2.every((line2, i) => root.lines[anchor + i] === line2) ? sourceLines2.map((_line, i) => root.lineNumber(anchor + i)) : void 0; + const sub = subLexer(source, opts, root.lineNumberOffset + anchor, sourceLineMap, root.unclosedContainerKeys); if (!sourceLineMap) sub.suppressPositions = true; sub.depth = root.depth + 1; @@ -9338,7 +9353,7 @@ function parseBlockSource(source, opts, root) { for (const [k, v] of root.abbrDefs) sub.abbrDefs.set(k, v); sub.footnoteDefs = root.footnoteDefs; - collectAbbrDefs(sub); + sub.footnoteDefPos = root.footnoteDefPos; collectLinkDefs(sub); if (!activeMatchers.length) return parseBlocks(sub, 0); @@ -9379,107 +9394,381 @@ function tryInlineMatchers(text, pos) { } return null; } -function collectAbbrDefs(lexer) { - for (let idx = 0; idx < lexer.lines.length; idx++) { - if (idx < lexer.pos) - continue; - const m = RE_ABBR_DEF.exec(lexer.lines[idx]); - if (m) - lexer.abbrDefs.set(m[1], m[2]); - } -} function normalizeRefLabel(label) { return label.trim().replace(/\s+/g, " "); } -function stripContainerPrefixesKeepIndent(raw) { - let line = raw; +function stripContainerPrefixesKeepIndent(raw, afterTerm = false) { + let line2 = raw; let prev; do { - prev = line; - line = line.replace(/^[^\S\u00a0]*>[^\S\u00a0]?/, "").replace(/^[^\S\u00a0]*(?:[-*]|\d+[.)])[^\S\u00a0]+(?:\[[ xX\-_>?]\][^\S\u00a0]+)?/, ""); - } while (line !== prev); - return line; + prev = line2; + line2 = line2.replace(/^[ \t]*>(?: |$)/, "").replace(/^[ \t]*(?:[-*]|\d+[.)])[ \t]+(?:\[[ xX\-_>?]\][ \t]+)?/, ""); + if (afterTerm) + line2 = line2.replace(RE_DESCRIPTION_PREFIX, ""); + } while (line2 !== prev); + return line2; +} +function stripContainerPrefixes(raw, afterTerm = false) { + return stripContainerPrefixesKeepIndent(raw, afterTerm).replace(/^[ \t]+/, ""); +} +function prepassMarker(text, re = RE_PREPASS_MARKER) { + const m = re.exec(text); + if (!m) + return null; + if (m[2] !== void 0 && !isValidInlineAttrPayload(m[2])) + return null; + return m; +} +function containerQuoteDepth(text) { + let rest = text; + let depth = 0; + for (; ; ) { + const run = RE_QUOTE_RUN.exec(rest); + if (run !== null) { + depth += (run[0].match(/>/g) ?? []).length; + rest = rest.slice(run[0].length); + continue; + } + const marker = prepassMarker(rest, RE_PREPASS_MARKER_STRIP); + if (marker === null) + return depth; + rest = rest.slice(marker[0].length); + } +} +function isColonFenceOpener(line2) { + return RE_DIV_OPEN.test(line2) || RE_ADMONITION_OPEN.test(line2) && !RE_ADMONITION_CLOSE.test(line2) || RE_LINE_BLOCK_OPEN.test(line2) || RE_HARDBREAKS_OPEN.test(line2); +} +function scopeHoldsLine(scope, raw, quoteDepth2, view) { + return quoteDepth2 >= scope.quoteDepth && (scope.contentCol === 0 || isBlankLine(raw) || // VISUAL COLUMNS, the way the parser measures reach: a tab is worth up to + // four. Counting characters read a tab-indented body line as column one + // against a column of three, ended the fence on it, and published the + // definitions in the sample below (raised by codex review). The cap keeps + // it O(the column) rather than O(the indentation run). + indentColumns(view, scope.contentCol) >= scope.contentCol); } -function stripContainerPrefixes(raw) { - return stripContainerPrefixesKeepIndent(raw).replace(/^[^\S\u00a0]+/, ""); +function prepassOpensBlock(line2) { + return line2 === "" || lineOpensBlock(line2) || RE_COMMENT_LINE.test(line2) || line2.startsWith("{") || isContinuationMarker(line2) || RE_TABLE_CONT.test(line2) || RE_ABBR_DEF.test(line2); +} +function composeContainerPrefix(raw, afterTerm, open) { + const peeled = []; + let pos = 0; + let depth = 0; + let handed = 0; + for (; ; ) { + const rest = raw.slice(pos); + const ind = leadingWhitespace(rest); + const col = pos + ind; + while (depth < open.length && !open[depth].quote && open[depth].col <= col) { + handed = open[depth].col; + depth++; + } + const after = rest.slice(ind); + if (after === "") + return { column: col, peeled, depth }; + if (after[0] === ">" && (after.length === 1 || after[1] === " ")) { + if (col !== handed) + return { column: col, peeled, depth }; + const content2 = col + (after.length === 1 ? 1 : 2); + const matched2 = depth < open.length && open[depth].quote && open[depth].col === content2; + if (matched2) + depth++; + peeled.push({ content: content2, quote: true, matched: matched2 }); + handed = content2; + pos = content2; + continue; + } + const desc = afterTerm ? /^:[ \t]+/.exec(after) : null; + const marker = desc ?? prepassMarker(after); + if (marker === null || !/\S/.test(after.slice(marker[0].length))) { + return { column: col, peeled, depth }; + } + const content = col + marker[0].length; + const matched = depth < open.length && !open[depth].quote && open[depth].col === content; + if (matched) + depth++; + peeled.push({ content, quote: false, matched }); + handed = content; + pos = content; + } } function collectLinkDefs(lexer) { let fence = null; + let verse = null; + let commentFence = null; + const commentScopeMemo = /* @__PURE__ */ new Map(); + const divs = []; const listCols = []; + const openCols = []; let prevBlank = true; let inFootnoteBody = false; + let plusColumn = null; + let paraState = "no"; + let paraLine = ""; + let attrRun = false; + const hasBlockMatchers = activeMatchers.some((e) => e.matchBlock); + let prepassClosers = null; for (let idx = 0; idx < lexer.lines.length; idx++) { if (idx < lexer.pos) continue; const raw = lexer.lines[idx]; - const line = stripContainerPrefixes(raw); + const afterTerm = RE_AFTER_TERM.test(stripContainerPrefixes(lexer.lines[idx - 1] ?? "")); + const line2 = stripContainerPrefixes(raw, afterTerm); + const unquoted = raw.replace(/^(?:>(?: |$))+/, ""); const wasPrevBlank = prevBlank; - prevBlank = raw.trim() === ""; - if (!fence) { - const marker = raw.match(/^([ \t]*)(?:[-*]|(?:[0-9]+|[ivxlcdm]+|[IVXLCDM]+|[a-z]|[A-Z])[.)])(?:\{[^}]*\})? +/); - const indent = raw.length - raw.replace(/^[ \t]+/, "").length; - const rawTrimmed = raw.trim(); - const startsBlock = /^#{1,6}([ \t]|$)/.test(rawTrimmed) || rawTrimmed.startsWith(">") || /^(`{3,}|~{3,})/.test(rawTrimmed) || /^(-{3,}|\*{3,}|_{3,})$/.test(rawTrimmed); - if (marker && /\S/.test(raw.slice(marker[0].length))) { - while (listCols.length && listCols[listCols.length - 1] > marker[1].length) - listCols.pop(); - listCols.push(marker[0].length); - } else if (raw.trim() !== "" && (wasPrevBlank || startsBlock)) { - while (listCols.length && listCols[listCols.length - 1] > indent) - listCols.pop(); - } - } - const contentCol = listCols.length ? listCols[listCols.length - 1] : 0; - const afterMarker = raw.replace(/^([ \t]*)(?:[-*]|(?:[0-9]+|[ivxlcdm]+|[IVXLCDM]+|[a-z]|[A-Z])[.)])(?:\{[^}]*\})? +(?:\[[ xX\-_>?]\] +)?/, ""); - const rawIsQuoted = /^(?:[^\S ]*>[^\S ]?)+/.test(raw) || /^(?:[^\S ]*>[^\S ]?)+/.test(afterMarker); + prevBlank = isBlankLine(raw); + const rawQuoteDepth = containerQuoteDepth(raw); + const rawIsQuoted = rawQuoteDepth > 0; if (fence) { - const k = fence.quoted ? raw.replace(/^(?:[^\S ]*>[^\S ]?)+/, "") : raw; + paraState = "no"; + const k = fence.quoted ? raw.replace(/^(?:[^\S ]*>(?: |$))+/, "") : raw; const ki = k.length - k.replace(/^[ \t]+/, "").length; const d = ki >= fence.contentCol ? k.slice(fence.contentCol) : k; - const close = d.match(/^([`~]{3,})\s*$/); - if (close && close[1][0] === fence.ch && close[1].length >= fence.len) + const close = d.match(RE_FENCE_CLOSER_PREPASS); + if (close && close[1][0] === fence.ch && close[1].length >= fence.len) { fence = null; + continue; + } + const divCloser = fence.divWidth !== null && !fence.hasCloser ? RE_ADMONITION_CLOSE.exec(d) : null; + const enclosingDivCloses = divCloser !== null && divCloser[1].length === fence.divWidth; + if (scopeHoldsLine(fence.scope, raw, rawQuoteDepth, unquoted) && !enclosingDivCloses) { + continue; + } + fence = null; + } + const marker = prepassMarker(unquoted); + const indent2 = unquoted.length - unquoted.replace(/^[ \t]+/, "").length; + const rawTrimmed = raw.trim(); + const startsBlock = /^#{1,6}([ \t]|$)/.test(rawTrimmed) || RE_BLOCKQUOTE.test(rawTrimmed) || /^(`{3,}|~{3,})/.test(rawTrimmed) || // A COLON FENCE ENDS THE ITEM TOO, and was the one block opener missing + // from this list. A flush `:::` under an unblanked item opens a SIBLING + // container - the parser renders the div next to the list, not inside it + // - so the item's content column is gone. Left here, the column stayed + // live and the div recorded it as the container it was opened in, which + // then released at the next blank line and let an abbreviation written + // INSIDE a visibly rendered div register (raised by codex review). + // + // Only a fence the parser REALLY opens: `:::note` is prose, and the + // parser folds it into the item lazily, so popping the column there + // rejected the definition below it as top-level indentation. + isColonFenceOpener(rawTrimmed) || /^(-{3,}|\*{3,}|_{3,})$/.test(rawTrimmed); + if (marker && /\S/.test(raw.slice(marker[0].length))) { + let rest = unquoted; + let base = 0; + for (let m2 = marker; m2 && /\S/.test(rest.slice(m2[0].length)); ) { + while (listCols.length && listCols[listCols.length - 1] > base + m2[1].length) { + listCols.pop(); + } + base += m2[0].length; + listCols.push(base); + rest = rest.slice(m2[0].length); + m2 = prepassMarker(rest); + } + } else if (RE_DEFLIST_DEF.test(unquoted)) { + while (listCols.length && listCols[listCols.length - 1] > indent2) + listCols.pop(); + listCols.push(indent2 + DEFLIST_CONTENT_COL); + } else if (!isBlankLine(raw) && // A LINK REFERENCE DEFINITION at column 0 ends the item too, so it has + // to pop the stack like any other block start. It is not in + // `startsBlock` because it is invisible, and being left out meant the + // stack still held the item's content column: the definition read as + // BELOW that column and was skipped, while the block lexer ended the + // list at it anyway. The line was rendered nowhere and defined nothing + // (carve-js#657) - the one outcome a definition may never have. + // + // At the content column this changes nothing: the `> indent` test pops + // only what sits DEEPER than the line, so a definition written at the + // column it belongs to still keeps its item open. + // + // The footnote form is already handled - its own prepass reads the line + // independently - and an ABBREVIATION definition deliberately does not + // qualify: all four implementations fold `- x` / `*[A]: b` as item text, + // because PART 12 §7 recognizes one only as a direct child of the + // document. + (wasPrevBlank || startsBlock || isLinkDefLine(rawTrimmed))) { + while (listCols.length && listCols[listCols.length - 1] > indent2) + listCols.pop(); + } + const composed = composeContainerPrefix(raw, afterTerm, openCols); + if (isBlankLine(raw)) { + const firstQuote = openCols.findIndex((e) => e.quote); + if (firstQuote >= 0) + openCols.length = firstQuote; + } else if (composed.peeled.length) { + openCols.length = composed.depth; + for (const one of composed.peeled) { + if (!one.matched) + openCols.push({ col: one.content, quote: one.quote }); + } + } else if (wasPrevBlank || startsBlock || isLinkDefLine(rawTrimmed)) { + while (openCols.length && openCols[openCols.length - 1].col > composed.column) { + openCols.pop(); + } + } + const contentCol = listCols.length ? listCols[listCols.length - 1] : 0; + if (commentFence !== null) { + const close = RE_COMMENT_BLOCK_ANY.exec(line2); + if (close && close[1].length === commentFence) + commentFence = null; + paraState = "no"; + continue; + } + { + const open2 = RE_COMMENT_BLOCK_ANY.exec(line2); + const commentScope = { + quoteDepth: rawQuoteDepth, + contentCol: plusColumn ?? contentCol + }; + const atDocumentLevel = commentScope.quoteDepth === 0 && commentScope.contentCol === 0; + const opensRegion = open2 !== null && (atDocumentLevel ? commentBlockHasCloser(lexer, open2[1].length, idx) : commentCloserInScope(lexer, open2[1].length, idx, commentScope, commentScopeMemo)); + if (open2 && opensRegion) { + commentFence = open2[1].length; + paraState = "no"; + continue; + } + } + if (verse !== null && !scopeHoldsLine(verse.scope, raw, rawQuoteDepth, unquoted)) { + verse = null; + } + if (verse !== null) { + const close = line2.trim().match(/^(:{3,})$/); + if (close && close[1].length >= verse.width) + verse = null; + paraState = "no"; + continue; + } + const verseOpen = line2.trim().match(/^(:{3,})[ \t]*\|$/); + if (verseOpen) { + verse = { + width: verseOpen[1].length, + scope: { quoteDepth: rawQuoteDepth, contentCol } + }; + paraState = "no"; continue; } - const kept = stripContainerPrefixesKeepIndent(raw); + while (divs.length && !scopeHoldsLine(divs[divs.length - 1].scope, raw, rawQuoteDepth, unquoted)) { + divs.pop(); + } + const colon = line2.trim().match(/^(:{3,})[ \t]*(.*)$/); + if (colon) { + const width2 = colon[1].length; + if (colon[2] === "" && divs.length && divs[divs.length - 1].width === width2) + divs.pop(); + else { + divs.push({ + width: width2, + opens: isColonFenceOpener(line2), + scope: { quoteDepth: rawQuoteDepth, contentCol } + }); + } + } + const paraWasOpen = paraState !== "no" && !(inFootnoteBody && !isBlankLine(raw) && leadingWhitespace(raw) === 0); + const paraAsk = paraState === "ask"; + const paraLineAbove = paraLine; + const inAttrRun = attrRun; + attrRun = !isBlankLine(raw) && !line2.includes("}") && (attrRun || line2.startsWith("{")); + paraState = isBlankLine(raw) || inAttrRun ? "no" : "ask"; + paraLine = line2; + const quoteIndent = leadingWhitespace(raw); + const quoteAtWrongColumn = quoteIndent > 0 && raw.slice(quoteIndent).startsWith(">") && !listCols.includes(quoteIndent); + if (quoteAtWrongColumn) + continue; + const kept = stripContainerPrefixesKeepIndent(raw, afterTerm); const keptIndent = kept.length - kept.replace(/^[ \t]+/, "").length; - const deIndented = keptIndent >= contentCol ? kept.slice(contentCol) : kept; + const openerCol = inFootnoteBody && contentCol === 0 ? keptIndent : contentCol; + const onDescriptionLine = afterTerm && RE_DESCRIPTION_PREFIX.test(unquoted); + const scopeCol = Math.max(openerCol, onDescriptionLine ? DEFLIST_CONTENT_COL : 0); + const deIndented = keptIndent >= openerCol ? kept.slice(openerCol) : kept; const open = RE_FENCE.exec(deIndented); - if (open) { - fence = { ch: open[2][0], len: open[2].length, contentCol, quoted: rawIsQuoted }; - continue; + const rawOpen = open ? null : RE_RAW_FENCE.exec(deIndented); + const run = open ? open[2] : rawOpen?.[1]; + if (run) { + let enclosingDiv; + for (let i = divs.length - 1; i >= 0; i--) { + if (divs[i].opens) { + enclosingDiv = divs[i]; + break; + } + } + if (!paraWasOpen || paraAsk && prepassOpensBlock(paraLineAbove) || hasBlockMatchers || codeCloserPossibleIn(prepassClosers ??= buildCodeCloserIndex(lexer.lines, RE_PREPASS_ANY_FENCE_CLOSER), run, idx)) { + fence = { + ch: run[0], + len: run.length, + contentCol: openerCol, + quoted: rawIsQuoted, + scope: { quoteDepth: rawQuoteDepth, contentCol: scopeCol }, + divWidth: enclosingDiv ? enclosingDiv.width : null, + // Asked only for a fence INSIDE a div, which is the one place the + // answer is read - so an ordinary document never builds the index. + // + // THE INDEX IS PERMISSIVE, and that is deliberate here. A merely + // closer-SHAPED line - indented, or inside another container - counts + // as "a closer may be ahead", so the div boundary declines to end the + // fence and a definition after it stays uncollected. That direction + // is a definition this pass does not reach, which is what it did + // before this change; the other direction ends a live fence early and + // publishes a definition out of a visible code sample. An exact + // answer wants a container-bounded scan per opener, which is the + // quadratic shape this index exists to avoid (raised by codex review, + // and unchanged from `origin/main` on the document it names). + hasCloser: enclosingDiv !== void 0 && codeCloserPossibleIn(prepassClosers ??= buildCodeCloserIndex(lexer.lines, RE_PREPASS_ANY_FENCE_CLOSER), run, idx) + }; + paraState = "no"; + continue; + } + paraState = "yes"; } if (RE_FOOTNOTE_DEF.test(raw)) inFootnoteBody = true; - else if (raw.trim() !== "" && leadingWhitespace(raw) === 0) + else if (!isBlankLine(raw) && leadingWhitespace(raw) === 0) inFootnoteBody = false; - if (RE_ABBR_DEF.test(line)) + const abbr = divs.length === 0 && listCols.length === 0 && !inFootnoteBody ? RE_ABBR_DEF.exec(raw) : null; + if (abbr) { + lexer.abbrDefs.set(abbr[1], abbr[2]); continue; - if (RE_FOOTNOTE_DEF.test(line)) + } + if (RE_FOOTNOTE_DEF.test(line2)) continue; const topLevelIndentedDef = contentCol === 0 && !inFootnoteBody && /^[ \t]/.test(deIndented); - const m = topLevelIndentedDef ? null : RE_LINK_DEF.exec(line); + const rawIndent = leadingWhitespace(unquoted); + if (isContinuationMarker(raw)) + plusColumn = leadingWhitespace(unquoted); + else if (isBlankLine(raw)) + plusColumn = null; + const openColumn = inFootnoteBody ? FOOTNOTE_BODY_COLUMN : contentCol; + const reached = (col) => composed.peeled.some((one) => one.content === col) || openCols.some((e, i) => i < composed.depth && e.col === col); + const anyReached = composed.peeled.length > 0 || composed.depth > 0; + const stoppedAtQuote = !composed.peeled.some((one) => one.quote) && composed.depth < openCols.length && openCols[composed.depth].quote; + const atAnOpenContentColumn = stoppedAtQuote ? false : plusColumn !== null ? rawIndent === plusColumn : anyReached ? reached(composed.column) : composed.column === openColumn; + const notAtContentColumn = !atAnOpenContentColumn; + const [defLine, defAttrText] = splitTrailingAttrBlock(line2); + const m = topLevelIndentedDef || notAtContentColumn ? null : RE_LINK_DEF.exec(defLine); if (m) { const def = { href: m[2] }; const title = m[3] ?? m[4]; if (title !== void 0) def.title = unescapeAttrValue(title); - lexer.linkDefs.set(normalizeRefLabel(m[1]), def); + if (defAttrText) { + const parsed = parseAttrs(defAttrText); + if (parsed.id !== void 0 || parsed.classes?.length || parsed.keyValues) { + def.attrs = parsed; + } + } + def.line = idx; + lexer.linkDefs.set(m[1], def); continue; } } } -function parseBlocks(lexer, baseIndent) { +function parseBlocks(lexer, baseIndent, carry) { const out = []; - let pending = null; + let pending = carry?.attrs ?? null; while (!lexer.eof()) { - const line = lexer.peek(); - if (isBlankLine(line)) { + const line2 = lexer.peek(); + if (isBlankLine(line2)) { lexer.consume(); continue; } - const indent = leadingWhitespace(line); - if (indent < baseIndent) + const indent2 = leadingWhitespace(line2); + if (indent2 < baseIndent) break; const ba = tryCollectBlockAttributes(lexer); if (ba) { @@ -9487,10 +9776,13 @@ function parseBlocks(lexer, baseIndent) { continue; } const node = parseBlock(lexer); + const invisible = node === null || node.type === "abbreviation_def" || node.type === "comment"; if (node) { - if (pending) { + if (pending && !invisible) { node.attrs = mergeAttrs(pending, node.attrs ?? {}); } + if (node.type === "table") + deriveTableColumns(node); const cb = node.type === "code_block" ? node : node.type === "figure" && node.target.type === "code_block" ? node.target : void 0; if (cb?.header !== void 0 && node.attrs?.keyValues?.title === void 0 && cb.attrs?.keyValues?.title === void 0) { cb.attrs = { @@ -9500,12 +9792,40 @@ function parseBlocks(lexer, baseIndent) { } out.push(node); } - pending = null; + if (!invisible) + pending = null; } + if (carry) + carry.attrs = pending; return out; } -function peekBlockAttributes(lexer) { - if (!/^\{/.test(lexer.peek())) +function deriveTableColumns(table) { + const kv = table.attrs?.keyValues; + if (!kv) + return; + const aligns = positional(kv.aligns, /* @__PURE__ */ new Set(["left", "right", "center"])); + const valigns = positional(kv.valigns, /* @__PURE__ */ new Set(["top", "middle", "bottom"])); + const widths = kv.widths?.split(",").map((raw) => { + const value = Number(raw.trim()); + return Number.isFinite(value) && value > 0 && value <= 100 ? value / 100 : void 0; + }) ?? []; + const count = Math.max(aligns.length, valigns.length, widths.length); + if (count === 0) + return; + table.columns = Array.from({ length: count }, (_, i) => ({ + ...aligns[i] ? { align: aligns[i] } : {}, + ...valigns[i] ? { valign: valigns[i] } : {}, + ...widths[i] ? { width: widths[i] } : {} + })); +} +function positional(value, allowed) { + return value?.split(",").map((raw) => { + const item2 = raw.trim(); + return allowed.has(item2) ? item2 : void 0; + }) ?? []; +} +function peekBlockAttributes(lexer, firstLine) { + if (!/^\{/.test(firstLine ?? lexer.peek())) return false; let collected = ""; let n = 0; @@ -9557,6 +9877,8 @@ function tryCollectBlockAttributes(lexer) { } function parseBlockAttributeRun(src) { let i = 0; + while (i < src.length && isCarveWhitespace(src[i])) + i++; let count = 0; let first = null; let id; @@ -9565,8 +9887,6 @@ function parseBlockAttributeRun(src) { const order = []; const orderSeen = /* @__PURE__ */ new Set(); while (i < src.length) { - while (i < src.length && /\s/.test(src[i])) - i++; if (i >= src.length) break; if (src[i] !== "{") @@ -9625,6 +9945,16 @@ function parseBlockAttributeRun(src) { } } i++; + if (i < src.length && isCarveWhitespace(src[i])) { + let end = i; + while (end < src.length && isCarveWhitespace(src[end])) + end++; + if (end === src.length) { + i = end; + break; + } + return null; + } } if (count === 0) return null; @@ -9649,58 +9979,63 @@ function parseBlock(lexer) { return node; } function parseBlockInner(lexer) { - const line = lexer.peek(); + const line2 = lexer.peek(); if (lexer.depth >= MAX_NESTING_DEPTH) - return parseParagraph(lexer); - if (RE_RAW_FENCE.test(line)) + return parseParagraph(lexer, true); + if (RE_RAW_FENCE.test(line2)) return parseRawBlock(lexer); - if (RE_FENCE.test(line)) + if (RE_FENCE.test(line2)) return parseFence(lexer); - if (RE_COMMENT_BLOCK.test(line)) + const commentFence = RE_COMMENT_BLOCK_ANY.exec(line2); + if (commentFence && commentBlockHasCloser(lexer, commentFence[1].length)) { return parseCommentBlock(lexer); - if (RE_COMMENT_LINE.test(line)) { + } + if (RE_COMMENT_LINE.test(line2)) { const l = lexer.consume(); - return { type: "comment", block: false, content: l.replace(/^[ \t]*%%/, "").replace(/^\s/, "") }; + return { type: "comment", block: false, content: l.replace(/^[ \t]*%%/, "").replace(/^[ \t]/, "") }; } - if (RE_LINE_BLOCK_OPEN.test(line) && lineBlockHasCloser(lexer)) + if (RE_LINE_BLOCK_OPEN.test(line2)) return parseLineBlock(lexer); - if (RE_HARDBREAKS_OPEN.test(line) && hardBreaksHasCloser(lexer)) + if (RE_HARDBREAKS_OPEN.test(line2)) return parseHardBreaksBlock(lexer); - if (RE_ADMONITION_OPEN.test(line) && !RE_ADMONITION_CLOSE.test(line) && divHasCloser(lexer)) + if (RE_ADMONITION_OPEN.test(line2) && !RE_ADMONITION_CLOSE.test(line2)) return parseAdmonition(lexer); - if (RE_DIV_OPEN.test(line) && divHasCloser(lexer)) + if (RE_DIV_OPEN.test(line2)) return parseDiv(lexer); - if (RE_ABBR_DEF.test(line)) { + if (lexer.atDocumentLevel && RE_ABBR_DEF.test(line2)) { return parseAbbrDef(lexer); } - if (RE_FOOTNOTE_DEF.test(line)) + if (RE_FOOTNOTE_DEF.test(line2)) return parseFootnoteDef(lexer); - if (leadingWhitespace(line) === 0 && RE_LINK_DEF.test(line)) { + if (leadingWhitespace(line2) === 0 && isLinkDefLine(line2) && !lexer.literalLazyLinkDefLines.has(lexer.lineNumber(lexer.pos))) { lexer.consume(); return null; } - if (RE_HR.test(line)) { + if (RE_HR.test(line2)) { lexer.consume(); - return { type: "thematic_break" }; + const node = { type: "thematic_break" }; + if (line2[0] === "*" || line2[0] === "_") + node.marker = line2[0]; + return node; } - if (RE_HEADING.test(line)) + if (RE_HEADING.test(line2)) return parseHeading(lexer); - if (RE_DEFLIST_TERM.test(line)) + if (RE_DEFLIST_TERM.test(line2)) return parseDefinitionList(lexer); - if (RE_BLOCKQUOTE.test(line)) + if (RE_BLOCKQUOTE.test(line2)) return parseBlockQuote(lexer); - if (RE_TASK.test(line) || RE_UNORDERED.test(line) || RE_ORDERED.test(line) || extractItemAttr(line) !== null) + if (RE_TASK.test(line2) || RE_UNORDERED.test(line2) || RE_ORDERED.test(line2) || extractItemAttr(line2) !== null) return parseList(lexer); - if (isTableRow(line)) + if (isTableRow(line2)) return parseTable(lexer); - if (isBlockImageLine(line) && imageIsBlock(lexer)) + if (isBlockImageLine(line2) && imageIsBlock(lexer)) return parseBlockImage(lexer); if (activeMatchers.length) { const matched = tryBlockMatchers(lexer); if (matched) return matched; } - if (line.trimStart().startsWith("$$`")) { + if (line2.trimStart().startsWith("$$`")) { const eq = parseEquationBlock(lexer); if (eq) return eq; @@ -9712,9 +10047,10 @@ function parseEquationBlock(lexer) { const raw = lexer.peek(); const firstLead = raw.match(/^[ \t]+/)?.[0].length ?? 0; const inline = parseInline(raw.replace(/^[ \t]+/, ""), lexer.abbrDefs, lexer.linkDefs, { + anchored: lexer.hasDocumentOffsets, baseOffset: lexer.lineOffset(lineIndex) + firstLead, startLine: lexer.lineNumber(lineIndex), - startColumn: 1 + firstLead + startColumn: lexer.lineStartColumn(lineIndex) + firstLead }); if (inline.length !== 1) return null; @@ -9731,10 +10067,11 @@ function parseEquationBlock(lexer) { if (cap && blanks2 <= 1) { for (let i = 0; i <= la; i++) lexer.consume(); + attachBlockPos(lexer, para, lineIndex, lineIndex + 1); return { type: "figure", target: para, - caption: parseInline(readCaptionText(lexer, cap[1]), lexer.abbrDefs, lexer.linkDefs, void 0, true) + caption: parseCaptionInline(lexer, cap[1]) }; } if (after !== void 0 && blanks2 === 0) @@ -9750,63 +10087,61 @@ function attachBlockPos(lexer, node, startLineIndex, endLineIndexExclusive) { node.pos = { startLine: lexer.lineNumber(startLineIndex), endLine: lexer.lineNumber(endLineIndex), - startColumn: 1, - endColumn: endLine.length + 1, + startColumn: lexer.lineStartColumn(startLineIndex), + endColumn: lexer.lineStartColumn(endLineIndex) + endLine.length, startOffset: lexer.lineOffset(startLineIndex), endOffset: lexer.lineOffset(endLineIndex) + endLine.length }; + if (node.type === "paragraph") { + const children = node.children; + const allPlaced = children?.every((child) => child.pos !== void 0) ?? false; + const first = allPlaced ? children?.[0]?.pos : void 0; + const last = allPlaced ? children?.[children.length - 1]?.pos : void 0; + if (first) { + node.pos.startLine = first.startLine; + if (first.startColumn !== void 0) + node.pos.startColumn = first.startColumn; + if (first.startOffset !== void 0) + node.pos.startOffset = first.startOffset; + } + if (last) { + node.pos.endLine = last.endLine; + if (last.endColumn !== void 0) + node.pos.endColumn = last.endColumn; + if (last.endOffset !== void 0) + node.pos.endOffset = last.endOffset; + } + } } function parseHeading(lexer) { const lineIndex = lexer.pos; - const line = lexer.consume(); - const m = RE_HEADING.exec(line); + const line2 = lexer.consume(); + const m = RE_HEADING.exec(line2); const level = m[1].length; - let text = line.replace(/^#{1,6} +/, ""); - const sameLevel = new RegExp(`^#{${level}} +(.+)$`); - const sameLevelBare = new RegExp(`^#{${level}}[ ]*$`); - while (!lexer.eof()) { - const next = lexer.peek(); - if (isBlankLine(next)) - break; - const cont = sameLevel.exec(next); - if (cont) { - text += "\n" + cont[1]; - lexer.consume(); - continue; - } - if (sameLevelBare.test(next)) { - lexer.consume(); - continue; - } - if (/^#{1,6}( |$)/.test(next) || RE_CAPTION.test(next) || RE_COMMENT_BLOCK.test(next)) { - break; - } - if (endsHeadingOrQuote(lexer)) - break; - text += "\n" + next; - lexer.consume(); - } + let text = line2.replace(/^#{1,6} +/, ""); text = text.replace(RE_TRAILING_WS, ""); const node = { type: "heading", level, children: [] }; - const textColumn = line.length - line.replace(/^#{1,6} +/, "").length + 1; + const textColumn = line2.length - line2.replace(/^#{1,6} +/, "").length + 1; node.children = parseInline(text, lexer.abbrDefs, lexer.linkDefs, { + anchored: lexer.hasDocumentOffsets, baseOffset: lexer.lineOffset(lineIndex) + textColumn - 1, startLine: lexer.lineNumber(lineIndex), - startColumn: textColumn + startColumn: lexer.lineStartColumn(lineIndex) + textColumn - 1 }); return node; } function parseFence(lexer) { + const fenceStartIndex = lexer.pos; const open = lexer.consume(); const m = RE_FENCE.exec(open); - const indent = m[1].length; + const indent2 = m[1].length; const marker = m[2]; const lang = m[3] || void 0; const headerRaw = m[4] ?? m[6]; const labelRaw = m[5] ?? m[7] ?? m[8]; const header = headerRaw ? headerRaw.slice(1, -1) : void 0; const label = labelRaw ? labelRaw.slice(1, -1) : void 0; - const closeRe = new RegExp(`^${marker[0]}{${marker.length},}\\s*$`); + const closeRe = fenceCloseRe(marker); const lines = []; while (!lexer.eof()) { const ln = lexer.peek(); @@ -9815,8 +10150,9 @@ function parseFence(lexer) { break; } lexer.consume(); - lines.push(ln.slice(Math.min(indent, leadingWhitespace(ln)))); + lines.push(ln.slice(Math.min(indent2, leadingWhitespace(ln)))); } + const fenceEndIndex = lexer.pos; const cb = { type: "code_block", content: lines.join("\n") }; if (lang) cb.lang = lang; @@ -9833,10 +10169,11 @@ function parseFence(lexer) { if (cap && lookahead <= 1) { for (let i = 0; i <= lookahead; i++) lexer.consume(); + attachBlockPos(lexer, cb, fenceStartIndex, fenceEndIndex); return { type: "figure", target: cb, - caption: parseInline(readCaptionText(lexer, cap[1]), lexer.abbrDefs, lexer.linkDefs, void 0, true) + caption: parseCaptionInline(lexer, cap[1]) }; } } @@ -9846,7 +10183,7 @@ function parseRawBlock(lexer) { const m = RE_RAW_FENCE.exec(lexer.consume()); const marker = m[1]; const format = m[2]; - const closeRe = new RegExp(`^${marker[0]}{${marker.length},}\\s*$`); + const closeRe = fenceCloseRe(marker); const lines = []; while (!lexer.eof()) { const ln = lexer.peek(); @@ -9859,29 +10196,247 @@ function parseRawBlock(lexer) { } return { type: "raw_block", format, content: lines.join("\n") }; } +function buildCodeCloserIndex(lines, re) { + const codeLast = /* @__PURE__ */ new Map(); + for (let i = 0; i < lines.length; i++) { + const f = re.exec(lines[i]); + if (f) { + const run = f[1]; + let byRun = codeLast.get(run[0]); + if (byRun === void 0) { + byRun = /* @__PURE__ */ new Map(); + codeLast.set(run[0], byRun); + } + byRun.set(run.length, i); + } + } + const code = /* @__PURE__ */ new Map(); + for (const [char, byRun] of codeLast) { + const runs = [...byRun.keys()].sort((a, b) => a - b); + const lastAtLeast = new Array(runs.length); + let best = -1; + for (let i = runs.length - 1; i >= 0; i--) { + best = Math.max(best, byRun.get(runs[i])); + lastAtLeast[i] = best; + } + code.set(char, { runs, lastAtLeast }); + } + return code; +} +function buildCloserIndex(lines) { + const comment = /* @__PURE__ */ new Map(); + const colon = /* @__PURE__ */ new Map(); + for (let i = 0; i < lines.length; i++) { + const line2 = lines[i]; + const c = RE_COMMENT_BLOCK_ANY.exec(line2); + if (c) + comment.set(c[1].length, i); + const d = RE_ANY_COLON_CLOSER.exec(line2); + if (d) + colon.set(d[1].length, i); + } + return { comment, colon, code: buildCodeCloserIndex(lines, RE_ANY_FENCE_CLOSER) }; +} +function closerIndex(lexer) { + lexer.fenceCloserIndex ??= buildCloserIndex(lexer.lines); + return lexer.fenceCloserIndex; +} +function codeCloserPossible(index2, marker, after) { + return codeCloserPossibleIn(index2.code, marker, after); +} +function codeCloserPossibleIn(code, marker, after) { + const entry = code.get(marker[0]); + if (entry === void 0) + return false; + let lo = 0; + let hi = entry.runs.length; + while (lo < hi) { + const mid = lo + hi >> 1; + if (entry.runs[mid] < marker.length) + lo = mid + 1; + else + hi = mid; + } + return lo < entry.runs.length && entry.lastAtLeast[lo] > after; +} +function exactCloserPossible(last, len, after) { + const at = last.get(len); + return at !== void 0 && at > after; +} +function commentBlockHasCloser(lexer, fence, after = lexer.pos) { + return exactCloserPossible(closerIndex(lexer).comment, fence, after); +} +function commentCloserInScope(lexer, fence, from, scope, memo) { + const at = commentRunLines(lexer).get(fence); + if (at === void 0) + return false; + let lo = 0; + let hi = at.length; + while (lo < hi) { + const mid = lo + hi >> 1; + if (at[mid].line <= from) + lo = mid + 1; + else + hi = mid; + } + if (lo >= at.length) + return false; + const end = commentScopeEnd(lexer, from, scope, memo); + for (let i = lo; i < at.length && at[i].line < end; i++) { + if (at[i].depth === scope.quoteDepth) + return true; + } + return false; +} +function commentRunLines(lexer) { + if (lexer.commentRunLines !== void 0) + return lexer.commentRunLines; + const m = /* @__PURE__ */ new Map(); + for (let i = 0; i < lexer.lines.length; i++) { + const raw = lexer.lines[i]; + const afterTerm = RE_AFTER_TERM.test(stripContainerPrefixes(lexer.lines[i - 1] ?? "")); + const c = RE_COMMENT_BLOCK_ANY.exec(stripContainerPrefixes(raw, afterTerm)); + if (c === null) + continue; + const entry = { + line: i, + // THE OPENER AND THE CLOSER ARE MEASURED THE SAME WAY, which is the whole + // point of naming this once: `- - > %%%` measured its own depth as 0 here + // while its closer ` > %%%` measured 1, so no run at the opener's depth + // existed and the region never opened (carve-js#1181). + depth: containerQuoteDepth(raw) + }; + const at = m.get(c[1].length); + if (at !== void 0) + at.push(entry); + else + m.set(c[1].length, [entry]); + } + lexer.commentRunLines = m; + return m; +} +function commentScopeEnd(lexer, from, scope, memo) { + const key2 = `${scope.quoteDepth}|${scope.contentCol}`; + const e = memo.get(key2); + if (e !== void 0 && from >= e.from && from < e.end) + return e.end; + let end = lexer.lines.length; + for (let i = from + 1; i < lexer.lines.length; i++) { + const raw = lexer.lines[i]; + if (isBlankLine(raw) || !isBlankLine(lexer.lines[i - 1] ?? "")) + continue; + if (isContinuationMarker(raw)) + continue; + if (scope.quoteDepth > 0) { + end = i; + break; + } + const depth = containerQuoteDepth(raw); + const view = raw.replace(/^(?:>(?: |$))+/, ""); + if (depth < scope.quoteDepth || // VISUAL COLUMNS, the way the parser measures reach: a tab is worth up to + // four. The cap keeps it O(the column) rather than O(the indentation run). + scope.contentCol > 0 && indentColumns(view, scope.contentCol) < scope.contentCol) { + end = i; + break; + } + } + memo.set(key2, { from, end }); + return end; +} +function quotedCommentHasCloser(lexer, fence, fromIndex) { + for (let i = fromIndex + 1; i < lexer.lines.length; i++) { + const quoted = RE_BLOCKQUOTE.exec(lexer.lines[i]); + if (!quoted) + return false; + const run = RE_COMMENT_BLOCK_ANY.exec(quoted[1] ?? ""); + if (run && run[1].length === fence) + return true; + } + return false; +} +function itemFenceHasCloser(lexer, marker, fromIndex, contentCol, memo) { + const char = marker[0]; + const start = fromIndex + 1; + if (fenceCloserMemoRefutes(memo, char, marker.length, start)) + return false; + const closeRe = fenceCloseRe(marker); + let maxRun = 0; + for (let i = start; i < lexer.lines.length; i++) { + const line2 = lexer.lines[i]; + if (isBlankLine(line2)) + continue; + if (indentColumns(line2, contentCol) < contentCol) + continue; + const dedented = sliceColumns(line2, contentCol, true); + if (closeRe.test(dedented)) + return true; + const closer = RE_FENCE_CLOSER.exec(dedented); + if (closer && closer[1][0] === char) + maxRun = Math.max(maxRun, closer[1].length); + } + memo.set(char, { from: start, maxRun }); + return false; +} +function fenceCloserMemoRefutes(memo, char, len, start) { + const cached = memo.get(char); + return cached !== void 0 && start >= cached.from && len > cached.maxRun; +} +function quotedFenceHasCloser(lexer, marker, fromIndex, memo) { + const char = marker[0]; + const start = fromIndex + 1; + if (fenceCloserMemoRefutes(memo, char, marker.length, start)) + return false; + const closeRe = fenceCloseRe(marker); + let maxRun = 0; + for (let i = start; i < lexer.lines.length; i++) { + const quoted = RE_BLOCKQUOTE.exec(lexer.lines[i]); + if (!quoted) + break; + const content = quoted[1] ?? ""; + if (closeRe.test(content)) + return true; + const closer = RE_FENCE_CLOSER.exec(content); + if (closer && closer[1][0] === char) + maxRun = Math.max(maxRun, closer[1].length); + } + memo.set(char, { from: start, maxRun }); + return false; +} function parseCommentBlock(lexer) { - const open = lexer.consume().trim(); + const openerLine = lexer.consume(); + const m = RE_COMMENT_BLOCK_ANY.exec(openerLine); + const fence = m[1].length; + const openerIndent = /^[ \t]*/.exec(openerLine)[0].length; + const dedent = (line2) => { + let cut = 0; + while (cut < openerIndent && (line2[cut] === " " || line2[cut] === " ")) + cut++; + return line2.slice(cut); + }; const lines = []; + const openerTail = trimNonNbsp(m[2]); + if (openerTail !== "") + lines.push(openerTail); while (!lexer.eof()) { const ln = lexer.peek(); - if (ln.trim() === open) { + const c = RE_COMMENT_BLOCK_ANY.exec(ln); + if (c && c[1].length === fence) { lexer.consume(); break; } lexer.consume(); - lines.push(ln); + lines.push(dedent(ln)); } return { type: "comment", block: true, content: lines.join("\n") }; } function parseFootnoteDef(lexer) { const defLineIndex = lexer.pos; const m = RE_FOOTNOTE_DEF.exec(lexer.consume()); - const label = m[1].trim(); + const label = m[1]; const bodyLines = [m[2]]; const bodyLineNumbers = [lexer.lineNumber(defLineIndex)]; let pendingBlanks = 0; let pendingBlankLineNumbers = []; - let contentCol = -1; while (!lexer.eof()) { const ln = lexer.peek(); if (isBlankLine(ln)) { @@ -9895,16 +10450,7 @@ function parseFootnoteDef(lexer) { lexer.consume(); pendingBlanks = 0; pendingBlankLineNumbers = []; - const attached = []; - const attachedLineNumbers = []; - while (!lexer.eof()) { - const a = lexer.peek(); - if (isBlankLine(a) || /^\+[ \t]*$/.test(a) || RE_FOOTNOTE_DEF.test(a)) - break; - attachedLineNumbers.push(lexer.lineNumber(lexer.pos)); - lexer.consume(); - attached.push(a); - } + const { lines: attached, lineNumbers: attachedLineNumbers } = collectAttachedBlock(lexer, (a) => isBlankLine(a) || /^\+[ \t]*$/.test(a) || RE_FOOTNOTE_DEF.test(a)); if (attached.length > 0) { bodyLines.push(""); bodyLineNumbers.push(plusLineNumber); @@ -9914,17 +10460,14 @@ function parseFootnoteDef(lexer) { } continue; } - const ws = leadingWhitespace(ln); - if (ws >= 2) { - if (contentCol === -1) - contentCol = ws; + if (indentColumns(ln, FOOTNOTE_BODY_COLUMN) >= FOOTNOTE_BODY_COLUMN) { for (let k = 0; k < pendingBlanks; k++) { bodyLines.push(""); bodyLineNumbers.push(pendingBlankLineNumbers[k]); } pendingBlanks = 0; pendingBlankLineNumbers = []; - bodyLines.push(ln.slice(Math.min(contentCol, ws))); + bodyLines.push(sliceColumns(ln, FOOTNOTE_BODY_COLUMN)); bodyLineNumbers.push(lexer.lineNumber(lexer.pos)); lexer.consume(); } else { @@ -9932,8 +10475,20 @@ function parseFootnoteDef(lexer) { } } if (!lexer.footnoteDefs.has(label)) { - const sub = nestedSubLexer(lexer, bodyLines.join("\n"), defLineIndex, bodyLineNumbers); + const sub = nestedSubLexer(lexer, bodyLines, defLineIndex, bodyLineNumbers); lexer.footnoteDefs.set(label, parseBlocks(sub, 0)); + if (lexer.hasDocumentOffsets) { + const lastIndex = Math.max(defLineIndex, lexer.pos - 1); + const lastLine = lexer.lines[lastIndex] ?? ""; + lexer.footnoteDefPos.set(label, { + startLine: lexer.lineNumber(defLineIndex), + endLine: lexer.lineNumber(lastIndex), + startColumn: lexer.lineStartColumn(defLineIndex), + endColumn: lexer.lineStartColumn(lastIndex) + lastLine.length, + startOffset: lexer.lineOffset(defLineIndex), + endOffset: lexer.lineOffset(lastIndex) + lastLine.length + }); + } } return null; } @@ -9942,68 +10497,202 @@ function parseAdmonition(lexer) { const open = lexer.consume(); const m = RE_ADMONITION_OPEN.exec(open); const fence = m[1].length; - const kind = m[2]; + const kind2 = m[2]; + const isFigureGroup = kind2 === "figure" && m[3] === void 0 && m[4] === void 0 && !lexer.inFigureGroup; const titleText = m[3] !== void 0 ? m[3].slice(1, -1) : void 0; const label = m[4] !== void 0 ? m[4].slice(1, -1) : void 0; - const inner = []; - while (!lexer.eof()) { - const ln = lexer.peek(); - const c = RE_ADMONITION_CLOSE.exec(ln); - if (c && c[1].length >= fence) { - lexer.consume(); - break; + const inner = collectColonFenceBody(lexer, { + kind: "admonition", + lineIndex: openLineIndex, + fenceWidth: fence + }); + const subLexer2 = nestedSubLexer(lexer, inner.map((line2) => line2.text), openLineIndex + 1); + if (isFigureGroup) + subLexer2.inFigureGroup = true; + const children = parseBlocks(subLexer2, 0); + if (isFigureGroup) { + const group = { type: "figure_group", children }; + let lookahead = 0; + while (!lexer.eof() && isBlankLine(lexer.peek(lookahead))) + lookahead++; + const next = lexer.peek(lookahead); + if (next) { + const cap = RE_CAPTION.exec(next); + if (cap && lookahead <= 1) { + for (let i = 0; i <= lookahead; i++) + lexer.consume(); + group.caption = parseCaptionInline(lexer, cap[1]); + } } - lexer.consume(); - inner.push(ln); + return group; } - const subLexer2 = nestedSubLexer(lexer, inner.join("\n"), openLineIndex + 1); - const children = parseBlocks(subLexer2, 0); - const node = { type: "admonition", kind, children }; + const node = { type: "admonition", kind: kind2, children }; if (titleText !== void 0) { - node.title = parseInline(titleText, lexer.abbrDefs, lexer.linkDefs); + const titleStart = open.indexOf(m[3]) + 1; + node.title = parseInline(titleText, lexer.abbrDefs, lexer.linkDefs, { + anchored: lexer.hasDocumentOffsets && titleStart > 0, + baseOffset: lexer.lineOffset(openLineIndex) + titleStart, + startLine: lexer.lineNumber(openLineIndex), + startColumn: lexer.lineStartColumn(openLineIndex) + titleStart + }); } if (label !== void 0) { node.label = label; } return node; } -function lineBlockHasCloser(lexer) { - const start = lexer.pos + 1; - if (start >= lexer.lineBlockNoCloserFrom) - return false; - const fence = RE_LINE_BLOCK_OPEN.exec(lexer.peek())[1].length; - if (start >= (lexer.lineBlockNoCloserOfLenFrom.get(fence) ?? Infinity)) - return false; - let sawAnyCloser = false; - for (let i = start; i < lexer.lines.length; i++) { - const c = RE_ADMONITION_CLOSE.exec(lexer.lines[i]); - if (c) { - sawAnyCloser = true; - if (c[1].length >= fence) - return true; +function stripPositions(nodes) { + const walk2 = (value) => { + if (!value || typeof value !== "object") + return; + if (Array.isArray(value)) { + for (const item2 of value) + walk2(item2); + return; + } + const record = value; + delete record["pos"]; + for (const key2 of Object.keys(record)) + walk2(record[key2]); + }; + walk2(nodes); + return nodes; +} +function unclosedContainerFromOpener(lexer, opener) { + const startOffset = lexer.lineOffset(opener.lineIndex); + return { + kind: opener.kind, + line: lexer.lineNumber(opener.lineIndex), + column: lexer.lineStartColumn(opener.lineIndex), + startOffset, + endOffset: startOffset + opener.fenceWidth, + fenceWidth: opener.fenceWidth + }; +} +function colonFenceOpenerLen(line2) { + const m = RE_DIV_OPEN.exec(line2) ?? (RE_ADMONITION_CLOSE.test(line2) ? null : RE_ADMONITION_OPEN.exec(line2)) ?? RE_LINE_BLOCK_OPEN.exec(line2) ?? RE_HARDBREAKS_OPEN.exec(line2); + return m ? m[1].length : null; +} +function colonFenceKind(line2) { + if (RE_LINE_BLOCK_OPEN.test(line2)) + return "line block"; + if (RE_HARDBREAKS_OPEN.test(line2)) + return "hard-break block"; + if (RE_ADMONITION_OPEN.test(line2)) + return "admonition"; + return "div"; +} +function consumeOpaqueColonFenceBodySpan(lexer, lines, lineIndex, text) { + const rawOpen = RE_RAW_FENCE.exec(text); + const codeOpen = rawOpen === null ? RE_FENCE.exec(text) : null; + const marker = rawOpen?.[1] ?? codeOpen?.[2]; + if (marker !== void 0) { + if (!startsInterruptingBlock(lexer)) + return false; + const closeRe = fenceCloseRe(marker); + const isCodeFence = codeOpen !== null; + lexer.consume(); + lines.push({ text, lineIndex }); + while (!lexer.eof()) { + const innerLineIndex = lexer.pos; + const innerText = lexer.peek(); + lexer.consume(); + lines.push({ text: innerText, lineIndex: innerLineIndex }); + if (closeRe.test(innerText) && (!isCodeFence || leadingWhitespace(innerText) <= 3)) + break; } + return true; + } + const commentOpen = RE_COMMENT_BLOCK.exec(text); + if (commentOpen !== null && commentBlockHasCloser(lexer, commentOpen[1].length)) { + const fence = commentOpen[1].length; + lexer.consume(); + lines.push({ text, lineIndex }); + while (!lexer.eof()) { + const innerLineIndex = lexer.pos; + const innerText = lexer.peek(); + const commentClose = RE_COMMENT_BLOCK.exec(innerText); + lexer.consume(); + lines.push({ text: innerText, lineIndex: innerLineIndex }); + if (commentClose !== null && commentClose[1].length === fence) + break; + } + return true; } - const prev = lexer.lineBlockNoCloserOfLenFrom.get(fence) ?? Infinity; - if (start < prev) - lexer.lineBlockNoCloserOfLenFrom.set(fence, start); - if (!sawAnyCloser) - lexer.lineBlockNoCloserFrom = start; return false; } +function collectColonFenceBody(lexer, opener) { + const lines = []; + const stack = [opener]; + let paragraphOpen = false; + while (!lexer.eof()) { + const lineIndex = lexer.pos; + const text = lexer.peek(); + const interruptsParagraph = paragraphOpen && startsInterruptingBlock(lexer); + if (consumeOpaqueColonFenceBodySpan(lexer, lines, lineIndex, text)) { + paragraphOpen = false; + continue; + } + const close = RE_ADMONITION_CLOSE.exec(text); + if (close && close[1].length === stack[stack.length - 1]?.fenceWidth) { + lexer.consume(); + stack.pop(); + if (stack.length === 0) + break; + lines.push({ text, lineIndex }); + paragraphOpen = false; + continue; + } + lexer.consume(); + lines.push({ text, lineIndex }); + const openerLen = colonFenceOpenerLen(text); + if (openerLen !== null) { + stack.push({ + kind: colonFenceKind(text), + lineIndex, + fenceWidth: openerLen + }); + paragraphOpen = false; + continue; + } + paragraphOpen = !isBlankLine(text) && !interruptsParagraph && (paragraphOpen || !lineOpensBlock(text)); + } + for (const unclosed of stack) { + lexer.reportUnclosedContainer(unclosedContainerFromOpener(lexer, unclosed)); + } + return lines; +} +function collectLiteralColonFenceBody(lexer, opener) { + const lines = []; + let closed = false; + while (!lexer.eof()) { + const lineIndex = lexer.pos; + const text = lexer.peek(); + const close = RE_ADMONITION_CLOSE.exec(text); + lexer.consume(); + if (close && close[1].length === opener.fenceWidth) { + closed = true; + break; + } + lines.push({ text, lineIndex }); + } + if (!closed) { + lexer.reportUnclosedContainer(unclosedContainerFromOpener(lexer, opener)); + } + return lines; +} function parseLineBlock(lexer) { + const openLineIndex = lexer.pos; const open = lexer.consume(); const m = RE_LINE_BLOCK_OPEN.exec(open); const fence = m[1].length; const stanzas = []; let stanza = []; - while (!lexer.eof()) { - const ln = lexer.peek(); - const c = RE_ADMONITION_CLOSE.exec(ln); - if (c && c[1].length >= fence) { - lexer.consume(); - break; - } - lexer.consume(); + for (const { text: ln, lineIndex } of collectLiteralColonFenceBody(lexer, { + kind: "line block", + lineIndex: openLineIndex, + fenceWidth: fence + })) { if (isBlankLine(ln)) { if (stanza.length) { stanzas.push(stanza); @@ -10011,79 +10700,229 @@ function parseLineBlock(lexer) { } continue; } - stanza.push(expandLineBlockLeadingWhitespace(ln)); + if (ln.startsWith("%%")) { + const comment = { + type: "comment", + block: false, + content: ln.slice(2).replace(/^[ \t]/, "") + }; + if (lexer.hasDocumentOffsets) { + comment.pos = { + startLine: lexer.lineNumber(lineIndex), + endLine: lexer.lineNumber(lineIndex), + startColumn: lexer.lineStartColumn(lineIndex), + endColumn: lexer.lineStartColumn(lineIndex) + ln.length, + startOffset: lexer.lineOffset(lineIndex), + endOffset: lexer.lineOffset(lineIndex) + ln.length + }; + } + stanza.push({ text: "", lineIndex, aligned: true, comment }); + continue; + } + const expanded = expandLineBlockWhitespace(ln); + stanza.push({ + text: dropTrailingSpaces(expanded), + lineIndex, + aligned: expanded.length === ln.length + }); } if (stanza.length) stanzas.push(stanza); - const children = stanzas.map((lines) => ({ - type: "paragraph", - children: parseInline(lines.join("\n"), lexer.abbrDefs, lexer.linkDefs).map((node2) => node2.type === "soft_break" ? { type: "hard_break" } : node2) - })); + const children = stanzas.map((lines) => { + const anchorable = lexer.hasDocumentOffsets && lines.every((l) => l.aligned); + const joined = lines.map((line2) => line2.text).join("\n"); + const firstLineNumber = lexer.lineNumber(lines[0].lineIndex); + const breakPos = (index2) => { + if (!lexer.hasDocumentOffsets) + return void 0; + const line2 = lines[index2]; + const next = lines[index2 + 1]; + if (!next) + return void 0; + const lineOffset = lexer.lineOffset(line2.lineIndex); + const sourceLineEnd = lineOffset + (lexer.lines[line2.lineIndex]?.length ?? 0); + return { + startLine: lexer.lineNumber(line2.lineIndex), + endLine: lexer.lineNumber(next.lineIndex), + startColumn: lexer.lineStartColumn(line2.lineIndex) + (lexer.lines[line2.lineIndex]?.length ?? 0), + endColumn: lexer.lineStartColumn(next.lineIndex), + // A COMMENT LINE IS MEASURED FROM ITS SOURCE, not from the empty text + // the block layer left behind. The clamp above reads the parsed text's + // length, which is zero here, so the break would start at the line's + // FIRST column while its `startColumn` is derived from the source line + // and reports the last - one span with two answers, overlapping the + // `comment` node that occupies those same bytes. + startOffset: line2.comment ? sourceLineEnd : Math.min(lineOffset + line2.text.length, sourceLineEnd), + endOffset: lexer.lineOffset(next.lineIndex) + }; + }; + const parsed = parseInline(joined, lexer.abbrDefs, lexer.linkDefs, lexer.hasDocumentOffsets ? inlineSource({ + baseOffset: lexer.lineOffset(lines[0].lineIndex), + startLine: firstLineNumber, + startColumn: lexer.lineStartColumn(lines[0].lineIndex), + lineAnchors: lines.map((line2) => ({ + offset: lexer.lineOffset(line2.lineIndex), + column: lexer.lineStartColumn(line2.lineIndex) + })) + }) : inlineSource({ anchored: false })); + const breakIndex = /* @__PURE__ */ new Map(); + const boundaryLines = /* @__PURE__ */ new Set(); + const INLINE_SLOTS = ["children", "inline", "content"]; + const slotsOf = (node2) => { + const record = node2; + return INLINE_SLOTS.map((slot) => record[slot]).filter(Array.isArray); + }; + const readBoundaries = (nodes) => { + for (const node2 of nodes) { + if (node2.type === "soft_break" || node2.type === "hard_break") { + const startLine = node2.pos?.startLine; + if (startLine === void 0) + continue; + boundaryLines.add(startLine - firstLineNumber); + if (node2.type === "soft_break") + breakIndex.set(node2, startLine - firstLineNumber); + continue; + } + for (const slot of slotsOf(node2)) + readBoundaries(slot); + } + }; + readBoundaries(parsed); + if (!anchorable) + stripPositions(parsed); + const pendingComments = /* @__PURE__ */ new Map(); + lines.forEach((line2, index2) => { + if (!line2.comment) + return; + if (!anchorable) + stripPositions([line2.comment]); + pendingComments.set(index2, line2.comment); + }); + const place = (nodes) => { + const out = []; + for (const node2 of nodes) { + if (node2.type !== "soft_break") { + const record = node2; + for (const slot of INLINE_SLOTS) { + const value = record[slot]; + if (Array.isArray(value)) + record[slot] = place(value); + } + out.push(node2); + continue; + } + const index2 = breakIndex.get(node2); + if (index2 !== void 0) { + const comment = pendingComments.get(index2); + if (comment) { + out.push(comment); + pendingComments.delete(index2); + } + } + const hardBreak = { type: "hard_break" }; + const pos = index2 === void 0 ? void 0 : breakPos(index2); + if (pos) + hardBreak.pos = pos; + out.push(hardBreak); + } + return out; + }; + const inline = place(parsed); + for (const index2 of [...pendingComments.keys()].sort((a, b) => a - b)) { + const isLastLine = index2 === lines.length - 1; + if (isLastLine && (index2 === 0 || boundaryLines.has(index2 - 1))) { + inline.push(pendingComments.get(index2)); + } + } + const paragraph = { type: "paragraph", children: inline }; + if (lexer.hasDocumentOffsets) { + const first = lines[0]; + const last = lines[lines.length - 1]; + paragraph.pos = { + startLine: lexer.lineNumber(first.lineIndex), + endLine: lexer.lineNumber(last.lineIndex), + startColumn: lexer.lineStartColumn(first.lineIndex), + endColumn: lexer.lineStartColumn(last.lineIndex) + (lexer.lines[last.lineIndex]?.length ?? 0), + startOffset: lexer.lineOffset(first.lineIndex), + endOffset: lexer.lineOffset(last.lineIndex) + (lexer.lines[last.lineIndex]?.length ?? 0) + }; + const placed = anchorable ? inline.filter((node2) => node2.pos !== void 0) : []; + const firstPos = placed.find((node2) => node2.type !== "soft_break" && node2.type !== "hard_break")?.pos; + const lastPos = placed[placed.length - 1]?.pos; + if (firstPos) { + paragraph.pos.startLine = firstPos.startLine; + if (firstPos.startColumn !== void 0) + paragraph.pos.startColumn = firstPos.startColumn; + if (firstPos.startOffset !== void 0) + paragraph.pos.startOffset = firstPos.startOffset; + } + if (lastPos) { + paragraph.pos.endLine = lastPos.endLine; + if (lastPos.endColumn !== void 0) + paragraph.pos.endColumn = lastPos.endColumn; + if (lastPos.endOffset !== void 0) + paragraph.pos.endOffset = lastPos.endOffset; + } + } + return paragraph; + }); const node = { - type: "div", - attrs: { classes: ["line-block"], order: [".class"] }, + type: "line_block", children }; return node; } -function expandLineBlockLeadingWhitespace(line) { +function expandLineBlockWhitespace(line2) { + let out = ""; let i = 0; - let columns = 0; - while (i < line.length) { - const ch = line[i]; - if (ch === " ") - columns++; - else if (ch === " ") - columns += 4 - columns % 4; - else - break; - i++; - } - return "\uE000".repeat(columns) + line.slice(i); -} -function hardBreaksHasCloser(lexer) { - const start = lexer.pos + 1; - if (start >= lexer.lineBlockNoCloserFrom) - return false; - const fence = RE_HARDBREAKS_OPEN.exec(lexer.peek())[1].length; - if (start >= (lexer.lineBlockNoCloserOfLenFrom.get(fence) ?? Infinity)) - return false; - let sawAnyCloser = false; - for (let i = start; i < lexer.lines.length; i++) { - const c = RE_ADMONITION_CLOSE.exec(lexer.lines[i]); - if (c) { - sawAnyCloser = true; - if (c[1].length >= fence) - return true; + let column = 0; + let seenContent = false; + while (i < line2.length) { + const ch = line2[i]; + if (ch !== " " && ch !== " ") { + out += ch; + seenContent = true; + column++; + i++; + continue; + } + let width2 = 0; + while (i < line2.length && (line2[i] === " " || line2[i] === " ")) { + if (line2[i] === " ") + width2 += 4 - (column + width2) % 4; + else + width2++; + i++; } + column += width2; + out += !seenContent || width2 >= 2 ? "\uE000".repeat(width2) : " "; } - const prev = lexer.lineBlockNoCloserOfLenFrom.get(fence) ?? Infinity; - if (start < prev) - lexer.lineBlockNoCloserOfLenFrom.set(fence, start); - if (!sawAnyCloser) - lexer.lineBlockNoCloserFrom = start; - return false; + return out; +} +function dropTrailingSpaces(line2) { + return line2.replace(/ +$/, ""); } function parseHardBreaksBlock(lexer) { const openLineIndex = lexer.pos; const m = RE_HARDBREAKS_OPEN.exec(lexer.consume()); const fence = m[1].length; - const inner = []; - while (!lexer.eof()) { - const ln = lexer.peek(); - const c = RE_ADMONITION_CLOSE.exec(ln); - if (c && c[1].length >= fence) { - lexer.consume(); - break; - } - lexer.consume(); - inner.push(ln); - } - const subLexer2 = nestedSubLexer(lexer, inner.join("\n"), openLineIndex + 1); + const inner = collectColonFenceBody(lexer, { + kind: "hard-break block", + lineIndex: openLineIndex, + fenceWidth: fence + }); + const subLexer2 = nestedSubLexer(lexer, inner.map((line2) => line2.text), openLineIndex + 1); const children = parseBlocks(subLexer2, 0); for (const child of children) { if (child.type === "paragraph") { - child.children = child.children.map((node) => node.type === "soft_break" ? { type: "hard_break" } : node); + child.children = child.children.map((node) => { + if (node.type !== "soft_break") + return node; + const hardBreak = { type: "hard_break" }; + if (node.pos) + hardBreak.pos = node.pos; + return hardBreak; + }); } } return { @@ -10092,46 +10931,17 @@ function parseHardBreaksBlock(lexer) { children }; } -function divHasCloser(lexer) { - const start = lexer.pos + 1; - if (start >= lexer.divNoCloserFrom) - return false; - const fence = /^(:{3,})/.exec(lexer.peek())[1].length; - if (start >= (lexer.divNoCloserOfLenFrom.get(fence) ?? Infinity)) - return false; - let sawAnyCloser = false; - for (let i = start; i < lexer.lines.length; i++) { - const c = RE_ADMONITION_CLOSE.exec(lexer.lines[i]); - if (c) { - sawAnyCloser = true; - if (c[1].length >= fence) - return true; - } - } - const prev = lexer.divNoCloserOfLenFrom.get(fence) ?? Infinity; - if (start < prev) - lexer.divNoCloserOfLenFrom.set(fence, start); - if (!sawAnyCloser) - lexer.divNoCloserFrom = start; - return false; -} function parseDiv(lexer) { const openLineIndex = lexer.pos; const m = RE_DIV_OPEN.exec(lexer.consume()); const fence = m[1].length; const label = m[2] !== void 0 ? m[2].slice(1, -1) : void 0; - const inner = []; - while (!lexer.eof()) { - const ln = lexer.peek(); - const c = RE_ADMONITION_CLOSE.exec(ln); - if (c && c[1].length >= fence) { - lexer.consume(); - break; - } - lexer.consume(); - inner.push(ln); - } - const subLexer2 = nestedSubLexer(lexer, inner.join("\n"), openLineIndex + 1); + const inner = collectColonFenceBody(lexer, { + kind: "div", + lineIndex: openLineIndex, + fenceWidth: fence + }); + const subLexer2 = nestedSubLexer(lexer, inner.map((line2) => line2.text), openLineIndex + 1); const node = { type: "div", children: parseBlocks(subLexer2, 0) }; if (label !== void 0) { node.label = label; @@ -10143,19 +10953,47 @@ function parseDefinitionList(lexer) { const parseDefBody = (first, firstLineIndex) => { const bodyLines = []; const bodyLineNumbers = []; + const lazyState = { + inFence: false, + fenceClose: null, + inComment: false, + commentLen: 0, + lazyFoldableBeforeComment: false, + openedCommentAtColumn: false, + inTable: false, + invisibleAtColumn: false, + inFootnoteBody: false, + quoteInner: null, + absorbingFence: false, + divDepth: 0, + lazyFoldable: false, + inDefList: false, + attrRun: null + }; + const defFenceMemo = /* @__PURE__ */ new Map(); + const track = (content, atLineIndex, atContentColumn = true) => { + trackItemLazyState(content, lazyState, (marker) => atLineIndex === void 0 ? true : itemFenceHasCloser(lexer, marker, atLineIndex, DEFLIST_CONTENT_COL, defFenceMemo), atContentColumn); + }; + const isDefBodyBoundary = (a) => isBlankLine(a) || /^\+[ \t]*$/.test(a) || RE_DEFLIST_TERM.test(a) || RE_DEFLIST_DEF.test(a); if (/^\+[ \t]*$/.test(first)) { - while (!lexer.eof()) { - const a = lexer.peek(); - if (isBlankLine(a) || /^\+[ \t]*$/.test(a) || RE_DEFLIST_TERM.test(a) || RE_DEFLIST_DEF.test(a)) - break; - const lineIndex = lexer.pos; - lexer.consume(); - bodyLines.push(a); - bodyLineNumbers.push(lexer.lineNumber(lineIndex)); - } + const firstBlock = collectAttachedBlock(lexer, isDefBodyBoundary); + bodyLines.push(...firstBlock.lines); + bodyLineNumbers.push(...firstBlock.lineNumbers); + for (const a of firstBlock.lines) + track(a); } else { bodyLines.push(first); bodyLineNumbers.push(lexer.lineNumber(firstLineIndex)); + const firstState = markerLineState(first); + lazyState.lazyFoldable = firstState.leavesParagraphOpen; + lazyState.inTable = firstState.endsOnTableRow; + lazyState.quoteInner = firstState.quote; + const leadFence = RE_FENCE.exec(first) ?? RE_RAW_FENCE.exec(first); + if (leadFence) { + lazyState.inFence = true; + lazyState.fenceClose = fenceCloseRe(RE_FENCE.test(first) ? leadFence[2] : leadFence[1]); + lazyState.lazyFoldable = false; + } } for (; ; ) { if (lexer.eof()) @@ -10164,30 +11002,25 @@ function parseDefinitionList(lexer) { if (/^\+[ \t]*$/.test(ln)) { const plusLineIndex = lexer.pos; lexer.consume(); - const attached = []; - const attachedLineNumbers = []; - while (!lexer.eof()) { - const a = lexer.peek(); - if (isBlankLine(a) || /^\+[ \t]*$/.test(a) || RE_DEFLIST_TERM.test(a) || RE_DEFLIST_DEF.test(a)) - break; - const lineIndex = lexer.pos; - lexer.consume(); - attached.push(a); - attachedLineNumbers.push(lexer.lineNumber(lineIndex)); - } + const { lines: attached, lineNumbers: attachedLineNumbers } = collectAttachedBlock(lexer, isDefBodyBoundary); if (attached.length > 0) { bodyLines.push(""); bodyLineNumbers.push(lexer.lineNumber(plusLineIndex)); - for (const a of attached) + track(""); + for (const a of attached) { bodyLines.push(a); + track(a); + } bodyLineNumbers.push(...attachedLineNumbers); } continue; } - if (!isBlankLine(ln) && leadingWhitespace(ln) >= 3) { + if (!isBlankLine(ln) && indentColumns(ln, DEFLIST_CONTENT_COL) >= DEFLIST_CONTENT_COL) { const lineIndex = lexer.pos; - bodyLines.push(ln.replace(/^[^\S\u00a0]+/, "")); + const dedented = sliceColumns(ln, DEFLIST_CONTENT_COL, true); + bodyLines.push(dedented); bodyLineNumbers.push(lexer.lineNumber(lineIndex)); + track(dedented, lineIndex); lexer.consume(); continue; } @@ -10196,35 +11029,53 @@ function parseDefinitionList(lexer) { while (isBlankLine(lexer.peek(look))) look++; const after = lexer.peek(look); - if (after !== void 0 && !isBlankLine(after) && leadingWhitespace(after) >= 3) { + if (after !== void 0 && !isBlankLine(after) && indentColumns(after, DEFLIST_CONTENT_COL) >= DEFLIST_CONTENT_COL) { for (let k = 0; k < look; k++) { const lineIndex = lexer.pos; bodyLines.push(""); bodyLineNumbers.push(lexer.lineNumber(lineIndex)); + track(""); lexer.consume(); } continue; } break; } - if (RE_DEFLIST_TERM.test(ln) || RE_DEFLIST_DEF.test(ln)) + if (RE_DEFLIST_TERM.test(ln) || RE_DEFLIST_DEF.test(ln) || RE_DEFLIST_MARKER_EMPTY.test(ln)) break; - if (!startsInterruptingBlock(lexer)) { + const below = ln.replace(/^[ \t]+/, ""); + if (lazyState.lazyFoldable && !startsInterruptingBlock(lexer, below)) { const lineIndex = lexer.pos; bodyLines.push(ln); bodyLineNumbers.push(lexer.lineNumber(lineIndex)); + track(ln, void 0, false); lexer.consume(); continue; } break; } - const sub = nestedSubLexer(lexer, bodyLines.join("\n"), firstLineIndex, bodyLineNumbers); + const sub = nestedSubLexer(lexer, bodyLines, firstLineIndex, bodyLineNumbers); return parseBlocks(sub, 0); }; + function lineRange(lx, first, last) { + const lastLine = lx.lines[last]; + if (lastLine === void 0) + return void 0; + return { + startLine: lx.lineNumber(first), + endLine: lx.lineNumber(last), + startColumn: lx.lineStartColumn(first), + endColumn: lx.lineStartColumn(last) + lastLine.length, + startOffset: lx.lineOffset(first), + endOffset: lx.lineOffset(last) + lastLine.length + }; + } while (!lexer.eof() && RE_DEFLIST_TERM.test(lexer.peek())) { const terms = []; + const termSpans = []; const definitions = []; const definitionLines = []; + const definitionSpans = []; while (!lexer.eof()) { const t = RE_DEFLIST_TERM.exec(lexer.peek()); if (!t) @@ -10232,18 +11083,35 @@ function parseDefinitionList(lexer) { const termLineIndex = lexer.pos; lexer.consume(); let termText = t[1]; + let continuationLines = 0; while (!lexer.eof()) { const next = lexer.peek(); - if (isBlankLine(next) || RE_DEFLIST_TERM.test(next) || RE_DEFLIST_DEF.test(next) || endsHeadingOrQuote(lexer)) + if (isBlankLine(next) || RE_DEFLIST_TERM.test(next) || RE_DEFLIST_DEF.test(next) || RE_DEFLIST_MARKER_EMPTY.test(next) || endsHeadingOrQuote(lexer)) break; termText += "\n" + next; + continuationLines++; lexer.consume(); } + termText = dropTrailingWhitespace(termText); + const termStart = lexer.lines[termLineIndex].indexOf(t[1]); + const termAnchors = continuationLines > 0 ? [ + { + offset: lexer.lineOffset(termLineIndex) + termStart, + column: lexer.lineStartColumn(termLineIndex) + termStart + }, + ...Array.from({ length: continuationLines }, (_unused, i) => ({ + offset: lexer.lineOffset(termLineIndex + 1 + i), + column: lexer.lineStartColumn(termLineIndex + 1 + i) + })) + ] : void 0; terms.push(parseInline(termText, lexer.abbrDefs, lexer.linkDefs, { - baseOffset: lexer.lineOffset(termLineIndex) + lexer.lines[termLineIndex].indexOf(t[1]), + anchored: lexer.hasDocumentOffsets, + baseOffset: lexer.lineOffset(termLineIndex) + termStart, startLine: lexer.lineNumber(termLineIndex), - startColumn: lexer.lines[termLineIndex].indexOf(t[1]) + 1 + startColumn: lexer.lineStartColumn(termLineIndex) + termStart, + ...termAnchors ? { lineAnchors: termAnchors } : {} })); + termSpans.push(lexer.hasDocumentOffsets ? lineRange(lexer, termLineIndex, termLineIndex + continuationLines) : void 0); } while (!lexer.eof()) { if (isBlankLine(lexer.peek())) { @@ -10262,8 +11130,9 @@ function parseDefinitionList(lexer) { lexer.consume(); definitionLines.push(lexer.lineNumber(defLineIndex)); definitions.push(parseDefBody(d[1], defLineIndex)); + definitionSpans.push(lexer.hasDocumentOffsets ? lineRange(lexer, defLineIndex, lexer.pos - 1) : void 0); } - items.push({ terms, definitions, definitionLines }); + items.push({ terms, definitions, termSpans, definitionLines, definitionSpans }); if (!lexer.eof() && isBlankLine(lexer.peek())) { let look = 1; while (isBlankLine(lexer.peek(look))) @@ -10279,74 +11148,114 @@ function parseDefinitionList(lexer) { return { type: "definition_list", items }; } function parseAbbrDef(lexer) { - const line = lexer.consume(); - const m = RE_ABBR_DEF.exec(line); + const line2 = lexer.consume(); + const m = RE_ABBR_DEF.exec(line2); return { type: "abbreviation_def", abbr: m[1], expansion: m[2] }; } -function trackBlockQuoteLazyState(content, state) { - if (state.inComment) { - const c = /^(%{3,})\s*$/.exec(content); - if (c && c[1].length >= state.commentLen) - state.inComment = false; - state.paragraphOpen = false; - return; +function trackBlockQuoteLazyState(content, state, hasCommentCloser, hasFenceCloser) { + let text = content; + let level = state; + for (; ; ) { + const descend2 = classifyQuotedLine(text, level, hasCommentCloser, hasFenceCloser); + if (descend2 === null) + return; + text = descend2.text; + level = descend2.state; } - if (state.inFence) { - if (state.fenceClose.test(content)) - state.inFence = false; - state.paragraphOpen = false; - return; +} +function classifyQuotedLine(content, state, hasCommentCloser, hasFenceCloser) { + const wasAbsorbing = state.mode.kind === "paragraph" && state.mode.absorbingFence; + const wasInTable = state.inTable; + state.inTable = false; + if (state.mode.kind === "comment_fence") { + const run = commentFenceRun(content); + if (run === state.mode.length) + state.mode = { kind: "closed" }; + return null; + } + if (state.mode.kind === "code_fence") { + if (state.mode.close.test(content)) + state.mode = { kind: "closed" }; + return null; + } + if (trackWrappedAttributeRun(state, content)) { + closeBlockQuoteParagraph(state); + return null; } if (isBlankLine(content)) { - state.paragraphOpen = false; - return; + closeBlockQuoteParagraph(state); + return null; + } + if (isBlockAttributeLine(content)) { + closeBlockQuoteParagraph(state); + return null; } if (RE_HEADING.test(content) || isTableRow(content) || RE_HR.test(content)) { - state.paragraphOpen = false; - return; + state.inTable = isTableRow(content); + closeBlockQuoteParagraph(state); + return null; } - if (!state.paragraphOpen) { - const fence = RE_FENCE.exec(content); - if (fence) { - const marker = fence[2]; - state.inFence = true; - state.fenceClose = new RegExp(`^${marker[0]}{${marker.length},}\\s*$`); - state.paragraphOpen = false; - return; - } - const raw = RE_RAW_FENCE.exec(content); - if (raw) { - const marker = raw[1]; - state.inFence = true; - state.fenceClose = new RegExp(`^${marker[0]}{${marker.length},}\\s*$`); - state.paragraphOpen = false; - return; - } - const comment = /^(%{3,})\s*$/.exec(content); - if (comment) { - state.inComment = true; - state.commentLen = comment[1].length; - state.paragraphOpen = false; - return; - } - if (RE_DIV_OPEN.test(content) || RE_ADMONITION_OPEN.test(content) || RE_LINE_BLOCK_OPEN.test(content) || RE_HARDBREAKS_OPEN.test(content)) { - state.paragraphOpen = false; - return; + if (wasInTable && RE_TABLE_CONT.test(content)) { + state.inTable = true; + closeBlockQuoteParagraph(state); + return null; + } + const quoted = RE_BLOCKQUOTE.exec(content); + if (quoted) { + const inner = state.mode.kind === "quote" ? state.mode.inner : { mode: { kind: "closed" }, inTable: false, colonWidths: [], attrRun: null }; + state.mode = { kind: "quote", inner }; + return { text: quoted[1] ?? "", state: inner }; + } + if (RE_DEFLIST_TERM.test(content) || RE_FOOTNOTE_DEF.test(content) || isLinkDefLine(content)) { + closeBlockQuoteParagraph(state); + return null; + } + const bareFenceRun = /^(:{3,})[ \t]*$/.exec(content); + const bareFence = bareFenceRun !== null; + if (bareFence && bareFenceRun[1].length === state.colonWidths[state.colonWidths.length - 1]) { + state.colonWidths.pop(); + closeBlockQuoteParagraph(state); + return null; + } + if (RE_DIV_OPEN.test(content) || RE_ADMONITION_OPEN.test(content) && !RE_ADMONITION_CLOSE.test(content) || RE_LINE_BLOCK_OPEN.test(content) || RE_HARDBREAKS_OPEN.test(content)) { + if (wasAbsorbing && bareFence) { + state.mode = { kind: "paragraph", absorbingFence: true }; + return null; } + state.colonWidths.push(colonFenceOpenerLen(content) ?? 3); + closeBlockQuoteParagraph(state); + return null; + } + if (/^:{3,}/.test(content)) { + state.mode = { kind: "paragraph", absorbingFence: true }; + return null; + } + const fence = RE_FENCE.exec(content); + const raw = fence ? null : RE_RAW_FENCE.exec(content); + const fenceMarker = fence ? fence[2] : raw ? raw[1] : null; + if (fenceMarker !== null && (!blockQuoteParagraphOpen(state) || hasFenceCloser(fenceMarker))) { + state.mode = { kind: "code_fence", close: fenceCloseRe(fenceMarker) }; + return null; } - state.paragraphOpen = true; + const commentRun = commentFenceRun(content); + if (commentRun !== void 0 && hasCommentCloser(commentRun)) { + state.mode = { kind: "comment_fence", length: commentRun }; + return null; + } + state.mode = { kind: "paragraph", absorbingFence: wasAbsorbing }; + return null; } function parseBlockQuote(lexer) { const firstLineIndex = lexer.pos; const inner = []; const innerLineNumbers = []; const state = { - inFence: false, - fenceClose: null, - inComment: false, - commentLen: 0, - paragraphOpen: false + mode: { kind: "closed" }, + inTable: false, + colonWidths: [], + attrRun: null }; + const fenceCloserMemo = /* @__PURE__ */ new Map(); while (!lexer.eof()) { const ln = lexer.peek(); const m = RE_BLOCKQUOTE.exec(ln); @@ -10356,49 +11265,43 @@ function parseBlockQuote(lexer) { const content = m[1] ?? ""; inner.push(content); innerLineNumbers.push(lexer.lineNumber(lineIndex2)); - trackBlockQuoteLazyState(content, state); + trackBlockQuoteLazyState(content, state, (fence) => quotedCommentHasCloser(lexer, fence, lineIndex2), (marker) => quotedFenceHasCloser(lexer, marker, lineIndex2, fenceCloserMemo)); continue; } if (/^\+[ \t]*$/.test(ln)) { - const plusLineNumber = lexer.lineNumber(lexer.pos); lexer.consume(); - const attached = []; - const attachedLineNumbers = []; - while (!lexer.eof()) { - const next2 = lexer.peek(); - if (isBlankLine(next2) || RE_BLOCKQUOTE.test(next2) || /^\+[ \t]*$/.test(next2)) { - break; - } - attachedLineNumbers.push(lexer.lineNumber(lexer.pos)); - lexer.consume(); - attached.push(next2); - } + const { lines: attached, lineNumbers: attachedLineNumbers } = collectAttachedBlock(lexer, (next2) => isBlankLine(next2) || RE_BLOCKQUOTE.test(next2) || /^\+[ \t]*$/.test(next2)); if (attached.length > 0) { inner.push(""); - innerLineNumbers.push(plusLineNumber); + innerLineNumbers.push(attachedLineNumbers[0]); for (const attachedLine of attached) inner.push(attachedLine); innerLineNumbers.push(...attachedLineNumbers); inner.push(""); - innerLineNumbers.push(plusLineNumber); - state.paragraphOpen = false; + innerLineNumbers.push(attachedLineNumbers[attachedLineNumbers.length - 1]); + closeBlockQuoteParagraph(state); } continue; } if (isBlankLine(ln) || RE_CAPTION.test(ln) || colonFenceShapeEndsLazyContinuation(ln) || startsInterruptingBlock(lexer)) { break; } - if (!state.paragraphOpen) + if (!blockQuoteParagraphOpen(state)) break; const lineIndex = lexer.pos; lexer.consume(); + const lazyLinkDef = isLinkDefLine(ln); + if (lazyLinkDef) { + lexer.literalLazyLinkDefLines.add(lexer.lineNumber(lineIndex)); + } inner.push(ln); innerLineNumbers.push(lexer.lineNumber(lineIndex)); - trackBlockQuoteLazyState(ln, state); + trackBlockQuoteLazyState(ln, state, (fence) => quotedCommentHasCloser(lexer, fence, lineIndex), (marker) => quotedFenceHasCloser(lexer, marker, lineIndex, fenceCloserMemo)); } - const subLexer2 = nestedSubLexer(lexer, inner.join("\n"), firstLineIndex, innerLineNumbers); + const subLexer2 = nestedSubLexer(lexer, inner, firstLineIndex, innerLineNumbers); const children = parseBlocks(subLexer2, 0); const bq = { type: "block_quote", children }; + const quoteEndIndex = lexer.pos; let lookahead = 0; while (!lexer.eof() && isBlankLine(lexer.peek(lookahead))) lookahead++; @@ -10408,18 +11311,19 @@ function parseBlockQuote(lexer) { if (cap && lookahead <= 1) { for (let i = 0; i <= lookahead; i++) lexer.consume(); + attachBlockPos(lexer, bq, firstLineIndex, quoteEndIndex); return { type: "figure", target: bq, - caption: parseInline(readCaptionText(lexer, cap[1]), lexer.abbrDefs, lexer.linkDefs, void 0, true) + caption: parseCaptionInline(lexer, cap[1]) }; } } return bq; } -function isBlockImageLine(line) { - const m = RE_BARE_IMAGE.exec(line); - return m !== null && (m[5] === void 0 || isValidAttrPayload(m[5]) && !isEmptyAttrs(parseAttrs(m[5]))); +function isBlockImageLine(line2) { + const m = RE_BARE_IMAGE.exec(line2); + return m !== null && (m[5] === void 0 || isValidInlineAttrPayload(m[5]) && !isEmptyAttrs(parseAttrs(m[5]))); } function imageIsBlock(lexer) { const next = lexer.peek(1); @@ -10432,8 +11336,9 @@ function imageIsBlock(lexer) { return interrupts; } function parseBlockImage(lexer) { - const line = lexer.consume(); - const m = RE_BARE_IMAGE.exec(line); + const imageLineIndex = lexer.pos; + const line2 = lexer.consume(); + const m = RE_BARE_IMAGE.exec(line2); const img = { type: "image", src: m[2], alt: m[1] }; const title = m[3] ?? m[4]; if (title !== void 0) @@ -10449,41 +11354,42 @@ function parseBlockImage(lexer) { if (cap && lookahead <= 1) { for (let i = 0; i <= lookahead; i++) lexer.consume(); + attachBlockPos(lexer, img, imageLineIndex, imageLineIndex + 1); return { type: "figure", target: img, - caption: parseInline(readCaptionText(lexer, cap[1]), lexer.abbrDefs, lexer.linkDefs, void 0, true) + caption: parseCaptionInline(lexer, cap[1]) }; } } return img; } -function unorderedMarkerChar(line) { - return line.replace(/^\s*/, "").charAt(0); +function unorderedMarkerChar(line2) { + return line2.replace(/^\s*/, "").charAt(0); } -function matchListMarker(line, isTask, isOrdered) { +function matchListMarker(line2, isTask, isOrdered) { if (isTask) - return RE_TASK.exec(line); + return RE_TASK.exec(line2); if (isOrdered) { - if (RE_TASK.test(line)) + if (RE_TASK.test(line2)) return null; - return RE_ORDERED.exec(line); + return RE_ORDERED.exec(line2); } - if (RE_TASK.test(line) || RE_ORDERED.test(line)) + if (RE_TASK.test(line2) || RE_ORDERED.test(line2)) return null; - return RE_UNORDERED.exec(line); + return RE_UNORDERED.exec(line2); } -function markerContentColumn(line) { - const la = extractItemAttr(line); - const mline = la ? la.stripped : line; - const base = indentColumns(line); +function markerContentColumn(line2) { + const la = extractItemAttr(line2); + const mline = la ? la.stripped : line2; + const base = indentColumns(line2); if (RE_TASK.test(mline)) - return base + 2 + (la ? line.length - mline.length : 0); + return base + 2 + (la ? line2.length - mline.length : 0); const m = RE_ORDERED.exec(mline) ?? RE_UNORDERED.exec(mline); if (!m) return -1; const content = m[m.length - 1]; - return base + (line.length - leadingWhitespace(line) - content.length); + return base + (line2.length - leadingWhitespace(line2) - content.length); } function romanToInt(s) { const map = { i: 1, v: 5, x: 10, l: 50, c: 100, d: 500, m: 1e3 }; @@ -10496,10 +11402,10 @@ function romanToInt(s) { } return total; } -function olKindMatches(marker, kind) { - switch (kind) { +function olKindMatches(marker, kind2) { + switch (kind2) { case "dec": - return /^[0-9]+$/.test(marker); + return /^[0-9]*$/.test(marker); case "alo": return /^[a-z]$/.test(marker); case "aup": @@ -10511,6 +11417,8 @@ function olKindMatches(marker, kind) { } } function olKindOf(marker, nextMarker) { + if (marker === "") + return "dec"; if (/^[0-9]+$/.test(marker)) return "dec"; const upper = marker === marker.toUpperCase(); @@ -10531,52 +11439,402 @@ function olKindOf(marker, nextMarker) { } return upper ? "aup" : "alo"; } -function olStartOf(marker, kind) { - if (kind === "dec") - return parseInt(marker, 10); - if (kind === "rlo" || kind === "rup") +function olStartOf(marker, kind2) { + if (kind2 === "dec") { + const n = parseInt(marker, 10); + return Number.isNaN(n) ? 1 : n; + } + if (kind2 === "rlo" || kind2 === "rup") return romanToInt(marker); return marker.toLowerCase().charCodeAt(0) - 96; } -function olTypeOf(kind) { - return kind === "dec" ? "" : kind === "alo" ? "a" : kind === "aup" ? "A" : kind === "rlo" ? "i" : "I"; +function olTypeOf(kind2) { + return kind2 === "dec" ? "" : kind2 === "alo" ? "a" : kind2 === "aup" ? "A" : kind2 === "rlo" ? "i" : "I"; } -function orderedContinues(line, kind, delim) { - const o = RE_ORDERED.exec(line); - return o !== null && o[3] === delim && olKindMatches(o[2], kind); +function orderedContinues(line2, kind2, delim) { + const o = RE_ORDERED.exec(line2); + return o !== null && o[3] === delim && olKindMatches(o[2], kind2); +} +function isInvisibleLine(line2) { + const l = line2.replace(/^[ \t]+/, ""); + if (RE_COMMENT_BLOCK.test(l)) + return false; + if (RE_COMMENT_LINE.test(l)) + return true; + if (indentColumns(line2, 1) === 0 && (isLinkDefLine(l) || RE_FOOTNOTE_DEF.test(l))) + return true; + return indentColumns(line2, 1) === 0 && isBlockAttributeLine(l); } -function lineOpensBlock(line) { - return RE_RAW_FENCE.test(line) || RE_FENCE.test(line) || RE_COMMENT_BLOCK.test(line) || RE_ABBR_DEF.test(line) || RE_FOOTNOTE_DEF.test(line) || RE_LINK_DEF.test(line) || RE_HR.test(line) || RE_HEADING.test(line) || RE_DEFLIST_TERM.test(line) || RE_BLOCKQUOTE.test(line) || RE_TASK.test(line) || RE_UNORDERED.test(line) || RE_ORDERED.test(line) || extractItemAttr(line) !== null || isTableRow(line) || RE_ADMONITION_OPEN.test(line) && !RE_ADMONITION_CLOSE.test(line) || RE_DIV_OPEN.test(line) || RE_LINE_BLOCK_OPEN.test(line) || RE_HARDBREAKS_OPEN.test(line); +function lineOpensBlock(line2) { + return RE_RAW_FENCE.test(line2) || RE_FENCE.test(line2) || RE_COMMENT_BLOCK.test(line2) || // No RE_ABBR_DEF: these lines are item content, never document level. + // + // The other two definition kinds are COLUMN-STRICT, like the attribute line + // below: collected only AT the container's content column, and one column + // further in they are not definitions at all - they render as ordinary text + // and open nothing. Testing the shape at any indent made an indented + // `[^f]: n` "open a block", so the looseness scan stopped short of the real + // second paragraph and left the item TIGHT where carve-php and carve-rs + // leave it loose (carve-js#976). `isLinkDefLine` is what actually fired: + // the anchored footnote pattern rejects the leading space, but a link + // definition reads `[^f]: n` as label `^f` - which is why the two are + // ordered as they are a few lines up. + indentColumns(line2, 1) === 0 && (RE_FOOTNOTE_DEF.test(line2) || isLinkDefLine(line2)) || RE_HR.test(line2) || RE_HEADING.test(line2) || RE_DEFLIST_TERM.test(line2) || RE_BLOCKQUOTE.test(line2) || RE_TASK.test(line2) || RE_UNORDERED.test(line2) || RE_ORDERED.test(line2) || extractItemAttr(line2) !== null || isTableRow(line2) || RE_ADMONITION_OPEN.test(line2) && !RE_ADMONITION_CLOSE.test(line2) || RE_DIV_OPEN.test(line2) || RE_LINE_BLOCK_OPEN.test(line2) || RE_HARDBREAKS_OPEN.test(line2); } -function lazyContinuationEndsList(line) { - return RE_RAW_FENCE.test(line) || RE_FENCE.test(line) || RE_COMMENT_BLOCK.test(line) || // A flush-left colon-fence shaped line ends list lazy continuation +function lazyContinuationEndsList(line2, lexer) { + if (RE_RAW_FENCE.test(line2)) + return fenceHasCloser(lexer, RE_RAW_FENCE.exec(line2)[1]); + if (RE_FENCE.test(line2)) + return fenceHasCloser(lexer, RE_FENCE.exec(line2)[2]); + return RE_COMMENT_BLOCK.test(line2) || // A flush-left colon-fence shaped line ends list lazy continuation // regardless of outer-stream closer lookahead. If the line belongs to the // item, it must be indented and parsed by the item sub-lexer; otherwise a // later flush-left `:::` can be incorrectly pulled in as the item's closer. - RE_ADMONITION_OPEN.test(line) && !RE_ADMONITION_CLOSE.test(line) || RE_DIV_OPEN.test(line) || RE_LINE_BLOCK_OPEN.test(line) || RE_HARDBREAKS_OPEN.test(line) || RE_ABBR_DEF.test(line) || RE_FOOTNOTE_DEF.test(line) || RE_LINK_DEF.test(line) || RE_HR.test(line) || RE_HEADING.test(line) || RE_DEFLIST_TERM.test(line) || RE_BLOCKQUOTE.test(line) || RE_TASK.test(line) || RE_UNORDERED.test(line) || RE_ORDERED.test(line) || extractItemAttr(line) !== null || isTableRow(line) || isBlockImageLine(line); + RE_ADMONITION_OPEN.test(line2) && !RE_ADMONITION_CLOSE.test(line2) || RE_DIV_OPEN.test(line2) || RE_LINE_BLOCK_OPEN.test(line2) || RE_HARDBREAKS_OPEN.test(line2) || // No RE_ABBR_DEF: a lazy line is item content, so the definition form is + // not recognized and the line folds into the item as text. + // + // The other two are gated on the line being FLUSH, which is what every + // other predicate here gets for free from its own anchor. RE_LINK_DEF is + // deliberately whitespace-tolerant - other passes need it to recognize a + // quoted or nested def - and its leading class is "whitespace except NBSP", + // so it matches a leading SPACE. Unguarded, that made a definition ONE + // COLUMN IN end the fold, where a heading, quote, table row, colon fence or + // bullet in the same position folds as text (PART 1 S4). It also swallowed + // the footnote form, since `[^f]: x` has the link-def shape too, which is + // why the flush-anchored RE_FOOTNOTE_DEF above never had to match for the + // footnote case to break. A definition opens only AT its container's + // content column - the same strict rule `parseBlockInner` applies + // (carve-js#597). + leadingWhitespace(line2) === 0 && (RE_FOOTNOTE_DEF.test(line2) || isLinkDefLine(line2)) || RE_HR.test(line2) || RE_HEADING.test(line2) || // A caption line (`^ …`) ends the item's lazy continuation rather than + // folding in, matching carve-php / carve-rs (a caption is a heading/figure + // terminator, not plain prose the item absorbs). + RE_CAPTION.test(line2) || // A BLOCK-ATTRIBUTE LINE ENDS THE FOLD (PART 9 §10 I5, markup-carve/carve#1028). + // I5 makes the invisible constructs interrupters - "a reference definition + // ..., a comment ..., and a block-attribute line (`{…}` alone on a line, + // §15)" - and I6 applies the relation to EVERY open paragraph, an item's + // included. Two arms above already carry the other two invisible kinds; this + // one was missing, so `- item` / `{.cls}` / `> quote` folded the attribute + // line INTO the item, where it had no following block to float onto and was + // dropped as dangling. The author's attribute reached neither the `
  • ` nor + // the quote and rendered nowhere, which is the shape PART 2's LIST-ITEM + // ATTRIBUTES clause names and REJECTS by engine: "a trailing `{…}` line + // folded onto a tight item, which carve-php attached to the `
  • ` and + // carve-js dropped". + // + // The lexer is positioned on this line, so the multi-line form (§15 A5) is + // recognized here exactly as `startsInterruptingBlock` recognizes it, rather + // than by a single-line spelling that would answer differently one column in. + peekBlockAttributes(lexer) || RE_DEFLIST_TERM.test(line2) || RE_BLOCKQUOTE.test(line2) || RE_TASK.test(line2) || RE_UNORDERED.test(line2) || RE_ORDERED.test(line2) || extractItemAttr(line2) !== null || isTableRow(line2); } -function colonFenceShapeEndsLazyContinuation(line) { - return RE_ADMONITION_OPEN.test(line) && !RE_ADMONITION_CLOSE.test(line) || RE_DIV_OPEN.test(line) || RE_LINE_BLOCK_OPEN.test(line) || RE_HARDBREAKS_OPEN.test(line); +function colonFenceShapeEndsLazyContinuation(line2) { + return RE_ADMONITION_OPEN.test(line2) && !RE_ADMONITION_CLOSE.test(line2) || RE_DIV_OPEN.test(line2) || RE_LINE_BLOCK_OPEN.test(line2) || RE_HARDBREAKS_OPEN.test(line2); } -function trackItemLazyState(content, state) { - if (state.inComment) { - const c = /^(%{3,})\s*$/.exec(content); - if (c && c[1].length >= state.commentLen) - state.inComment = false; - state.lazyFoldable = false; - state.inDefList = false; - return; - } - if (state.inFence) { - if (state.fenceClose.test(content)) - state.inFence = false; - state.lazyFoldable = false; - state.inDefList = false; - return; +function isLiteralColonFenceLine(line2) { + line2 = line2.replace(/^[ \t]+/, ""); + return /^:{3,}/.test(line2) && !RE_ADMONITION_CLOSE.test(line2) && !(RE_ADMONITION_OPEN.test(line2) && !RE_ADMONITION_CLOSE.test(line2)) && !RE_DIV_OPEN.test(line2) && !RE_LINE_BLOCK_OPEN.test(line2) && !RE_HARDBREAKS_OPEN.test(line2); +} +function insideOpenFence(state) { + return state.inFence || state.inComment || state.divDepth > 0; +} +function insideOpenQuoteParagraph(state) { + return state.quoteInner !== null && blockQuoteParagraphOpen(state.quoteInner); +} +function opaqueSpanEnd(scan2, i) { + const line2 = scan2.at(i); + if (line2 === void 0) + return -1; + const fence = RE_FENCE.exec(line2); + const rawFence = fence ? null : RE_RAW_FENCE.exec(line2); + const marker = fence ? fence[2] : rawFence ? rawFence[1] : null; + if (marker !== null) { + if (!codeCloserPossible(scan2.index, marker, scan2.base + i)) + return -1; + const closeRe = fenceCloseRe(marker); + for (let j = i + 1; ; j++) { + const candidate = scan2.at(j); + if (candidate === void 0) + return -1; + if (closeRe.test(candidate)) + return j; + } } - if (isBlankLine(content)) { - state.lazyFoldable = false; - return; + const run = commentFenceRun(line2); + if (run === void 0) + return -1; + if (!exactCloserPossible(scan2.index.comment, run, scan2.base + i)) + return -1; + for (let j = i + 1; ; j++) { + const candidate = scan2.at(j); + if (candidate === void 0) + return -1; + if (commentFenceRun(candidate) === run) + return j; + } +} +function colonBlockOpenerRun(line2) { + const m = (RE_ADMONITION_CLOSE.test(line2) ? null : RE_ADMONITION_OPEN.exec(line2)) ?? RE_LINE_BLOCK_OPEN.exec(line2) ?? RE_HARDBREAKS_OPEN.exec(line2) ?? RE_DIV_OPEN.exec(line2); + return m ? m[1].length : null; +} +function findColonCloser(scan2, openIdx, len) { + if (!exactCloserPossible(scan2.index.colon, len, scan2.base + openIdx)) + return -1; + const stack = [len]; + for (let j = openIdx + 1; ; j++) { + const line2 = scan2.at(j); + if (line2 === void 0) + return -1; + const span2 = opaqueSpanEnd(scan2, j); + if (span2 !== -1) { + j = span2; + continue; + } + const close = RE_ADMONITION_CLOSE.exec(line2); + if (close) { + const closeLen = close[1].length; + if (closeLen === stack[stack.length - 1]) { + stack.pop(); + if (stack.length === 0) + return j; + } else { + stack.push(closeLen); + } + continue; + } + const open = colonBlockOpenerRun(line2); + if (open !== null) + stack.push(open); + } +} +function fencedBlockEnd(scan2) { + const opaque = opaqueSpanEnd(scan2, 0); + if (opaque !== -1) + return opaque; + const first = scan2.at(0); + if (first === void 0) + return -1; + const run = colonBlockOpenerRun(first); + if (run !== null) { + const close = findColonCloser(scan2, 0, run); + if (close !== -1) + return close; + } + return -1; +} +function attachedBlockExtent(lexer, limit, transform) { + if (limit <= 1) + return limit; + const lines = []; + for (let k = 0; k < limit; k++) { + const line2 = lexer.peek(k); + lines.push(transform ? transform(line2) : line2); + } + const probe = subLexer(lines, lexer.parseOptions, 0); + probe.nested = true; + probe.suppressPositions = true; + probe.depth = lexer.depth + 1; + const matchers = activeMatchers; + activeMatchers = []; + try { + for (; ; ) { + while (!probe.eof() && tryCollectBlockAttributes(probe) !== null) { + } + if (probe.eof()) + return limit; + const node = parseBlock(probe); + const invisible = node === null || node.type === "abbreviation_def" || node.type === "comment"; + if (!invisible || probe.eof()) + break; + } + } finally { + activeMatchers = matchers; + } + return Math.min(Math.max(probe.pos, 1), limit); +} +function collectAttachedBlock(lexer, isBoundary, transform) { + const fenced = fencedBlockEnd({ + at: (offset) => { + const line2 = lexer.peek(offset); + return line2 === void 0 ? void 0 : transform ? transform(line2) : line2; + }, + index: closerIndex(lexer), + base: lexer.pos + }); + let take = 0; + if (fenced !== -1) { + take = fenced + 1; + } else { + while (lexer.peek(take) !== void 0 && !isBoundary(lexer.peek(take))) + take++; + const measured = attachedBlockExtent(lexer, take, transform); + if (measured < take) + take = measured; + } + const startLineIndex = lexer.pos; + const lines = []; + const lineNumbers = []; + for (let k = 0; k < take; k++) { + const raw = lexer.peek(); + lines.push(transform ? transform(raw) : raw); + lineNumbers.push(lexer.lineNumber(lexer.pos)); + lexer.consume(); + } + return { lines, lineNumbers, startLineIndex }; +} +function isBlockAttributeLine(content) { + if (!content.startsWith("{") || !content.includes("}")) + return false; + return parseBlockAttributeRun(content) !== null; +} +function prefixWalkBound(content) { + const nl = content.indexOf("\n"); + return nl === -1 ? content.length : nl + 1; +} +function quotePrefixLength(content, from, bound) { + const window = content.slice(from, Math.min(from + PREFIX_WINDOW, bound)); + const quoted = RE_BLOCKQUOTE.exec(window); + if (!quoted) + return 0; + return window.length - (quoted[1]?.length ?? 0); +} +function markerPrefixLength(content, from, bound) { + for (let width2 = PREFIX_WINDOW; ; width2 *= 2) { + const end = Math.min(from + width2, bound); + const window = content.slice(from, end); + const marked = extractItemAttr(window)?.stripped ?? window; + const item2 = RE_TASK.exec(marked) ?? RE_ORDERED.exec(marked) ?? RE_UNORDERED.exec(marked); + if (item2) + return window.length - item2[item2.length - 1].length; + if (end === bound) + return 0; + } +} +function walkContainerPrefix(content) { + const bound = prefixWalkBound(content); + let at = 0; + for (; ; ) { + const quote = quotePrefixLength(content, at, bound); + if (quote > 0) { + at += quote; + continue; + } + const marker = markerPrefixLength(content, at, bound); + if (marker === 0) + return at; + at += marker; + } +} +function markerLineQuoteState(content) { + const quoted = RE_BLOCKQUOTE.exec(content); + if (!quoted) + return null; + const inner = { + mode: { kind: "closed" }, + inTable: false, + colonWidths: [], + attrRun: null + }; + trackBlockQuoteLazyState(quoted[1] ?? "", inner, () => true, () => true); + return inner; +} +function markerLineBottomBlock(content) { + const walked = walkContainerPrefix(content); + return walked === 0 ? content : content.slice(walked); +} +function markerLineState(content) { + const bottom = markerLineBottomBlock(content); + const quote = markerLineQuoteState(content); + return { + leavesParagraphOpen: bottomBlockLeavesParagraphOpen(bottom), + endsOnTableRow: quote === null && isTableRow(bottom), + quote + }; +} +function bottomBlockLeavesParagraphOpen(rest) { + if (isBlankLine(rest) || trimStructural(rest) === "") + return false; + if (rest.startsWith(" ") || rest.startsWith(" ")) + return true; + if (RE_HEADING.test(rest)) + return false; + if (RE_HR.test(rest)) + return false; + if (isTableRow(rest)) + return false; + if (RE_COMMENT_LINE.test(rest)) + return false; + if (RE_FOOTNOTE_DEF.test(rest) || isLinkDefLine(rest)) + return false; + if (isBlockAttributeLine(rest)) + return false; + return true; +} +function opensWrappedAttributeBlock(content) { + return content.startsWith("{") && !content.includes("}"); +} +function continueWrappedAttributeBlock(collected, content) { + if (isBlankLine(content)) + return { run: "", verdict: "text" }; + const run = `${collected} +${content}`; + if (!content.includes("}")) + return { run, verdict: "open" }; + return { run: "", verdict: parseBlockAttributeRun(run) !== null ? "attributes" : "text" }; +} +function trackWrappedAttributeRun(state, content) { + if (state.attrRun !== null) { + const { run, verdict } = continueWrappedAttributeBlock(state.attrRun, content); + state.attrRun = verdict === "open" ? run : null; + return verdict === "attributes"; + } + if (opensWrappedAttributeBlock(content)) + state.attrRun = content; + return false; +} +function trackItemLazyState(content, state, hasFenceCloser = () => true, atContentColumn = true) { + const wasAbsorbing = state.absorbingFence; + state.absorbingFence = false; + const wasInTable = state.inTable; + state.inTable = false; + const wasQuote = state.quoteInner; + state.quoteInner = null; + const wasInvisibleAtColumn = state.invisibleAtColumn; + state.invisibleAtColumn = false; + if (state.inFootnoteBody && !isBlankLine(content) && indentColumns(content, FOOTNOTE_BODY_COLUMN) < FOOTNOTE_BODY_COLUMN) { + state.inFootnoteBody = false; + } + if (state.inFootnoteBody) { + state.invisibleAtColumn = wasInvisibleAtColumn; + state.lazyFoldable = false; + state.inDefList = false; + return; + } + if (state.inComment) { + const run = commentFenceRun(content); + if (run === state.commentLen) { + state.inComment = false; + state.lazyFoldable = state.lazyFoldableBeforeComment && !state.openedCommentAtColumn; + state.invisibleAtColumn = state.openedCommentAtColumn; + } else { + state.lazyFoldable = false; + } + state.inDefList = false; + return; + } + if (state.inFence) { + if (state.fenceClose.test(content)) + state.inFence = false; + state.lazyFoldable = false; + state.inDefList = false; + return; + } + if (trackWrappedAttributeRun(state, content)) { + state.lazyFoldable = false; + state.inDefList = false; + return; + } + if (isBlankLine(content)) { + state.lazyFoldable = false; + state.absorbingFence = false; + return; } if (RE_DEFLIST_TERM.test(content) || RE_DEFLIST_DEF.test(content)) { state.inDefList = true; @@ -10584,46 +11842,108 @@ function trackItemLazyState(content, state) { return; } const fence = RE_FENCE.exec(content); - if (fence) { - const marker = fence[2]; + const raw = fence ? null : RE_RAW_FENCE.exec(content); + const fenceMarker = fence ? fence[2] : raw ? raw[1] : null; + if (fenceMarker !== null && (!state.lazyFoldable || hasFenceCloser(fenceMarker))) { state.inFence = true; - state.fenceClose = new RegExp(`^${marker[0]}{${marker.length},}\\s*$`); + state.fenceClose = fenceCloseRe(fenceMarker); state.lazyFoldable = false; state.inDefList = false; return; } - const raw = RE_RAW_FENCE.exec(content); - if (raw) { - const marker = raw[1]; - state.inFence = true; - state.fenceClose = new RegExp(`^${marker[0]}{${marker.length},}\\s*$`); - state.lazyFoldable = false; + if (fenceMarker !== null) { + state.lazyFoldable = true; state.inDefList = false; return; } - const comment = /^(%{3,})\s*$/.exec(content); - if (comment) { + const commentRun = commentFenceRun(content); + if (commentRun !== void 0) { state.inComment = true; - state.commentLen = comment[1].length; + state.commentLen = commentRun; + state.lazyFoldableBeforeComment = state.lazyFoldable; + state.openedCommentAtColumn = atContentColumn; state.lazyFoldable = false; state.inDefList = false; return; } - if (isTableRow(content) || RE_HEADING.test(content) || RE_HR.test(content)) { + if (RE_HEADING.test(content)) { state.lazyFoldable = false; state.inDefList = false; return; } - if (RE_BLOCKQUOTE.test(content)) { - state.lazyFoldable = true; + if (isTableRow(content) || RE_HR.test(content)) { + state.inTable = isTableRow(content); + state.lazyFoldable = false; + state.inDefList = false; + return; + } + if (wasInTable && RE_TABLE_CONT.test(content)) { + state.inTable = true; + state.lazyFoldable = false; + state.inDefList = false; + return; + } + if (atContentColumn && RE_INVISIBLE_BLOCK_LEAD.test(content) && (RE_COMMENT_LINE.test(content) || RE_FOOTNOTE_DEF.test(content) || isLinkDefLine(content))) { + state.inFootnoteBody = RE_FOOTNOTE_DEF.test(content); + state.invisibleAtColumn = true; + state.lazyFoldable = false; + state.inDefList = false; + return; + } + const quotedLine = RE_BLOCKQUOTE.exec(content); + if (quotedLine) { + const inner = wasQuote ?? { + mode: { kind: "closed" }, + inTable: false, + colonWidths: [], + attrRun: null + }; + trackBlockQuoteLazyState(quotedLine[1] ?? "", inner, () => true, () => true); + state.quoteInner = inner; + state.lazyFoldable = blockQuoteParagraphOpen(inner); + state.inDefList = false; + return; + } + if (isBlockAttributeLine(content)) { + state.lazyFoldable = false; + state.inDefList = false; + return; + } + const bareFence = /^:{3,}[ \t]*$/.test(content); + if (bareFence && state.divDepth > 0) { + state.divDepth--; + state.lazyFoldable = false; state.inDefList = false; return; } if (RE_DIV_OPEN.test(content) || RE_ADMONITION_OPEN.test(content) && !RE_ADMONITION_CLOSE.test(content) || RE_LINE_BLOCK_OPEN.test(content) || RE_HARDBREAKS_OPEN.test(content)) { + if (wasAbsorbing && bareFence) { + state.absorbingFence = true; + state.lazyFoldable = true; + return; + } + state.divDepth++; state.lazyFoldable = false; state.inDefList = false; return; } + if (/^:{3,}/.test(content)) { + state.absorbingFence = state.divDepth === 0; + state.lazyFoldable = true; + state.inDefList = false; + return; + } + const nestedMarker = extractItemAttr(content)?.stripped ?? content; + if (RE_TASK.test(nestedMarker) || RE_ORDERED.test(nestedMarker) || RE_UNORDERED.test(nestedMarker)) { + state.absorbingFence = false; + const nested = markerLineState(content); + state.lazyFoldable = nested.leavesParagraphOpen; + state.inTable = nested.endsOnTableRow; + state.quoteInner = nested.quote; + state.inDefList = false; + return; + } + state.absorbingFence = wasAbsorbing; state.lazyFoldable = true; } function parseList(lexer) { @@ -10642,27 +11962,40 @@ function parseList(lexer) { let k = 1; for (; lexer.peek(k) !== void 0; k++) { const ln = lexer.peek(k); - if (!isBlankLine(ln) && indentColumns(ln) <= baseIndent) + if (!isBlankLine(ln) && indentColumns(ln, baseIndent + 1) <= baseIndent) break; } const nextLine = lexer.peek(k); const nextStripped = nextLine !== void 0 ? extractItemAttr(nextLine)?.stripped ?? nextLine : void 0; - const nm = nextStripped !== void 0 && indentColumns(nextLine) === baseIndent ? RE_ORDERED.exec(nextStripped) : null; + const nm = nextStripped !== void 0 && indentColumns(nextLine, baseIndent + 1) === baseIndent ? RE_ORDERED.exec(nextStripped) : null; orderedKind = olKindOf(firstOrdered[2], nm ? nm[2] : null); orderedStart = olStartOf(firstOrdered[2], orderedKind); } const items = []; let loose = false; + const isItemAttachBoundary = (a) => { + if (isBlankLine(a)) + return true; + const ind = indentColumns(a, baseIndent + 1); + if (ind < baseIndent) + return true; + if (ind !== baseIndent) + return false; + const am = matchListMarker(a, isTask, isOrdered); + const sibling = am && (isOrdered ? orderedContinues(a, orderedKind, orderedDelim) : unorderedMarkerChar(a) === firstMarkerChar); + const anyMarker = RE_ORDERED.test(a) || RE_UNORDERED.test(a) || RE_TASK.test(a) || extractItemAttr(a) !== null; + return Boolean(sibling) || anyMarker || isContinuationMarker(a); + }; while (!lexer.eof()) { const itemStartLineIndex = lexer.pos; - const line = lexer.peek(); - if (isBlankLine(line)) { + const line2 = lexer.peek(); + if (isBlankLine(line2)) { break; } - if (indentColumns(line) !== baseIndent) + if (indentColumns(line2, baseIndent + 1) !== baseIndent) break; - const la = extractItemAttr(line); - const mline = la ? la.stripped : line; + const la = extractItemAttr(line2); + const mline = la ? la.stripped : line2; const m = matchListMarker(mline, isTask, isOrdered); if (!m) break; @@ -10681,33 +12014,22 @@ function parseList(lexer) { content = m[2]; } const itemAttrs = la ? la.attrs : void 0; - const contentCol = isTask ? baseIndent + 2 + (la ? line.length - mline.length : 0) : baseIndent + (line.length - leadingWhitespace(line) - content.length); + const contentCol = isTask ? baseIndent + 2 + (la ? line2.length - mline.length : 0) : baseIndent + (line2.length - leadingWhitespace(line2) - content.length); lexer.consume(); - if (trimStructural(content) === "+") { - const attached = []; - const attachedLineNumbers = []; - let attachedStartLineIndex = lexer.pos; - while (!lexer.eof()) { - const a = lexer.peek(); - if (isBlankLine(a)) - break; - const ind = indentColumns(a); - if (ind < baseIndent) - break; - if (ind === baseIndent) { - const am = matchListMarker(a, isTask, isOrdered); - const sibling = am && (isOrdered ? orderedContinues(a, orderedKind, orderedDelim) : unorderedMarkerChar(a) === firstMarkerChar); - const anyMarker = RE_ORDERED.test(a) || RE_UNORDERED.test(a) || RE_TASK.test(a) || extractItemAttr(a) !== null; - if (sibling || anyMarker || trimStructural(a) === "+") - break; - } - if (attached.length === 0) - attachedStartLineIndex = lexer.pos; - attached.push(sliceColumns(a, baseIndent)); - attachedLineNumbers.push(lexer.lineNumber(lexer.pos)); + if (isContinuationMarker(content)) { + const { lines: attached, lineNumbers: attachedLineNumbers, startLineIndex: attachedStartLineIndex } = collectAttachedBlock(lexer, isItemAttachBoundary, (a) => sliceColumns(a, baseIndent)); + while (!lexer.eof() && isContinuationMarker(lexer.peek())) { + const plusLineIndex = lexer.pos; lexer.consume(); + const more = collectAttachedBlock(lexer, isItemAttachBoundary, (a) => sliceColumns(a, baseIndent)); + if (more.lines.length === 0) + break; + attached.push(""); + attachedLineNumbers.push(lexer.lineNumber(plusLineIndex)); + attached.push(...more.lines); + attachedLineNumbers.push(...more.lineNumbers); } - const sub = nestedSubLexer(lexer, attached.join("\n"), attachedStartLineIndex, attachedLineNumbers); + const sub = nestedSubLexer(lexer, attached, attachedStartLineIndex, attachedLineNumbers); const fbChildren = parseBlocks(sub, 0); const fbItem = { type: "list_item", children: fbChildren }; attachBlockPos(lexer, fbItem, itemStartLineIndex, lexer.pos); @@ -10721,17 +12043,46 @@ function parseList(lexer) { const nested = []; const nestedLineNumbers = []; let firstBlockIdx = -1; + let bodyHasContentColumnLine = false; let pendingBlanks = 0; let pendingBlankLineNumbers = []; const plusSeparators = /* @__PURE__ */ new Set(); + const leadState = markerLineState(content); const lazyState = { inFence: false, fenceClose: null, inComment: false, commentLen: 0, - lazyFoldable: !isBlankLine(content), - inDefList: RE_DEFLIST_TERM.test(content) || RE_DEFLIST_DEF.test(content) + lazyFoldableBeforeComment: false, + openedCommentAtColumn: false, + invisibleAtColumn: false, + inFootnoteBody: false, + absorbingFence: false, + divDepth: 0, + // The lead text opens a paragraph unless it is one of the shapes that + // open nothing - PART 1 S4's one question, asked of the block the marker + // line holds. See `markerLineState`. + lazyFoldable: leadState.leavesParagraphOpen, + inTable: leadState.endsOnTableRow, + quoteInner: leadState.quote, + inDefList: RE_DEFLIST_TERM.test(content) || RE_DEFLIST_DEF.test(content), + attrRun: null }; + const itemFenceMemo = /* @__PURE__ */ new Map(); + const leadFence = RE_FENCE.exec(content) ?? RE_RAW_FENCE.exec(content); + if (leadFence) { + lazyState.inFence = true; + lazyState.fenceClose = fenceCloseRe(RE_FENCE.test(content) ? leadFence[2] : leadFence[1]); + lazyState.lazyFoldable = false; + } + const leadComment = leadFence ? void 0 : commentFenceRun(content); + if (leadComment !== void 0) { + lazyState.inComment = true; + lazyState.commentLen = leadComment; + lazyState.lazyFoldableBeforeComment = lazyState.lazyFoldable; + lazyState.lazyFoldable = false; + } + lazyState.absorbingFence = /^:{3,}/.test(content) && !RE_DIV_OPEN.test(content) && !RE_ADMONITION_OPEN.test(content) && !RE_LINE_BLOCK_OPEN.test(content) && !RE_HARDBREAKS_OPEN.test(content); while (!lexer.eof()) { const l = lexer.peek(); if (isBlankLine(l)) { @@ -10740,7 +12091,7 @@ function parseList(lexer) { lexer.consume(); continue; } - if (indentColumns(l) === baseIndent && trimStructural(l) === "+") { + if (indentColumns(l, baseIndent + 1) === baseIndent && isContinuationMarker(l)) { const plusLineNumber = lexer.lineNumber(lexer.pos); lexer.consume(); pendingBlanks = 0; @@ -10749,30 +12100,17 @@ function parseList(lexer) { nested.push(""); nestedLineNumbers.push(plusLineNumber); trackItemLazyState("", lazyState); - while (!lexer.eof()) { - const a = lexer.peek(); - if (isBlankLine(a)) - break; - const ind = indentColumns(a); - if (ind < baseIndent) - break; - if (ind === baseIndent) { - const am = matchListMarker(a, isTask, isOrdered); - const sibling = am && (isOrdered ? orderedContinues(a, orderedKind, orderedDelim) : unorderedMarkerChar(a) === firstMarkerChar); - const anyMarker = RE_ORDERED.test(a) || RE_UNORDERED.test(a) || RE_TASK.test(a) || extractItemAttr(a) !== null; - if (sibling || anyMarker || trimStructural(a) === "+") - break; - } - const attached = sliceColumns(a, baseIndent); - nested.push(attached); - nestedLineNumbers.push(lexer.lineNumber(lexer.pos)); - trackItemLazyState(attached, lazyState); - lexer.consume(); + const { lines: attachedLines, lineNumbers: attachedLineNumbers } = collectAttachedBlock(lexer, isItemAttachBoundary, (a) => sliceColumns(a, baseIndent)); + for (let k = 0; k < attachedLines.length; k++) { + nested.push(attachedLines[k]); + nestedLineNumbers.push(attachedLineNumbers[k]); + trackItemLazyState(attachedLines[k], lazyState); } continue; } - const lw = indentColumns(l); + const lw = indentColumns(l, contentCol); if (lw >= contentCol) { + bodyHasContentColumnLine = true; for (let k = 0; k < pendingBlanks; k++) { nested.push(""); nestedLineNumbers.push(pendingBlankLineNumbers[k]); @@ -10780,18 +12118,19 @@ function parseList(lexer) { } pendingBlanks = 0; pendingBlankLineNumbers = []; - const isMarker = RE_ORDERED.test(l) || RE_UNORDERED.test(l) || RE_TASK.test(l) || // An abutting-attr bullet (`-{.x} item`) is a marker too. It no longer - // reaches here via §10 interruption (bullets do not interrupt), so the - // sub-list nesting path must recognize it directly to keep nesting. - extractItemAttr(l) !== null; + const isMarker = !insideOpenFence(lazyState) && !insideOpenQuoteParagraph(lazyState) && (RE_ORDERED.test(l) || RE_UNORDERED.test(l) || RE_TASK.test(l) || // An abutting-attr bullet (`-{.x} item`) is a marker too. It no + // longer reaches here via §10 interruption (bullets do not + // interrupt), so the sub-list nesting path must recognize it + // directly to keep nesting. + extractItemAttr(l) !== null); if (firstBlockIdx === -1 && isMarker) { firstBlockIdx = nested.length; } - const keepResidual = firstBlockIdx !== -1 && isMarker; - const dedented = sliceColumns(l, contentCol, keepResidual); + const dedented = sliceColumns(l, contentCol, true); nested.push(dedented); nestedLineNumbers.push(lexer.lineNumber(lexer.pos)); - trackItemLazyState(dedented, lazyState); + const fenceLineIndex = lexer.pos; + trackItemLazyState(dedented, lazyState, (marker) => itemFenceHasCloser(lexer, marker, fenceLineIndex, contentCol, itemFenceMemo)); lexer.consume(); } else if (pendingBlanks === 0 && // A dedented (below content-column) plain line only lazily continues an // OPEN paragraph (family-D rule). After a code fence or table -- which @@ -10802,46 +12141,169 @@ function parseList(lexer) { // An UNTERMINATED fence (inFence still open) is NOT a code block -- it is // an inline-verbatim run that is part of the paragraph, so a dedented // line folds into it (matching the §10 closer-lookahead rule). - ((lazyState.lazyFoldable || lazyState.inFence) && !lazyContinuationEndsList(l) || // A list marker indented past the base column but BELOW the content + // `inComment` counts like `inFence`: an UNCLOSED comment fence opens no + // block (§28) and is still a comment, so a below-column line after it is + // part of the paragraph the fence never interrupted. Without this, giving + // the opener its info string (see trackItemLazyState) latched the tracker + // inside a comment that never closes, and the item ended there. + // + // "The paragraph the fence never interrupted" is the whole of that + // reason, so it needs a paragraph to have been open when the fence + // arrived - which `lazyFoldableBeforeComment` is exactly the record of. + // A comment fence written ON THE MARKER LINE interrupts nothing: it IS + // the item's first block, and it takes its body from the content column + // and nowhere else, so a column-0 line below it reaches no container + // (§24 C3) and ends the item, the same answer `- %% c` gives one + // spelling over (PART 1 S4, markup-carve/carve#1280). + ((lazyState.lazyFoldable || lazyState.inComment && lazyState.lazyFoldableBeforeComment || // AN INVISIBLE BLOCK AT THE COLUMN ENDED THE PARAGRAPH, NOT THE ITEM + // (markup-carve/carve#1364). The item goes on collecting, so a line + // still indented belongs to it and starts a paragraph of its own + // there (corpus 197, 277-3, 358). The container ends at document + // column 0, which is the line this test excludes and which is all + // that separates 358 from 357-2. + lazyState.invisibleAtColumn && indentColumns(l, contentCol) > 0) && !lazyContinuationEndsList(l, lexer) || // A list marker indented past the base column but BELOW the content // column folds into the lead text rather than ending the list. Under // symmetric §10 no list marker interrupts a paragraph, so on the // recursive reparse it stays folded: `1. a`/` 1. b`, `- a`/` - b`, // and the abutting-attr form `- a`/` -{.x} b` all fold. (At or past // the content column the marker nests; at the base column it can start // a sibling list, §11 -- so only a below-content indented one folds.) - indentColumns(l) > baseIndent && (RE_TASK.test(l) || RE_UNORDERED.test(l) || RE_ORDERED.test(l) || extractItemAttr(l) !== null))) { + indentColumns(l, baseIndent + 1) > baseIndent && (RE_TASK.test(l) || RE_UNORDERED.test(l) || RE_ORDERED.test(l) || extractItemAttr(l) !== null))) { let lazyLine = l; - if (lazyState.inDefList && indentColumns(l) < contentCol) { + if (lexer.literalLazyLinkDefLines.has(lexer.lineNumber(lexer.pos))) { + lazyLine = l.replace(/^[ \t]+/, ""); + } else if (lazyState.inDefList && indentColumns(l, contentCol) < contentCol) { lazyLine = l.replace(/^[ \t]+/, ""); + } else if (indentColumns(l, contentCol) < contentCol && lineOpensBlock(l.replace(/^[ \t]+/, ""))) { + lazyLine = " " + l.replace(/^[ \t]+/, ""); } nested.push(lazyLine); nestedLineNumbers.push(lexer.lineNumber(lexer.pos)); - trackItemLazyState(lazyLine, lazyState); + trackItemLazyState(lazyLine, lazyState, () => true, false); lexer.consume(); } else { break; } } - if (pendingBlanks > 0 && !lexer.eof()) { + let blankBeforeInvisible = false; + for (let k = nested.length - 1; k >= 0; k--) { + const ln = nested[k]; + if (isBlankLine(ln)) { + blankBeforeInvisible = k < nested.length - 1 && !plusSeparators.has(k); + break; + } + if (!isInvisibleLine(ln)) + break; + } + if (pendingBlanks > 0 && (lazyState.inFence || lazyState.inComment)) { + for (let k = 0; k < pendingBlanks; k++) { + nested.push(""); + nestedLineNumbers.push(pendingBlankLineNumbers[k]); + } + } + if ((pendingBlanks > 0 || blankBeforeInvisible) && !lexer.eof()) { const nextLine = lexer.peek(); const nextStripped = extractItemAttr(nextLine)?.stripped ?? nextLine; - if (indentColumns(nextLine) === baseIndent && matchListMarker(nextStripped, isTask, isOrdered) && (isOrdered ? orderedContinues(nextStripped, orderedKind, orderedDelim) : unorderedMarkerChar(nextStripped) === firstMarkerChar)) { + if (indentColumns(nextLine, baseIndent + 1) === baseIndent && matchListMarker(nextStripped, isTask, isOrdered) && (isOrdered ? orderedContinues(nextStripped, orderedKind, orderedDelim) : unorderedMarkerChar(nextStripped) === firstMarkerChar)) { loose = true; } } + const fenceLines = [content, ...nested]; + const inFence = new Array(fenceLines.length).fill(false); + const closers = buildCloserIndex(fenceLines); + const open = []; + let openIdx = -1; + for (let k = 0; k < fenceLines.length; k++) { + const line3 = fenceLines[k]; + const inner = open[open.length - 1]; + if (inner !== void 0 && inner.kind !== "colon") { + const closed = inner.kind === "code" ? inner.close.test(line3) : commentFenceRun(line3) === inner.len; + if (!closed) + continue; + open.pop(); + if (open.length === 0) { + for (let i = openIdx; i <= k; i++) + inFence[i] = true; + openIdx = -1; + } + continue; + } + if (inner !== void 0) { + const close = RE_ADMONITION_CLOSE.exec(line3); + if (close) { + const len = close[1].length; + if (len === inner.len) { + open.pop(); + if (open.length === 0) { + for (let i = openIdx; i <= k; i++) + inFence[i] = true; + openIdx = -1; + } + } else { + open.push({ kind: "colon", close: null, len }); + } + continue; + } + } + const fence = RE_FENCE.exec(line3); + const rawFence = fence ? null : RE_RAW_FENCE.exec(line3); + const marker = fence ? fence[2] : rawFence ? rawFence[1] : null; + let opened = null; + if (marker !== null) { + if (codeCloserPossible(closers, marker, k)) + opened = { kind: "code", close: fenceCloseRe(marker), len: marker.length }; + } else { + const run = commentFenceRun(line3); + if (run !== void 0) { + if (exactCloserPossible(closers.comment, run, k)) + opened = { kind: "comment", close: null, len: run }; + } else { + const colon = colonBlockOpenerRun(line3); + if (colon !== null && exactCloserPossible(closers.colon, colon, k)) + opened = { kind: "colon", close: null, len: colon }; + } + } + if (opened === null) + continue; + if (open.length === 0) + openIdx = k; + open.push(opened); + } + const inFootnoteRun = new Array(nested.length).fill(false); + for (let k = 0; k < nested.length; k++) { + const line3 = nested[k]; + if (indentColumns(line3, 1) !== 0 || !RE_FOOTNOTE_DEF.test(line3)) + continue; + let last = k; + for (let j = k + 1; j < nested.length; j++) { + const next = nested[j]; + if (next === "") + continue; + if (indentColumns(next, FOOTNOTE_BODY_COLUMN) < FOOTNOTE_BODY_COLUMN) + break; + last = j; + } + for (let j = k + 1; j <= last; j++) + inFootnoteRun[j] = true; + k = last; + } for (let k = 0; k < nested.length; k++) { + if (inFence[k + 1]) + continue; + if (inFootnoteRun[k]) + continue; if (nested[k] !== "") continue; if (plusSeparators.has(k)) continue; let j = k + 1; - while (j < nested.length && nested[j] === "") + while (j < nested.length && (nested[j] === "" || isInvisibleLine(nested[j]))) j++; if (j >= nested.length) continue; if (firstBlockIdx !== -1) { const subCol = markerContentColumn(nested[firstBlockIdx]); - if (subCol >= 0 && indentColumns(nested[j]) >= subCol) + if (subCol >= 0 && indentColumns(nested[j], subCol) >= subCol) continue; } if (!lineOpensBlock(nested[j])) { @@ -10855,31 +12317,40 @@ function parseList(lexer) { // merges/absorbs like the plain one. extractItemAttr(content) !== null; const leadOpensColonFence = RE_ADMONITION_OPEN.test(content) && !RE_ADMONITION_CLOSE.test(content) || RE_DIV_OPEN.test(content); - const colonFenceLen = leadOpensColonFence ? /^(:{3,})/.exec(content)[1].length : 0; - const colonFenceHasBodyCloser = leadOpensColonFence && nested.some((ln) => { - const c = RE_ADMONITION_CLOSE.exec(ln); - return c !== null && c[1].length >= colonFenceLen; - }); - const keepStreamWhole = firstBlockIdx === -1 || leadIsMarker || colonFenceHasBodyCloser; + const literalBelowColumnColonFence = leadOpensColonFence && nested.length > 0 && !bodyHasContentColumnLine; + const itemLead = literalBelowColumnColonFence ? ` ${content}` : content; + const keepStreamWhole = firstBlockIdx === -1 || leadIsMarker || leadOpensColonFence && !literalBelowColumnColonFence; const leadLines = keepStreamWhole ? nested : nested.slice(0, firstBlockIdx); const blockLines = keepStreamWhole ? [] : nested.slice(firstBlockIdx); - const mkSub = (text, startLineIndex, sourceLineMap) => { - return nestedSubLexer(lexer, text, startLineIndex, sourceLineMap); + const mkSub = (lines, startLineIndex, sourceLineMap) => { + return nestedSubLexer(lexer, lines, startLineIndex, sourceLineMap); }; - const children = parseBlocks(mkSub([content, ...leadLines].join("\n"), itemStartLineIndex, [ + const carry = { attrs: null }; + const children = parseBlocks(mkSub([itemLead, ...leadLines], itemStartLineIndex, [ lexer.lineNumber(itemStartLineIndex), ...nestedLineNumbers.slice(0, leadLines.length) - ]), 0); + ]), 0, blockLines.length > 0 ? carry : void 0); if (blockLines.length > 0) { - children.push(...parseBlocks(mkSub(blockLines.join("\n"), itemStartLineIndex + 1 + firstBlockIdx, nestedLineNumbers.slice(firstBlockIdx)), 0)); + children.push(...parseBlocks(mkSub(blockLines, itemStartLineIndex + 1 + firstBlockIdx, nestedLineNumbers.slice(firstBlockIdx)), 0, carry)); + } + const item2 = { type: "list_item", children }; + let itemEnd = lexer.pos; + while (itemEnd > itemStartLineIndex + 1 && isBlankLine(lexer.lines[itemEnd - 1])) + itemEnd--; + attachBlockPos(lexer, item2, itemStartLineIndex, itemEnd); + const lastOwned = [...children].reverse().find((child) => child.pos !== void 0)?.pos; + if (item2.pos && lastOwned) { + item2.pos.endLine = lastOwned.endLine; + if (lastOwned.endColumn !== void 0) + item2.pos.endColumn = lastOwned.endColumn; + if (lastOwned.endOffset !== void 0) + item2.pos.endOffset = lastOwned.endOffset; } - const item = { type: "list_item", children }; - attachBlockPos(lexer, item, itemStartLineIndex, lexer.pos); if (checked !== void 0) - item.checked = checked; + item2.checked = checked; if (itemAttrs) - item.attrs = itemAttrs; - items.push(item); + item2.attrs = itemAttrs; + items.push(item2); } const list = { type: "list", ordered: isOrdered, tight: !loose, items }; if (isOrdered) { @@ -10890,22 +12361,26 @@ function parseList(lexer) { list.olType = t; if (orderedDelim === "." || orderedDelim === ")") list.delim = orderedDelim; + if (firstOrdered && firstOrdered[2] === "") + list.bareMarker = true; } else if (firstMarkerChar === "-" || firstMarkerChar === "*") { list.bulletChar = firstMarkerChar; } return list; } +function readCellAttributeBlock(src, from = 0) { + if (src[from] !== "{") + return void 0; + const m = RE_INLINE_ATTR.exec(src.slice(from)); + if (!m || !isValidInlineAttrPayload(m[1])) + return void 0; + const attrs = parseAttrs(m[1]); + if (isEmptyAttrs(attrs)) + return void 0; + return { attrs, length: m[0].length }; +} function parseCellMarkers(src) { - if (src[0] === "{") { - const m = RE_INLINE_ATTR.exec(src); - if (m && isValidAttrPayload(m[1])) { - const attrs = parseAttrs(m[1]); - if (!isEmptyAttrs(attrs)) { - return { header: false, attrs, content: trimStructural(src.slice(m[0].length)) }; - } - } - } - if (trimStructural(src) === "<") + if (trimCellPadding(src) === "<") return { header: false, span: "colspan", content: "" }; let i = 0; let header = false; @@ -10913,99 +12388,212 @@ function parseCellMarkers(src) { header = true; i++; } + const markerStart = i; let align; - const a = src[i]; - if (a === ">") { - align = "right"; - i++; - } else if (a === "<") { - align = "left"; - i++; - } else if (a === "~") { - align = "center"; + let valign; + let invalidAxis = false; + while (src[i] !== void 0 && "<>~^v".includes(src[i])) { + const marker = src[i]; + if (marker === "<" || marker === ">" || marker === "~") { + if (align === void 0) { + if (marker === "~" && valign === void 0 && (src[i + 1] === "<" || src[i + 1] === ">")) { + valign = "middle"; + } else { + align = marker === "<" ? "left" : marker === ">" ? "right" : "center"; + } + } else if (marker === "~" && valign === void 0) { + valign = "middle"; + } else { + invalidAxis = true; + break; + } + } else { + if (valign !== void 0) { + invalidAxis = true; + break; + } + valign = marker === "^" ? "top" : "bottom"; + } i++; } - if (i > 0) { - const content = trimStructural(src.slice(i)); - return align ? { header, align, content } : { header, content }; + const validRun = i > markerStart && !invalidAxis && (/\s/.test(src[i] ?? "") || src[i] === "{" || src[i] !== void 0 && "<>~^v".includes(src[i])); + if (!validRun) { + i = markerStart; + align = void 0; + valign = void 0; } - const trimmed = trimStructural(src); + const block = readCellAttributeBlock(src, i); + const attrs = block?.attrs; + if (block) + i += block.length; + if (i > 0) { + const content = trimCellPadding(src.slice(i)); + if ((align !== void 0 || valign !== void 0) && attrs !== void 0) + return { header, ...align ? { align } : {}, ...valign ? { valign } : {}, attrs, content }; + if (align !== void 0 || valign !== void 0) + return { header, ...align ? { align } : {}, ...valign ? { valign } : {}, content }; + if (attrs !== void 0) + return { header, attrs, content }; + return { header, content }; + } + const trimmed = trimCellPadding(src); if (trimmed === "^") return { header: false, span: "rowspan", content: "" }; return { header: false, content: trimmed }; } -var isGfmDelimiterCell = (c) => !c.span && !c.attrs && /^:?-+:?$/.test(trimStructural(c.raw)); -var isGfmDelimiterRow = (row) => row.length > 0 && row.every(isGfmDelimiterCell); -function rowAttrsFromLine(line) { - const stripped = line.replace(/[ \t]+$/, ""); +function rowAttrsFromLine(line2) { + const stripped = line2.replace(/[ \t]+$/, ""); const lastPipe = stripped.lastIndexOf("|"); if (lastPipe < 0 || stripped[lastPipe + 1] !== "{") - return { body: line }; + return { body: line2 }; const after = stripped.slice(lastPipe + 1); const m = RE_INLINE_ATTR.exec(after); - if (m && m[0].length === after.length && isValidAttrPayload(m[1])) { + if (m && m[0].length === after.length && isValidInlineAttrPayload(m[1])) { const attrs = parseAttrs(m[1]); if (!isEmptyAttrs(attrs)) return { attrs, body: stripped.slice(0, lastPipe + 1) }; } - return { body: line }; + return { body: line2 }; +} +function openVerbatimRun(text, from = 0) { + let openRun = from; + for (let i = 0; i < text.length; i++) { + if (openRun === 0 && text[i] === "\\") { + i++; + continue; + } + if (text[i] !== "`") + continue; + let run = 1; + while (text[i + run] === "`") + run++; + if (openRun === 0) + openRun = run; + else if (run === openRun) + openRun = 0; + i += run - 1; + } + return openRun; } function parseTable(lexer) { const rawRows = []; const rowAttrsList = []; + const rowStarts = []; + const rowEnds = []; let lastRaw = null; while (!lexer.eof() && (isTableRow(lexer.peek()) || RE_TABLE_CONT.test(lexer.peek()))) { - const line = lexer.peek(); - if (RE_TABLE_CONT.test(line)) { + const line2 = lexer.peek(); + const lineIndex = lexer.pos; + if (RE_TABLE_CONT.test(line2)) { if (!lastRaw) break; if (rawRows.length === 2 && rawRows[1] === lastRaw && isGfmDelimiterRow(lastRaw) && !isGfmDelimiterRow(rawRows[0])) break; lexer.consume(); - splitTableRow(line).forEach((src, idx) => { - const frag = trimStructural(src); + rowEnds[rawRows.length - 1] = { + line: lexer.lineNumber(lineIndex), + column: lexer.lineStartColumn(lineIndex) + line2.length, + offset: lexer.lineOffset(lineIndex) + line2.length + }; + const contOffset = lexer.lineOffset(lineIndex); + const contLine = lexer.lineNumber(lineIndex); + const contColumn = lexer.lineStartColumn(lineIndex); + const contCanPosition = lexer.hasDocumentOffsets; + splitTableRowSpans(line2, lastRaw.map((c) => c.openRun)).forEach(({ text: src, start }, idx) => { + const frag = trimCellPadding(src); const target = lastRaw[idx]; if (!frag || !target || target.span) return; + const fragStart = target.raw ? target.raw.length + 1 : 0; target.raw = target.raw ? `${target.raw} ${frag}` : frag; + target.openRun = openVerbatimRun(frag, target.openRun); + delete target.pos; + const within = contCanPosition ? src.indexOf(frag) : -1; + if (within >= 0 && line2.slice(start + within, start + within + frag.length) === frag) { + const range = { + from: fragStart, + to: fragStart + frag.length, + offset: contOffset + start + within, + line: contLine, + column: contColumn + start + within + }; + if (target.anchors) + target.anchors.push(range); + else + target.anchors = [range]; + } }); continue; } lexer.consume(); - const { attrs: rowAttrs, body: rowBody } = rowAttrsFromLine(line); - const raw = splitTableRow(rowBody).map((src) => { - const { header, span, align, attrs, content } = parseCellMarkers(src); - const c = { header, raw: content }; - if (span) - c.span = span; + const { attrs: rowAttrs, body: rowBody } = rowAttrsFromLine(line2); + const canPosition = lexer.hasDocumentOffsets; + const lineOffset = lexer.lineOffset(lineIndex); + const lineNo = lexer.lineNumber(lineIndex); + const lineCol = lexer.lineStartColumn(lineIndex); + const raw = splitTableRowSpans(rowBody).map(({ text: src, start }) => { + const { header, span: span2, align, valign, attrs, content } = parseCellMarkers(src); + const c = { header, raw: content, openRun: openVerbatimRun(content) }; + if (span2) + c.span = span2; if (align) c.align = align; + if (valign) + c.valign = valign; if (attrs) c.attrs = attrs; + if (canPosition) { + c.pos = { + startLine: lineNo, + endLine: lineNo, + startColumn: lineCol + start, + endColumn: lineCol + start + src.length, + startOffset: lineOffset + start, + endOffset: lineOffset + start + src.length + }; + } + const within = content === "" || !canPosition ? -1 : src.indexOf(content); + if (within >= 0 && rowBody.slice(start + within, start + within + content.length) === content) { + c.anchors = [ + { + from: 0, + to: content.length, + offset: lineOffset + start + within, + line: lineNo, + column: lineCol + start + within + } + ]; + } return c; }); rawRows.push(raw); rowAttrsList.push(rowAttrs); + rowStarts[rawRows.length - 1] = canPosition ? { line: lineNo, column: lineCol, offset: lineOffset } : void 0; + rowEnds[rawRows.length - 1] = canPosition ? { + line: lineNo, + column: lineCol + line2.length, + offset: lineOffset + line2.length + } : void 0; lastRaw = raw; } if (rawRows.length >= 2 && isGfmDelimiterRow(rawRows[1]) && !isGfmDelimiterRow(rawRows[0])) { const aligns = rawRows[1].map((c) => { - const t = trimStructural(c.raw); + const t = trimCellPadding(c.raw); const left = t.startsWith(":"); const right = t.endsWith(":"); return left && right ? "center" : right ? "right" : left ? "left" : void 0; }); rawRows.splice(1, 1); rowAttrsList.splice(1, 1); + rowStarts.splice(1, 1); + rowEnds.splice(1, 1); for (const c of rawRows[0]) c.header = true; - for (const rc of rawRows) { - rc.forEach((c, i) => { - const a = aligns[i]; - if (a && !c.align) - c.align = a; - }); - } + rawRows[0].forEach((c, i) => { + const a = aligns[i]; + if (a && !c.align) + c.align = a; + }); } const rows = rawRows.map((rc, idx) => { const row = { @@ -11014,17 +12602,60 @@ function parseTable(lexer) { const cell = { type: "table_cell", header: c.header, - children: c.span ? [] : parseInline(c.raw, lexer.abbrDefs, lexer.linkDefs) + children: c.span ? [] : c.anchors?.length ? parseInline(c.raw, lexer.abbrDefs, lexer.linkDefs, inlineSource({ + baseOffset: c.anchors[0].offset, + startLine: c.anchors[0].line, + startColumn: c.anchors[0].column, + anchoredRanges: c.anchors + })) : stripPositions(parseInline(c.raw, lexer.abbrDefs, lexer.linkDefs)) }; if (c.span) cell.span = c.span; if (c.align) cell.align = c.align; + if (c.valign) + cell.valign = c.valign; if (c.attrs) cell.attrs = c.attrs; + if (c.pos) + cell.pos = c.pos; return cell; }) }; + const spans = rc.map((c) => c.pos); + const end = rowEnds[idx]; + if (end) { + const first = rowStarts[idx] ?? spans.find(Boolean); + const startLine = "startLine" in (first ?? {}) ? first.startLine : void 0; + const rowStart = first ? "line" in first ? { line: first.line, column: first.column, offset: first.offset } : { + line: startLine, + column: first.startColumn, + offset: first.startOffset + } : void 0; + if (rowStart) { + row.pos = { + startLine: rowStart.line, + endLine: end.line, + startColumn: rowStart.column, + endColumn: end.column, + startOffset: rowStart.offset, + endOffset: end.offset + }; + } + } else { + const first = spans[0]; + const last = spans[spans.length - 1]; + if (first && last && spans.every(Boolean) && first.startColumn !== void 0 && last.endColumn !== void 0 && first.startOffset !== void 0 && last.endOffset !== void 0) { + row.pos = { + startLine: first.startLine, + endLine: last.endLine, + startColumn: first.startColumn, + endColumn: last.endColumn, + startOffset: first.startOffset, + endOffset: last.endOffset + }; + } + } const ra = rowAttrsList[idx]; if (ra) row.attrs = ra; @@ -11040,57 +12671,78 @@ function parseTable(lexer) { if (cap && lookahead <= 1) { for (let i = 0; i <= lookahead; i++) lexer.consume(); - table.caption = parseInline(readCaptionText(lexer, cap[1]), lexer.abbrDefs, lexer.linkDefs, void 0, true); + table.caption = parseCaptionInline(lexer, cap[1]); } } return table; } -function splitTableRow(line) { +function splitTableRowSpans(line2, carried) { const cells = []; let buf = ""; - let inCode = false; + let cellIndex = 0; + let openRun = carried?.[0] ?? 0; let i = 0; - if (line[0] === "|" || line[0] === "+") + if (line2[0] === "|" || line2[0] === "+") i = 1; - for (; i < line.length; i++) { - const ch = line[i]; - if (ch === "`") - inCode = !inCode; - if (ch === "\\" && line[i + 1] === "|") { - buf += "|"; + let cellStart = i; + const bodyEnd = line2.replace(/[ \t]+$/, "").length; + const scanEnd = bodyEnd > i && line2[bodyEnd - 1] === "|" ? bodyEnd - 1 : line2.length; + for (; i < scanEnd; i++) { + const ch = line2[i]; + if (ch === "`") { + let run = 1; + while (line2[i + run] === "`") + run++; + if (openRun === 0) + openRun = run; + else if (run === openRun) + openRun = 0; + buf += line2.slice(i, i + run); + i += run - 1; + continue; + } + if (ch === "\\" && line2[i + 1] === "|") { + buf += "\\|"; i++; continue; } - if (ch === "|" && !inCode) { - cells.push(buf); + if (ch === "|" && openRun === 0) { + cells.push({ text: buf, start: cellStart }); buf = ""; + cellStart = i + 1; + cellIndex++; + openRun = carried?.[cellIndex] ?? 0; continue; } buf += ch; } - if (trimStructural(buf) !== "") - cells.push(buf); + if (scanEnd < line2.length || trimStructural(buf) !== "") + cells.push({ text: buf, start: cellStart }); return cells; } +function splitTableRow(line2) { + return splitTableRowSpans(line2).map((cell) => cell.text); +} function fenceHasCloser(lexer, marker) { + const char = marker[0]; const start = lexer.pos + 1; - if (start >= lexer.noFenceCloserFrom) + if (fenceCloserMemoRefutes(lexer.fenceCloserMemo, char, marker.length, start)) return false; - const closeRe = new RegExp(`^${marker[0]}{${marker.length},}\\s*$`); - let sawAnyCloser = false; + const closeRe = fenceCloseRe(marker); + let maxRun = 0; for (let i = start; i < lexer.lines.length; i++) { const l = lexer.lines[i]; if (closeRe.test(l)) return true; - if (RE_FENCE_CLOSER.test(l)) - sawAnyCloser = true; + const closer = RE_FENCE_CLOSER.exec(l); + if (closer && closer[1][0] === char) + maxRun = Math.max(maxRun, closer[1].length); } - if (!sawAnyCloser) - lexer.noFenceCloserFrom = start; + lexer.fenceCloserMemo.set(char, { from: start, maxRun }); return false; } -function startsInterruptingBlock(lexer) { - const ln = lexer.peek(); +function startsInterruptingBlock(lexer, content) { + const ln = content ?? lexer.peek(); if (ln === void 0) return false; let i = 0; @@ -11115,24 +12767,48 @@ function startsInterruptingBlock(lexer) { case "+": return false; case "*": - return RE_ABBR_DEF.test(ln) || RE_HR.test(ln); + return lexer.atDocumentLevel && RE_ABBR_DEF.test(ln) || RE_HR.test(ln); case "_": return RE_HR.test(ln); case ":": if (RE_ADMONITION_OPEN.test(ln) && !RE_ADMONITION_CLOSE.test(ln) || RE_DIV_OPEN.test(ln) || RE_LINE_BLOCK_OPEN.test(ln) || RE_HARDBREAKS_OPEN.test(ln)) - return divHasCloser(lexer); + return true; return RE_DEFLIST_TERM.test(ln); case "[": - return RE_LINK_DEF.test(ln) || RE_FOOTNOTE_DEF.test(ln); + return i === 0 && (isLinkDefLine(ln) || RE_FOOTNOTE_DEF.test(ln)); case "%": return RE_COMMENT_LINE.test(ln) || RE_COMMENT_BLOCK.test(ln); case "{": - return peekBlockAttributes(lexer); + return peekBlockAttributes(lexer, content === void 0 ? void 0 : ln); default: return false; } } -function readCaptionText(lexer, firstLine) { +function parseCaptionInline(lexer, firstLine) { + const capIndex = lexer.pos - 1; + const capLine = lexer.lines[capIndex]; + const anchors = []; + const anchorable = lexer.hasDocumentOffsets && capLine !== void 0 && capLine.endsWith(firstLine); + if (anchorable) { + const within = capLine.length - firstLine.length; + anchors.push({ + offset: lexer.lineOffset(capIndex) + within, + column: lexer.lineStartColumn(capIndex) + within + }); + } + const text = readCaptionText(lexer, firstLine, anchorable ? anchors : void 0); + if (!anchorable) { + return stripPositions(parseInline(text, lexer.abbrDefs, lexer.linkDefs, void 0, true)); + } + return parseInline(text, lexer.abbrDefs, lexer.linkDefs, inlineSource({ + anchored: true, + baseOffset: anchors[0].offset, + startLine: lexer.lineNumber(capIndex), + startColumn: anchors[0].column, + lineAnchors: anchors + }), true); +} +function readCaptionText(lexer, firstLine, anchors) { let text = firstLine; while (!lexer.eof()) { const next = lexer.peek(); @@ -11141,9 +12817,13 @@ function readCaptionText(lexer, firstLine) { if (startsInterruptingBlock(lexer)) break; text += "\n" + next; + anchors?.push({ + offset: lexer.lineOffset(lexer.pos), + column: lexer.lineStartColumn(lexer.pos) + }); lexer.consume(); } - return text.replace(RE_TRAILING_WS, ""); + return dropTrailingWhitespace(text); } function endsHeadingOrQuote(lexer) { const ln = lexer.peek(); @@ -11152,80 +12832,119 @@ function endsHeadingOrQuote(lexer) { } return startsInterruptingBlock(lexer); } -function parseParagraph(lexer) { +function parseParagraph(lexer, flattened = false) { const lines = []; const startLineIndex = lexer.pos; while (!lexer.eof()) { const ln = lexer.peek(); if (isBlankLine(ln)) break; - if (lines.length > 0 && startsInterruptingBlock(lexer)) + if (!flattened && lines.length > 0 && !lexer.literalLazyLinkDefLines.has(lexer.lineNumber(lexer.pos)) && startsInterruptingBlock(lexer) && !(RE_ADMONITION_CLOSE.test(ln) && lines.some((line2) => isLiteralColonFenceLine(line2)))) break; lexer.consume(); lines.push(ln); } const firstLead = lines[0].match(/^[ \t]+/)?.[0].length ?? 0; - const text = lines.map((ln) => ln.replace(/^[ \t]+/, "")).join("\n").replace(/[ \t]+$/, ""); + const text = dropTrailingWhitespace(lines.map((ln) => ln.replace(/^[ \t]+/, "")).join("\n")); + const anchors = lines.length > 1 ? lines.map((ln, i) => { + const lead = ln.match(/^[ \t]+/)?.[0].length ?? 0; + return { + offset: lexer.lineOffset(startLineIndex + i) + lead, + column: lexer.lineStartColumn(startLineIndex + i) + lead + }; + }) : void 0; return { type: "paragraph", children: parseInline(text, lexer.abbrDefs, lexer.linkDefs, { + anchored: lexer.hasDocumentOffsets, baseOffset: lexer.lineOffset(startLineIndex) + firstLead, startLine: lexer.lineNumber(startLineIndex), - startColumn: 1 + firstLead + startColumn: lexer.lineStartColumn(startLineIndex) + firstLead, + ...anchors ? { lineAnchors: anchors } : {} }) }; } -function leadingWhitespace(line) { +function leadingWhitespace(line2) { let n = 0; - while (n < line.length && (line[n] === " " || line[n] === " ")) + while (n < line2.length && (line2[n] === " " || line2[n] === " ")) n++; return n; } -function indentColumns(line) { +function indentColumns(line2, cap = Infinity) { let col = 0; - for (let i = 0; i < line.length; i++) { - if (line[i] === " ") + let i = 0; + while (i < line2.length && col < cap) { + const c = line2[i]; + if (c === " ") col++; - else if (line[i] === " ") + else if (c === " ") col += 4 - col % 4; else break; + i++; } - return col; + if (layoutWork.on) + layoutWork.gate += i; + return col > cap ? cap : col; } -function sliceColumns(line, cols, keepResidual = false) { +function sliceColumns(line2, cols, keepResidual = false) { let col = 0; let i = 0; - while (i < line.length && col < cols) { - if (line[i] === " ") { + while (i < line2.length && col < cols) { + if (line2[i] === " ") { col++; i++; - } else if (line[i] === " ") { + } else if (line2[i] === " ") { col += 4 - col % 4; i++; } else { break; } } + if (layoutWork.on) + layoutWork.strip += i; if (keepResidual && col > cols) - return " ".repeat(col - cols) + line.slice(i); - return line.slice(i); -} -var RE_FOOTNOTE_REF = /^\[\^([^\]]+)\]/; -var RE_EXTENSION = /^:([a-zA-Z_][\w-]*)\[([^\]]*)\](?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?/; -var RE_RAW_INLINE = /^\{=([a-zA-Z][\w-]*)\}/; -var RE_SYMBOL = /^:([a-zA-Z0-9+-][\w+-]*):/; -var RE_AUTOLINK = /^<([a-zA-Z][a-zA-Z0-9+.\-]*:[^>\s<"\\`{}|^]+|[A-Za-z0-9._+\-]+@[A-Za-z0-9._+\-]+\.[A-Za-z]+)>/; -var RE_CROSSREF = /^<\/#([^>\s]+)>/; -var RE_INLINE_ATTR = /^\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\}/; -var ATTR_INERT_PREV = /* @__PURE__ */ new Set(["text", "soft_break", "hard_break", "mention", "tag"]); -var RE_LINK_TAIL = /^\(([^)\s]+)(?:\s+"((?:[^"\\]|\\.)*)"|\s+'((?:[^'\\]|\\.)*)')?\)(?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?/; -var RE_REF_TAIL = /^\[([^\]]*)\](?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?/; -var RE_SPAN_TAIL = /^\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')*)\}/; + return " ".repeat(col - cols) + line2.slice(i); + return line2.slice(i); +} +function scanDestination(tail) { + if (tail[0] !== "(") + return null; + let dest = ""; + let depth = 0; + let i = 1; + for (; i < tail.length; i++) { + const c = tail[i]; + if (c === "\\" && (tail[i + 1] === "(" || tail[i + 1] === ")" || tail[i + 1] === "\\")) { + dest += tail[i + 1]; + i++; + continue; + } + if (c === "(") + depth++; + else if (c === ")") { + if (depth === 0) + break; + depth--; + } else if (RE_DESTINATION_WHITESPACE.test(c)) + break; + dest += c; + } + return { dest, end: i }; +} +function execLinkTail(tail) { + const scanned = scanDestination(tail); + if (scanned === null || scanned.dest === "") + return null; + const rest = RE_LINK_REST.exec(tail.slice(scanned.end)); + if (rest === null) + return null; + return [tail.slice(0, scanned.end + rest[0].length), scanned.dest, rest[1], rest[2], rest[3]]; +} function stripVerbatimPadding(content) { - if (content.trim() === "") + if (trimStructural(content) === "") return content; - return content.replace(/^ (.*) $/, "$1"); + return content.replace(/^ ([\s\S]*) $/, "$1"); } function verbatimSpanEnd(text, i) { let openLen = 1; @@ -11246,6 +12965,9 @@ function verbatimSpanEnd(text, i) { } return { end: text.length, closed: false, openLen }; } +function rawBracketRunCloses(text) { + return buildBracketMap(`[${text}]`)[0] === text.length + 1; +} function buildBracketMap(s) { const map = {}; const stack = []; @@ -11259,13 +12981,27 @@ function buildBracketMap(s) { j = verbatimSpanEnd(s, j).end - 1; continue; } - if (ch === "[") { - stack.push(j); - } else if (ch === "]") { - const open = stack.pop(); - if (open !== void 0) - map[open] = j; - } + if (ch === "{" && s[j + 1] === "%") { + const close = s.indexOf("%}", j + 2); + if (close !== -1) { + j = close + 1; + continue; + } + } + if (ch === "{" && s[j + 1] === "#") { + const close = s.indexOf("#}", j + 2); + if (close !== -1) { + j = close + 1; + continue; + } + } + if (ch === "[") { + stack.push(j); + } else if (ch === "]") { + const open = stack.pop(); + if (open !== void 0) + map[open] = j; + } } return map; } @@ -11291,13 +13027,15 @@ function suffixHasPair(s, a, b) { } return suf; } -var WS_NO_NL = /[^\S\n]/; function isIdentStart(c) { return c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "_"; } function isIdentPart(c) { return isIdentStart(c) || c >= "0" && c <= "9" || c === "-"; } +function isAsciiAlphanumeric(c) { + return /^[A-Za-z0-9]$/.test(c); +} function spanAttrProvablyInvalid(text, brace) { const n = text.length; let i = brace + 1; @@ -11322,13 +13060,19 @@ function spanAttrProvablyInvalid(text, brace) { i++; continue; } + if (c === ":") { + i++; + while (i < n && (isAsciiAlphanumeric(text[i]) || text[i] === "-")) + i++; + continue; + } if (isIdentStart(c)) { i++; while (i < n && isIdentPart(text[i])) i++; if (text[i] === "=") { const v = text[i + 1]; - if (v === void 0 || v === "}" || /\s/.test(v)) { + if (v === void 0 || v === "}" || isCarveWhitespace(v)) { return true; } return false; @@ -11339,36 +13083,6 @@ function spanAttrProvablyInvalid(text, brace) { } return true; } -var RE_CRITIC_INS = /^\{\+((?:[^+]|\+(?!\}))*)\+\}/; -var RE_CRITIC_DEL = /^\{-((?:[^-]|-(?!\}))*)-\}/; -var RE_CRITIC_SUB = /^\{~([^}]*)~>([^}]*)~\}/; -var RE_CRITIC_CMT = /^\{#([^}]*)#\}/; -var RE_FORCED_EMPHASIS = /^\{([/*_^,~=])([\s\S]+?)\1\}/; -var FORCED_TYPE = { - "/": "emphasis", - "*": "strong", - _: "underline", - "^": "superscript", - ",": "subscript", - "~": "strike", - "=": "highlight" -}; -var RE_MENTION = /^@([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/; -var RE_TAG = /^#([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/; -var SMART_TOKENS = [ - ["<->", "\u2194"], - ["(tm)", "\u2122"], - ["...", "\u2026"], - ["->", "\u2192"], - ["<-", "\u2190"], - ["=>", "\u21D2"], - ["<=", "\u2264"], - [">=", "\u2265"], - ["!=", "\u2260"], - ["+-", "\xB1"], - ["(c)", "\xA9"], - ["(r)", "\xAE"] -]; function allocateDashes(n) { if (n % 3 === 0) return "\u2014".repeat(n / 3); @@ -11384,46 +13098,86 @@ function allocateDashes(n) { } return "\u2014".repeat(em) + "\u2013".repeat(en); } -var isAlnum = (ch) => /[A-Za-z0-9]/.test(ch); -var isQuoteOpenContext = (prev) => prev === "" || // `=` opens a quote so an attribute-like `key="value"` / `="x"` gets an -// opening curly quote; `:` opens too (`:"q"` -> `:“q”`), matching carve-rs. -/[\s([{\-–—/=:]/.test(prev) || prev === "\u201C" || prev === "\u2018" || // U+E000 is the internal non-breaking-space placeholder (escaped `\ ` / -// line-block indent); a nbsp is whitespace, so a quote after it opens. -prev === "\uE000"; +function lastEmittedGlyph(out) { + const previous = out[out.length - 1]; + if (previous && previous.type === "smart_punctuation") { + const glyph = previous.glyph ?? SMART_PUNCTUATION_GLYPHS[previous.kind]; + if (glyph) + return glyph; + } + if (previous && previous.type === "escaped_text") + return previous.value; + return "x"; +} function smartToken(text, i, prev) { - for (const [tok, out] of SMART_TOKENS) { + for (const [tok, out, kind2] of SMART_TOKENS) { if (text.startsWith(tok, i)) - return { out, len: tok.length }; + return { out, len: tok.length, kind: kind2 }; } if (text[i] === "-" && text[i + 1] === "-") { let n = 0; while (text[i + n] === "-") n++; - return { out: allocateDashes(n), len: n }; + return { out: allocateDashes(n), len: n, kind: "dash_run" }; } const c = text[i]; if (c === '"') { - return { out: isQuoteOpenContext(prev) ? "\u201C" : "\u201D", len: 1 }; + const open = isQuoteOpenContext(prev); + return { out: open ? activeQuoteCharacters[0] : activeQuoteCharacters[1], len: 1, kind: open ? "left_double_quote" : "right_double_quote" }; } if (c === "'") { const next = text[i + 1] ?? ""; - const apostrophe = isAlnum(prev) || /[0-9]/.test(next) || !isQuoteOpenContext(prev); - return { out: apostrophe ? "\u2019" : "\u2018", len: 1 }; + const open = isQuoteOpenContext(prev); + const apostrophe = /[0-9]/.test(next) || !open && isAlnum(next); + return { + out: apostrophe ? "\u2019" : open ? activeQuoteCharacters[2] : activeQuoteCharacters[3], + len: 1, + kind: open && !apostrophe ? "left_single_quote" : "right_single_quote" + }; } return null; } +function parseRefLabelInlines(label) { + return scanInline(label, inlineSource(), false); +} function parseInline(text, abbrDefs, linkDefs = /* @__PURE__ */ new Map(), source = inlineSource(), captionContext = false) { const nodes = applyAbbreviations(scanInline(text, source, false, captionContext), abbrDefs); return applyLinkDefs(nodes, linkDefs); } function inlineSource(overrides = {}) { - return { + const source = { baseOffset: overrides.baseOffset ?? 0, startLine: overrides.startLine ?? 1, startColumn: overrides.startColumn ?? 1 }; + if (overrides.lineAnchors) + source.lineAnchors = overrides.lineAnchors; + if (overrides.anchorShift) + source.anchorShift = overrides.anchorShift; + if (overrides.anchoredRanges) + source.anchoredRanges = overrides.anchoredRanges; + if (overrides.rangeShift) + source.rangeShift = overrides.rangeShift; + if (overrides.anchored === false) + source.anchored = false; + return source; +} +function anchorRangeAt(ranges, offset) { + let lo = 0; + let hi = ranges.length - 1; + let found; + while (lo <= hi) { + const mid = lo + hi >> 1; + const r = ranges[mid]; + if (r.from <= offset) { + found = r; + lo = mid + 1; + } else { + hi = mid - 1; + } + } + return found && offset <= found.to ? found : void 0; } -var inlineDepth = 0; function scanInline(text, source = inlineSource(), inFootnote = false, captionContext = false) { if (inlineDepth >= MAX_NESTING_DEPTH) { return [withPos({ type: "text", value: text }, source, text, 0, text.length)]; @@ -11460,7 +13214,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { bufEscapedCaret = false; } }; - const append = (value) => { + const append2 = (value) => { if (!buf) bufStart = i; buf += value; @@ -11483,7 +13237,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { continue; } if (c === "\\" && text[i + 1] === " ") { - append("\uE000"); + append2("\uE000"); i += 2; continue; } @@ -11492,21 +13246,44 @@ function scanInlineInner(text, source, inFootnote, captionContext) { if (/[\\`*_{}\[\]()#+\-.!~^/<>@%|=,"'$&:;?]/.test(nxt)) { if (nxt === "^" && buf === "") bufEscapedCaret = true; - append(nxt); + const escStart = i; + flush(); + out.push(withPos({ type: "escaped_text", value: nxt }, source, text, escStart, i + 2)); i += 2; continue; } } { - const prevForQuote = buf.length ? bufLast : out.length ? "x" : ""; + const prevForQuote = buf.length ? bufLast : out.length ? lastEmittedGlyph(out) : ""; const st = smartToken(text, i, prevForQuote); if (st) { - append(st.out); + flush(); + if (st.kind === "dash_run") { + let consumed = 0; + for (const glyph of st.out) { + const width2 = glyph === "\u2014" ? 3 : 2; + out.push(withPos({ + type: "smart_punctuation", + kind: glyph === "\u2014" ? "em_dash" : "en_dash", + value: text.slice(i + consumed, i + consumed + width2) + }, source, text, i + consumed, i + consumed + width2)); + consumed += width2; + } + } else { + const node = { + type: "smart_punctuation", + kind: st.kind, + value: text.slice(i, i + st.len) + }; + if (st.kind.endsWith("_quote")) + node.glyph = st.out; + out.push(withPos(node, source, text, i, i + st.len)); + } i += st.len; continue; } } - if (c === "%" && text[i + 1] === "%" && (i === 0 || /[ \t]/.test(text[i - 1]))) { + if (c === "%" && text[i + 1] === "%" && (i === 0 || /[ \t\n]/.test(text[i - 1]))) { const trimmed = buf.replace(/[ \t]+$/, ""); const commentStart = i - (buf.length - trimmed.length); if (trimmed) { @@ -11520,15 +13297,25 @@ function scanInlineInner(text, source, inFootnote, captionContext) { const nl = text.indexOf("\n", i); const end = nl === -1 ? text.length : nl; const content = text.slice(i + 2, end).replace(/^[ \t]/, ""); - out.push(withPos({ type: "comment", block: false, content }, source, text, commentStart, end)); + out.push(withPos({ type: "comment", block: false, content }, source, text, i, end)); i = end; continue; } + if (c === "{" && text[i + 1] === "%") { + const close = text.indexOf("%}", i + 2); + if (close !== -1) { + flush(); + const content = text.slice(i + 2, close).replace(/^ /, "").replace(/ $/, ""); + out.push(withPos({ type: "comment", block: false, delimited: true, content }, source, text, i, close + 2)); + i = close + 2; + continue; + } + } if (c === "`") { const { end, closed, openLen } = verbatimSpanEnd(text, i); flush(); if (!closed) { - const value = text.slice(i + openLen).replace(/\s+$/, ""); + const value = text.slice(i + openLen).replace(/[ \t\n\r]+$/, ""); out.push(withPos({ type: "code", value }, source, text, i, text.length)); i = text.length; continue; @@ -11552,9 +13339,10 @@ function scanInlineInner(text, source, inFootnote, captionContext) { if (text[tick] === "`") { const { end, closed, openLen } = verbatimSpanEnd(text, tick); const innerEnd = end - openLen; - if (closed && text[end] !== "`" && innerEnd > tick + openLen && text[innerEnd - 1] !== "`") { + const hasContent = closed ? innerEnd > tick + openLen && text[innerEnd - 1] !== "`" : text.length > tick + openLen; + if (hasContent && (!closed || text[end] !== "`")) { flush(); - const content = stripVerbatimPadding(text.slice(tick + openLen, innerEnd)); + const content = closed ? stripVerbatimPadding(text.slice(tick + openLen, innerEnd)) : text.slice(tick + openLen).replace(/[ \t\n\r]+$/, ""); const len = end - i; out.push(withPos({ type: "math", display, content }, source, text, i, i + len)); i += len; @@ -11578,7 +13366,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { if (close > 1) { const alt = rest.slice(2, close); const tail = rest.slice(close + 1); - const ml = rparenSuf && rparenSuf[i + close + 1] ? RE_LINK_TAIL.exec(tail) : null; + const ml = rparenSuf && rparenSuf[i + close + 1] ? execLinkTail(tail) : null; if (ml) { flush(); const img = { type: "image", src: ml[1], alt }; @@ -11587,7 +13375,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { img.title = unescapeAttrValue(title); let len = close + 1 + ml[0].length; if (ml[4]) { - if (!isValidAttrPayload(ml[4])) { + if (!isValidInlineAttrPayload(ml[4])) { len -= ml[4].length + 2; } else { const a = parseAttrs(ml[4]); @@ -11607,7 +13395,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { let len = close + 1 + mref[0].length; let attrs; if (mref[2]) { - if (!isValidAttrPayload(mref[2])) { + if (!isValidInlineAttrPayload(mref[2])) { len -= mref[2].length + 2; } else { const a = parseAttrs(mref[2]); @@ -11622,7 +13410,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { src: "", alt, ref: mref[1] !== "" ? mref[1] : alt, - rawRef: rest.slice(0, len) + rawRef: rawSourceSlice(source, text, i, i + len) ?? rest.slice(0, len) }; if (attrs) img.attrs = attrs; @@ -11638,7 +13426,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { flush(); const inner = text.slice(i + 2, close); const children = scanInline(inner, shiftSource(source, text, i + 2), true); - out.push(withPos({ type: "footnote", inline: children }, source, text, i, close + 1)); + out.push(withPos({ type: "inline_footnote", inline: children }, source, text, i, close + 1)); i = close + 1; continue; } @@ -11652,11 +13440,11 @@ function scanInlineInner(text, source, inFootnote, captionContext) { const mfn2 = inFootnote ? null : RE_FOOTNOTE_REF.exec(rest); if (mfn2) { flush(); - out.push(withPos({ type: "footnote", id: mfn2[1].trim() }, source, text, i, i + mfn2[0].length)); + out.push(withPos({ type: "footnote_ref", id: mfn2[1] }, source, text, i, i + mfn2[0].length)); i += mfn2[0].length; continue; } - const ml = rparenSuf && rparenSuf[i + close + 1] ? RE_LINK_TAIL.exec(tail) : null; + const ml = rparenSuf && rparenSuf[i + close + 1] ? execLinkTail(tail) : null; if (ml) { flush(); const link = { @@ -11669,7 +13457,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { link.title = unescapeAttrValue(title); let len = close + 1 + ml[0].length; if (ml[4]) { - if (!isValidAttrPayload(ml[4])) { + if (!isValidInlineAttrPayload(ml[4])) { len -= ml[4].length + 2; } else { const a = parseAttrs(ml[4]); @@ -11684,12 +13472,12 @@ function scanInlineInner(text, source, inFootnote, captionContext) { continue; } const mref = RE_REF_TAIL.exec(tail); - if (mref && innerText !== "") { + if (mref && (innerText !== "" || !mref[1].startsWith("@"))) { flush(); let len = close + 1 + mref[0].length; let attrs; if (mref[2]) { - if (!isValidAttrPayload(mref[2])) { + if (!isValidInlineAttrPayload(mref[2])) { len -= mref[2].length + 2; } else { const a = parseAttrs(mref[2]); @@ -11705,8 +13493,10 @@ function scanInlineInner(text, source, inFootnote, captionContext) { children: scanInline(innerText, shiftSource(source, text, i + 1), inFootnote), ref: mref[1] !== "" ? mref[1] : innerText, // rawRef includes any consumed trailing {attrs} so the literal - // fallback for an unresolved ref preserves the full source. - rawRef: rest.slice(0, len) + // fallback for an unresolved ref preserves the full source, and it + // is read from the DOCUMENT where the scanner's own text is not + // that source (carve-js#1183). + rawRef: rawSourceSlice(source, text, i, i + len) ?? rest.slice(0, len) }; if (attrs) refLink.attrs = attrs; @@ -11718,21 +13508,20 @@ function scanInlineInner(text, source, inFootnote, captionContext) { const mfn = inFootnote ? null : RE_FOOTNOTE_REF.exec(rest); if (mfn) { flush(); - out.push(withPos({ type: "footnote", id: mfn[1].trim() }, source, text, i, i + mfn[0].length)); + out.push(withPos({ type: "footnote_ref", id: mfn[1] }, source, text, i, i + mfn[0].length)); i += mfn[0].length; continue; } if (close > 0) { const innerText = rest.slice(1, close); const ms = rbraceSuf && rbraceSuf[i + close + 1] && !spanAttrProvablyInvalid(text, i + close + 1) ? RE_SPAN_TAIL.exec(rest.slice(close + 1)) : null; - if (ms && isValidAttrPayload(ms[1])) { + if (ms && isValidInlineAttrPayload(ms[1])) { flush(); - out.push({ + out.push(withPos({ type: "span", children: scanInline(innerText, shiftSource(source, text, i + 1), inFootnote), - attrs: parseAttrs(ms[1]), - pos: sourcePos(source, text, i, i + close + 1 + ms[0].length) - }); + attrs: parseAttrs(ms[1]) + }, source, text, i, i + close + 1 + ms[0].length)); i += close + 1 + ms[0].length; continue; } @@ -11747,10 +13536,15 @@ function scanInlineInner(text, source, inFootnote, captionContext) { name: m[1], content: scanInline(m[2], shiftSource(source, text, i + m[0].indexOf("[") + 1), inFootnote) }; - if (m[3]) - ext.attrs = parseAttrs(m[3]); - out.push(withPos(ext, source, text, i, i + m[0].length)); - i += m[0].length; + let consumed = m[0].length; + if (m[3] !== void 0) { + if (isValidInlineAttrPayload(m[3])) + ext.attrs = parseAttrs(m[3]); + else + consumed -= m[3].length + 2; + } + out.push(withPos(ext, source, text, i, i + consumed)); + i += consumed; continue; } const sym = i === 0 || !/[A-Za-z0-9_]/.test(text[i - 1]) ? RE_SYMBOL.exec(rest) : null; @@ -11766,8 +13560,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { if (cr) { flush(); const cref = { type: "heading_ref", target: cr[1] }; - cref.pos = sourcePos(source, text, i, i + cr[0].length); - out.push(cref); + out.push(withPos(cref, source, text, i, i + cr[0].length)); i += cr[0].length; continue; } @@ -11784,7 +13577,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { }; let consumed = m[0].length; const am = /^\{([^}\n]+)\}/.exec(text.slice(i + consumed)); - if (am && isValidAttrPayload(am[1])) { + if (am && isValidInlineAttrPayload(am[1])) { const attrs = parseAttrs(am[1]); if (!isEmptyAttrs(attrs)) { if (attrs.keyValues?.href !== void 0) { @@ -11807,12 +13600,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { const sub = hasBrace ? RE_CRITIC_SUB.exec(rest) : null; if (sub) { flush(); - out.push({ - type: "substitution", - oldText: sub[1], - newText: sub[2], - pos: sourcePos(source, text, i, i + sub[0].length) - }); + out.push(withPos({ type: "substitution", oldText: sub[1], newText: sub[2] }, source, text, i, i + sub[0].length)); i += sub[0].length; continue; } @@ -11833,7 +13621,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { const cmt = hasBrace ? RE_CRITIC_CMT.exec(rest) : null; if (cmt) { flush(); - out.push(withPos({ type: "critic-comment", text: cmt[1] }, source, text, i, i + cmt[0].length)); + out.push(withPos({ type: "critic_comment", text: cmt[1] }, source, text, i, i + cmt[0].length)); i += cmt[0].length; continue; } @@ -11845,12 +13633,13 @@ function scanInlineInner(text, source, inFootnote, captionContext) { continue; } const attr = !buf && hasBrace ? RE_INLINE_ATTR.exec(rest) : null; - if (attr && out.length && isValidAttrPayload(attr[1])) { + if (attr && out.length && isValidInlineAttrPayload(attr[1])) { const prev = out[out.length - 1]; const parsed = parseAttrs(attr[1]); if (!ATTR_INERT_PREV.has(prev.type) && !isEmptyAttrs(parsed)) { ; prev.attrs = mergeAttrs(prev.attrs, parsed); + extendPosTo(prev, source, text, i + attr[0].length); i += attr[0].length; continue; } @@ -11903,7 +13692,7 @@ function scanInlineInner(text, source, inFootnote, captionContext) { continue; } } - append(c); + append2(c); i++; } flush(); @@ -11913,20 +13702,33 @@ function matchEmphasis(text, i, source, inFootnote = false, noClose = /* @__PURE const c = text[i]; if (c === "/" && text[i + 1] === "*") { const start = i + 2; - if (start < text.length && !/\s/.test(text[start])) { + if (start < text.length && !isCarveWhitespace(text[start])) { let searchPos = start; for (; ; ) { const close = findClose(text, searchPos, "*/"); if (close === -1) break; const inner = text.slice(start, close); - if (inner === "" || /\s/.test(inner[inner.length - 1])) { + if (inner === "" || isCarveWhitespace(inner[inner.length - 1])) { searchPos = close + 1; continue; } const children = scanInline(inner, shiftSource(source, text, start), inFootnote); return { - node: { type: "strong", children: [{ type: "emphasis", children }] }, + // `boldItalic` records that the author used the combined form. The + // nested spelling `*/x/*` yields the same tree, so the writer needs the + // mark to reproduce what was written (PART 11 §6). + node: { + type: "strong", + boldItalic: true, + // The inner emphasis is synthesized from the single `/*…*/` token + // rather than scanned as its own delimiter pair, so nothing else + // assigns it a span. PART 12 §4 requires one on every node but the + // document root, and a consumer cannot tell a synthesized node from + // a parsed one. It spans the CONTENT; the outer strong spans the + // delimiters too. + children: [withPos({ type: "emphasis", children }, source, text, start, close)] + }, end: close + 2 }; } @@ -11976,30 +13778,98 @@ function cachedFindEmphasisClose(text, from, delim, noClose) { return close; } function withPos(node, source, text, start, end) { - node.pos = sourcePos(source, text, start, end); + if (source.anchored === false) + return node; + const pos = sourcePos(source, text, start, end); + if (pos) + node.pos = pos; return node; } +function extendPosTo(node, source, text, end) { + const pos = node.pos; + if (!pos) + return; + const point2 = pointAt(source, text, end); + if (!point2) { + delete node.pos; + return; + } + pos.endLine = point2.line; + pos.endColumn = point2.column; + pos.endOffset = point2.offset; +} function sourcePos(source, text, start, end) { const startPoint = pointAt(source, text, start); const endPoint = pointAt(source, text, end); + if (!startPoint || !endPoint) + return void 0; + if (source.anchoredRanges && startPoint.range !== endPoint.range) + return void 0; return { startLine: startPoint.line, endLine: endPoint.line, startColumn: startPoint.column, endColumn: endPoint.column, - startOffset: source.baseOffset + start, - endOffset: source.baseOffset + end + startOffset: startPoint.offset, + endOffset: endPoint.offset }; } +function rawSourceSlice(source, text, start, end) { + if (!source.lineAnchors || activeDocument === null) + return void 0; + const pos = sourcePos(source, text, start, end); + if (pos?.startOffset === void 0 || pos.endOffset === void 0) + return void 0; + const candidate = normalizeNewlines(activeDocument.slice(pos.startOffset, pos.endOffset)); + const local = text.slice(start, end); + if (candidate === local) + return void 0; + const candidateLines = candidate.split("\n"); + const localLines = local.split("\n"); + if (candidateLines.length !== localLines.length) + return void 0; + for (const [i, localLine] of localLines.entries()) { + if (localLine !== "" && localLine !== candidateLines[i]) + return void 0; + } + return candidate; +} function shiftSource(source, text, by) { - const point = pointAt(source, text, by); - return { - baseOffset: source.baseOffset + by, - startLine: point.line, - startColumn: point.column + const point2 = pointAt(source, text, by); + const shifted = { + // THE ANCHORED BASE, NOT THE LINEAR ONE. `baseOffset + by` walks the LOCAL + // text, which is the document only while the two have the same length. A + // line block's joined text is shorter than its source by every comment line + // the block layer emptied, so past the first such line the linear sum lands + // mid-comment: `*a` / `%% secret` / `c*` measured `c` at the second `%` + // (carve-js#1182). `pointAt` already resolved the anchored answer. + baseOffset: point2?.offset ?? source.baseOffset + by, + startLine: point2?.line ?? source.startLine, + startColumn: point2?.column ?? source.startColumn }; + if (source.anchoredRanges) { + shifted.anchoredRanges = source.anchoredRanges; + shifted.rangeShift = (source.rangeShift ?? 0) + by; + } + if (source.lineAnchors) { + shifted.lineAnchors = source.lineAnchors; + shifted.anchorShift = (source.anchorShift ?? 0) + newlinesUpTo(text, by); + } + return shifted; +} +function newlinesUpTo(text, offset) { + const indices = newlineIndices(text); + let lo = 0; + let hi = indices.length; + while (lo < hi) { + const mid = lo + hi >> 1; + if (indices[mid] < offset) + lo = mid + 1; + else + hi = mid; + } + return lo; } -var newlineIndexCache = /* @__PURE__ */ new Map(); function newlineIndices(text) { let indices = newlineIndexCache.get(text); if (indices === void 0) { @@ -12013,21 +13883,33 @@ function newlineIndices(text) { return indices; } function pointAt(source, text, offset) { + if (source.anchoredRanges) { + const cellOffset = offset + (source.rangeShift ?? 0); + const range = anchorRangeAt(source.anchoredRanges, cellOffset); + if (!range) + return void 0; + const within = cellOffset - range.from; + return { + line: range.line, + column: range.column + within, + offset: range.offset + within, + range + }; + } const indices = newlineIndices(text); - let lo = 0; - let hi = indices.length; - while (lo < hi) { - const mid = lo + hi >> 1; - if (indices[mid] < offset) { - lo = mid + 1; - } else { - hi = mid; + const newlinesBefore = newlinesUpTo(text, offset); + const line2 = source.startLine + newlinesBefore; + const lineStart = newlinesBefore === 0 ? 0 : indices[newlinesBefore - 1] + 1; + const withinLine = offset - lineStart; + const anchor = source.lineAnchors?.[newlinesBefore + (source.anchorShift ?? 0)]; + if (anchor) { + if (newlinesBefore === 0) { + return { line: line2, column: source.startColumn + offset, offset: source.baseOffset + offset }; } + return { line: line2, column: anchor.column + withinLine, offset: anchor.offset + withinLine }; } - const newlinesBefore = lo; - const line = source.startLine + newlinesBefore; const column = newlinesBefore === 0 ? source.startColumn + offset : offset - indices[newlinesBefore - 1]; - return { line, column }; + return { line: line2, column, offset: source.baseOffset + offset }; } function findEmphasisClose(text, from, delim) { let depth = 0; @@ -12038,12 +13920,19 @@ function findEmphasisClose(text, from, delim) { continue; } if (ch === "`") { - const span = verbatimSpanEnd(text, j); - if (!span.closed) + const span2 = verbatimSpanEnd(text, j); + if (!span2.closed) return -1; - j = span.end - 1; + j = span2.end - 1; continue; } + if (ch === "{" && text[j + 1] === "%") { + const close = text.indexOf("%}", j + 2); + if (close !== -1) { + j = close + 1; + continue; + } + } if (ch === delim) { const prev = text[j - 1]; if (prev === " " || prev === "\n" || prev === void 0) @@ -12058,6 +13947,20 @@ function findEmphasisClose(text, from, delim) { } return -1; } +function fragmentPos(parent, start, end) { + if (!parent) + return void 0; + const pos = { startLine: parent.startLine, endLine: parent.startLine }; + if (parent.startColumn !== void 0) { + pos.startColumn = parent.startColumn + start; + pos.endColumn = parent.startColumn + end; + } + if (parent.startOffset !== void 0) { + pos.startOffset = parent.startOffset + start; + pos.endOffset = parent.startOffset + end; + } + return pos; +} function applyAbbreviations(nodes, defs) { if (defs.size === 0) return nodes; @@ -12075,6 +13978,11 @@ function applyAbbreviations(nodes, defs) { ; node.inline = applyAbbreviations(anyInline, defs); } + const anyContent = node.content; + if (Array.isArray(anyContent)) { + ; + node.content = applyAbbreviations(anyContent, defs); + } out.push(node); continue; } @@ -12085,6 +13993,9 @@ function applyAbbreviations(nodes, defs) { while (m = abbrRe.exec(value)) { if (m.index > last) { const frag = { type: "text", value: value.slice(last, m.index) }; + const fragSpan = fragmentPos(node.pos, last, m.index); + if (fragSpan) + frag.pos = fragSpan; if (last === 0 && node.escapedLeadingCaret) frag.escapedLeadingCaret = true; out.push(frag); @@ -12093,12 +14004,17 @@ function applyAbbreviations(nodes, defs) { out.push({ type: "abbreviation", abbr, - expansion: defs.get(abbr) + expansion: defs.get(abbr), + pos: fragmentPos(node.pos, m.index, m.index + abbr.length) }); last = m.index + abbr.length; } if (last < value.length) { - out.push({ type: "text", value: value.slice(last) }); + out.push({ + type: "text", + value: value.slice(last), + pos: fragmentPos(node.pos, last, value.length) + }); } else if (last === 0) { out.push(node); } @@ -12119,25 +14035,25 @@ function applyLinkDefs(nodes, defs) { node.inline = applyLinkDefs(anyInline, defs); } if (node.type === "link" && node.ref !== void 0) { - const def = defs.get(normalizeRefLabel(node.ref)); + const def = defs.get(node.ref); if (def) { node.href = def.href; if (def.title !== void 0) node.title = def.title; - delete node.ref; - delete node.rawRef; + if (def.attrs) + node.attrs = mergeAttrs(def.attrs, node.attrs ?? {}); } out.push(node); continue; } if (node.type === "image" && node.ref !== void 0) { - const def = defs.get(normalizeRefLabel(node.ref)); + const def = defs.get(node.ref); if (def) { node.src = def.href; if (def.title !== void 0) node.title = def.title; - delete node.ref; - delete node.rawRef; + if (def.attrs) + node.attrs = mergeAttrs(def.attrs, node.attrs ?? {}); } out.push(node); continue; @@ -12147,8 +14063,22 @@ function applyLinkDefs(nodes, defs) { return out; } function isValidAttrPayload(inner) { - const stripped = inner.replace(/(?:#[a-zA-Z_][\w-]*)|(?:\.[a-zA-Z_][\w-]*)|(?:[a-zA-Z_][\w-]*=(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\S+))|(?:[a-zA-Z_][\w-]*)|\s+/g, ""); - return stripped === ""; + if (quotedRunSpansLines(inner)) + return false; + return ATTR_PAYLOAD.test(inner); +} +function isValidInlineAttrPayload(inner) { + return isValidAttrPayload(inner) && !inlineAttrPayloadHasTab(inner); +} +function inlineAttrPayloadHasTab(inner) { + return inner.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g, "").includes(" "); +} +function quotedRunSpansLines(inner) { + for (const m of inner.matchAll(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g)) { + if (m[0].includes("\n")) + return true; + } + return false; } function isEmptyAttrs(attrs) { return attrs.id === void 0 && (attrs.classes === void 0 || attrs.classes.length === 0) && (attrs.keyValues === void 0 || Object.keys(attrs.keyValues).length === 0); @@ -12159,35 +14089,38 @@ function unescapeAttrValue(v) { function parseAttrs(src) { const attrs = {}; const order = []; - const note = (slot) => { + const note2 = (slot) => { if (!order.includes(slot)) order.push(slot); }; - const re = /(?:#([a-zA-Z_][\w-]*))|(?:\.([a-zA-Z_][\w-]*))|(?:([a-zA-Z_][\w-]*)=(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)'|(\S+)))|(?:([a-zA-Z_][\w-]*))/g; + const re = /(?:#([a-zA-Z_][\w-]*))|(?:\.([a-zA-Z_][\w-]*))|(?:([a-zA-Z_][\w-]*)=(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)'|([^ \t\n\r]+)))|(?:(?<=^|[ \t\n\r]):((?:[A-Za-z0-9]{1,8}(?:-[A-Za-z0-9]{1,8})*)?)(?=[ \t\n\r]|$))|(?:([a-zA-Z_][\w-]*))/g; let m; while (m = re.exec(src)) { if (m[1]) { attrs.id = m[1]; - note("#id"); + note2("#id"); } else if (m[2]) { attrs.classes = [...attrs.classes ?? [], m[2]]; - note(".class"); + note2(".class"); } else if (m[3]) { const val = m[4] !== void 0 ? unescapeAttrValue(m[4]) : m[5] !== void 0 ? unescapeAttrValue(m[5]) : m[6] ?? ""; if (m[3] === "id") { attrs.id = val; - note("#id"); + note2("#id"); } else { attrs.keyValues = { ...attrs.keyValues ?? {}, [m[3]]: val }; - note(m[3]); + note2(m[3]); } - } else if (m[7]) { - if (m[7] === "id") { + } else if (m[7] !== void 0) { + attrs.keyValues = { ...attrs.keyValues ?? {}, lang: m[7] }; + note2("lang"); + } else if (m[8]) { + if (m[8] === "id") { attrs.id = ""; - note("#id"); + note2("#id"); } else { - attrs.keyValues = { ...attrs.keyValues ?? {}, [m[7]]: "" }; - note(m[7]); + attrs.keyValues = { ...attrs.keyValues ?? {}, [m[8]]: "" }; + note2(m[8]); } } } @@ -12226,917 +14159,1422 @@ function attrOrder(a) { o.push(k); return o; } +var activeMatchers, activeMatcherCtx, activeDocument, RE_HEADING, RE_HR, TRAILING_WS, FENCE_TRAILING_WS, RE_FENCE, RE_UNORDERED, RE_ORDERED, RE_TASK, RE_ITEM_ATTR, TRIM_STRUCTURAL_RE, trimCellPadding, RE_BLANK_LINE, RE_CONTINUATION_MARKER, RE_BLOCKQUOTE, RE_ADMONITION_OPEN, RE_ADMONITION_CLOSE, RE_LINE_BLOCK_OPEN, RE_HARDBREAKS_OPEN, RE_DIV_OPEN, RE_DEFLIST_TERM, RE_DEFLIST_MARKER_EMPTY, RE_DEFLIST_DEF, RE_ABBR_DEF, RE_DESTINATION_WHITESPACE, AUTOLINK_BODY_EXCLUDED, RE_LINK_DEF, RE_FOOTNOTE_DEF, FOOTNOTE_BODY_COLUMN, RE_CAPTION, RE_TRAILING_WS, RE_TABLE_ROW, isTableRow, RE_TABLE_CONT, RE_BARE_IMAGE, RE_FRONTMATTER_OPEN, RE_FRONTMATTER_CLOSE, RE_RAW_FENCE, RE_COMMENT_BLOCK, RE_COMMENT_BLOCK_ANY, commentFenceRun, RE_COMMENT_LINE, RE_FENCE_CLOSER, RE_FENCE_CLOSER_PREPASS, MAX_NESTING_DEPTH, layoutWork, Lexer, EMPTY_LINE_INDICES, RE_DESCRIPTION_PREFIX, RE_AFTER_TERM, RE_PREPASS_MARKER, RE_PREPASS_MARKER_STRIP, RE_QUOTE_RUN, RE_ANY_COLON_CLOSER, RE_ANY_FENCE_CLOSER, RE_PREPASS_ANY_FENCE_CLOSER, DEFLIST_CONTENT_COL, blockQuoteParagraphOpen, closeBlockQuoteParagraph, PREFIX_WINDOW, RE_INVISIBLE_BLOCK_LEAD, TABLE_ALIGNMENT_MARKERS, isGfmDelimiterCell, isGfmDelimiterRow, RE_FOOTNOTE_REF, RE_EXTENSION, RE_RAW_INLINE, RE_SYMBOL, RE_AUTOLINK, RE_CROSSREF, RE_INLINE_ATTR, ATTR_INERT_PREV, RE_LINK_REST, RE_REF_TAIL, RE_SPAN_TAIL, WS_NO_NL, RE_CRITIC_INS, RE_CRITIC_DEL, RE_CRITIC_SUB, RE_CRITIC_CMT, RE_FORCED_EMPHASIS, FORCED_TYPE, RE_MENTION, RE_TAG, SMART_TOKENS, isAlnum, isQuoteOpenContext, activeQuoteCharacters, inlineDepth, newlineIndexCache, ATTR_ITEM_SRC, ATTR_PAYLOAD; +var init_parse = __esm({ + "node_modules/@markup-carve/carve/dist/parse.js"() { + init_ast(); + init_abbr_budget(); + init_trim_non_nbsp(); + activeMatchers = []; + activeMatcherCtx = null; + activeDocument = null; + RE_HEADING = /^(#{1,6}) +((?=[ \t]*[^ \t\n\r]).+?)(?:[ \t]+\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?[ \t]*$/; + RE_HR = /^([-*_])\1{2,}[ \t]*$/; + TRAILING_WS = "[ \\t]*$"; + FENCE_TRAILING_WS = "[ \\t]*$"; + RE_FENCE = new RegExp('^()(`{3,}|~{3,}) ?(?:([a-zA-Z0-9_+#/.-]+)(?: +("[^"]*"))?(?: +(\\[[^\\]]*\\]))?|("[^"]*")(?: +(\\[[^\\]]*\\]))?|(\\[[^\\]]*\\]))?' + FENCE_TRAILING_WS); + RE_UNORDERED = /^(?=([ \t]*))\1[-*] +[ \t]*([^ \t].*)$/; + RE_ORDERED = /^(?=([ \t]*))\1([0-9]+|[ivxlcdm]+|[IVXLCDM]+|[a-z]|[A-Z]|(?=\.))([.)]) +[ \t]*([^ \t].*)$/; + RE_TASK = /^(?=([ \t]*))\1[-*] +\[([ xX\-_>?])\] +[ \t]*([^ \t].*)$/; + RE_ITEM_ATTR = /^([ \t]*)((?:[-*])|(?:[0-9]+|[ivxlcdm]+|[IVXLCDM]+|[a-z]|[A-Z]|(?=\.))[.)])\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')*)\}( +[^ \t].*)$/; + TRIM_STRUCTURAL_RE = /^[ \t\n\r]+|[ \t\n\r]+$/g; + trimCellPadding = (text) => { + let start = 0; + let end = text.length; + while (start < end && text.charCodeAt(start) === 32) + start++; + while (end > start && text.charCodeAt(end - 1) === 32) + end--; + if (start === 0 && end === text.length) + return text; + return text.slice(start, end); + }; + RE_BLANK_LINE = /^[ \t]*$/; + RE_CONTINUATION_MARKER = new RegExp("^[ \\t]*\\+" + TRAILING_WS); + RE_BLOCKQUOTE = /^>(?: (.*)|)$/; + RE_ADMONITION_OPEN = /^(:{3,}) +([a-zA-Z_][\w-]*)(?: +("[^"]*"))?(?: +(\[[^\]]*\]))?[ \t]*$/; + RE_ADMONITION_CLOSE = new RegExp("^(:{3,})" + TRAILING_WS); + RE_LINE_BLOCK_OPEN = /^(:{3,}) +\|[ \t]*$/; + RE_HARDBREAKS_OPEN = /^(:{3,}) +\\[ \t]*$/; + RE_DIV_OPEN = /^(:{3,}) *(\[[^\]]*\])?[ \t]*$/; + RE_DEFLIST_TERM = /^::(?!:) [ \t]*(?=[^ \t])(.+)$/; + RE_DEFLIST_MARKER_EMPTY = /^::?(?!:)[ \t]+$/; + RE_DEFLIST_DEF = /^: {2,}(.+)$/; + RE_ABBR_DEF = /^\*\[([A-Za-z0-9]+)\]: +(?![ \t]*$)([^]+)$/u; + RE_DESTINATION_WHITESPACE = new RegExp("\\p{White_Space}", "u"); + AUTOLINK_BODY_EXCLUDED = "\\p{White_Space}\\p{Cf}\\p{Cc}"; + RE_LINK_DEF = new RegExp(`^[ \\t]*\\[(?!@)([^\\]]+)\\]: \\p{White_Space}*(\\P{White_Space}+)(?: (?:"((?:[^"\\\\]|\\\\.)*)"|'((?:[^'\\\\]|\\\\.)*)'))?[ \\t]*$`, "u"); + RE_FOOTNOTE_DEF = /^\[\^([^\]]+)\]: +([^]+)$/; + FOOTNOTE_BODY_COLUMN = 2; + RE_CAPTION = /^\^ +(.*[^ \t\n\r].*)$/; + RE_TRAILING_WS = /[ \t]+$/; + RE_TABLE_ROW = /^\|/; + isTableRow = (line2) => { + if (!RE_TABLE_ROW.test(line2)) + return false; + if (!/\|[ \t]*$/.test(line2) && rowAttrsFromLine(line2).attrs === void 0) + return false; + const cells = splitTableRow(rowAttrsFromLine(line2).body); + return cells.some((cell) => cell.trim().length > 0) || cells.length >= 2; + }; + RE_TABLE_CONT = /^\+.*\|[ \t]*$/; + RE_BARE_IMAGE = /^!\[([^\]]*)\]\(([^)\s]+)(?: "([^"]*)"| '([^']*)')?\)(?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?[ \t]*$/; + RE_FRONTMATTER_OPEN = new RegExp("^--- ?(\\w*)" + TRAILING_WS); + RE_FRONTMATTER_CLOSE = new RegExp("^---" + TRAILING_WS); + RE_RAW_FENCE = new RegExp("^(`{3,}|~{3,}) ?=([a-zA-Z][\\w-]*)" + FENCE_TRAILING_WS); + RE_COMMENT_BLOCK = /^(%{3,})(.*)$/; + RE_COMMENT_BLOCK_ANY = /^[ \t]*(%{3,})(.*)$/; + commentFenceRun = (line2) => { + const m = RE_COMMENT_BLOCK_ANY.exec(line2); + return m ? m[1].length : void 0; + }; + RE_COMMENT_LINE = /^[ \t]*%%/; + RE_FENCE_CLOSER = new RegExp("^(`{3,}|~{3,})" + FENCE_TRAILING_WS); + RE_FENCE_CLOSER_PREPASS = new RegExp("^([`~]{3,})" + FENCE_TRAILING_WS); + MAX_NESTING_DEPTH = 200; + layoutWork = { + /** Whether to accumulate. Tests turn this on around a single parse. */ + on: false, + /** Characters walked by the indentation gate (`indentColumns`). */ + gate: 0, + /** Characters walked by the column strip (`sliceColumns`). */ + strip: 0, + /** Characters re-copied at a container recursion seam (join/split/normalize). */ + seam: 0, + reset() { + this.gate = 0; + this.strip = 0; + this.seam = 0; + }, + get total() { + return this.gate + this.strip + this.seam; + } + }; + Lexer = class { + lines; + lineOffsets; + lineNumberOffset; + sourceLineMap; + /** + * Document offset of each line's CONTENT start, for a sub-lexer over stripped + * container lines. Without it `lineOffset` reports an offset into the + * container's own text, so every inline position inside a blockquote, list or + * admonition pointed at the wrong place (#444). + */ + sourceOffsetMap; + /** + * Width of the container prefix stripped from each line (`> `, `- `, and so + * on). Columns are 1-based against the DOCUMENT line, so the inline scanner + * has to add back what the container removed. It varies per line, since `>`, + * `> ` and `> ` are all valid. + */ + linePrefixWidths; + suppressPositions = false; + pos = 0; + // Block-container nesting depth of this (sub-)lexer; 0 at the document top. + depth = 0; + frontmatter; + /** Format applied to a bare `---` fence; set from ParseOptions. */ + defaultFrontmatterFormat = "yaml"; + parseOptions; + unclosedContainerKeys; + abbrDefs = /* @__PURE__ */ new Map(); + /** + * True only for the lexer over the whole document. PART 12 §7 recognizes an + * abbreviation definition ONLY at document level: inside a block quote, list + * item or div the line is ordinary paragraph text. Sub-lexers leave this + * false, which is what makes a container-authored `*[X]: y` inert. + */ + atDocumentLevel = false; + linkDefs = /* @__PURE__ */ new Map(); + /** Document lines admitted only as a block quote's lazy paragraph text. */ + literalLazyLinkDefLines = /* @__PURE__ */ new Set(); + // Footnote definitions keyed by raw label; value is the parsed note + // body (def line + indented continuation), set by parseFootnoteDef. + footnoteDefs = /* @__PURE__ */ new Map(); + /** Where each definition sits in the source, parallel to `footnoteDefs`. */ + footnoteDefPos = /* @__PURE__ */ new Map(); + // True for sub-lexers over already-nested block content (list item / + // blockquote / admonition bodies). Informational only: under the §10 + // Markdown-like rule a visible block interrupts a paragraph at EVERY level + // (top and nested) — startsInterruptingBlock no longer branches on this — + // but sub-lexers still set it to mark their context. + nested = false; + /** + * True while this lexer reads the body of an open `::: figure` group, at any + * depth (PART 9 §4c: groups do not nest). `parseAdmonition` sets it on the + * group's body sub-lexer and `nestedSubLexer` carries it into every deeper + * container, so a bare `::: figure` ANYWHERE inside an open group's body is + * demoted to a generic container. A sibling after the group parses from the + * parent lexer, where the flag was never set. + */ + inFigureGroup = false; + // Negative cache for fenceHasCloser (paragraph-interruption closer + // lookahead), the same entry the container-local scans keep: per fence + // CHARACTER, where a scan started and the longest bare run of that character + // it saw. Once proven, every later opener (pos only advances) whose marker is + // longer than that run short-circuits, keeping "many unclosed fences" input + // linear. + // + // This was one index, char- and length-agnostic, so a single `~~~` or a + // single short ``` ``` ``` anywhere ahead pinned it at Infinity forever and + // the lookahead stayed quadratic: 500 unterminated ` ````js ` openers over + // one ``` ``` ``` took 25ms and 4000 took 347ms. + fenceCloserMemo = /* @__PURE__ */ new Map(); + // Where a closer of each fence shape LAST occurs in these lines, built once + // by `closerIndex`. See `CloserIndex`. + fenceCloserIndex = void 0; + // EVERY line carrying a `%` run, keyed by run length and ascending, built + // once by `commentRunLines`. `fenceCloserIndex` keeps only the LAST line of + // each width, which answers "is there one ahead" and cannot answer "is there + // one before the container ends" - the question `commentCloserInScope` asks. + commentRunLines = void 0; + // Document line number -> every index of THIS lexer's lines carrying it, + // built once by attachDocumentOffsets when the first child asks for it. + // + // BUILT ONCE PER PARENT, NOT ONCE PER CHILD. The inversion is a function of + // this lexer alone - `lines` and `lineNumber` - and neither changes after the + // constructor runs, so every child of the same parent was rebuilding a map it + // could have shared. A list gets one sub-lexer per item, so an n-line + // document paid n x O(n): 16,000 flat bullets took 18 s where 0.1.2 took + // 82 ms, on the DEFAULT path (this is not behind the `positions` option). + // + // Undefined until asked for, so a document that never nests never allocates. + lineIndicesByNumber = void 0; + constructor(source, opts = {}, lineNumberOffset = 0, unclosedContainerKeys) { + this.parseOptions = opts; + this.unclosedContainerKeys = unclosedContainerKeys; + this.lineNumberOffset = lineNumberOffset; + this.defaultFrontmatterFormat = opts.defaultFrontmatterFormat ?? "yaml"; + if (typeof source === "string") { + if (layoutWork.on) + layoutWork.seam += source.length; + this.lines = normalizeNewlines(source).split("\n"); + } else { + this.lines = source.slice(); + } + if (typeof source === "string" && this.lines.length && this.lines[this.lines.length - 1] === "") { + this.lines.pop(); + } + const raw = typeof source === "string" ? source : void 0; + this.lineOffsets = []; + let offset = 0; + let index2 = 0; + for (const line2 of this.lines) { + this.lineOffsets.push(offset); + index2 += line2.length; + let width2 = 1; + if (raw !== void 0 && raw[index2] === "\r") + width2 = raw[index2 + 1] === "\n" ? 2 : 1; + offset += line2.length + width2; + index2 += width2; + } + } + consumeFrontmatter() { + if (this.lines.length < 2) + return; + const open = RE_FRONTMATTER_OPEN.exec(this.lines[0]); + if (!open) + return; + for (let i = 1; i < this.lines.length; i++) { + if (RE_FRONTMATTER_CLOSE.test(this.lines[i])) { + const content = this.lines.slice(1, i).join("\n"); + const format = open[1] !== "" ? open[1] : this.defaultFrontmatterFormat; + const closeOffset = (this.lineOffsets[i] ?? 0) + this.lines[i].length; + this.frontmatter = { + format, + content, + pos: { + startLine: 1, + endLine: i + 1, + startColumn: 1, + endColumn: this.lines[i].length + 1, + startOffset: 0, + endOffset: closeOffset + } + }; + this.pos = i + 1; + return; + } + } + } + peek(offset = 0) { + return this.lines[this.pos + offset]; + } + consume() { + return this.lines[this.pos++]; + } + eof() { + return this.pos >= this.lines.length; + } + lineOffset(lineIndex) { + return this.sourceOffsetMap?.[lineIndex] ?? this.lineOffsets[lineIndex] ?? 0; + } + /** 1-based column, in the DOCUMENT line, where this line's content starts. */ + lineStartColumn(lineIndex) { + return (this.linePrefixWidths?.[lineIndex] ?? 0) + 1; + } + /** + * Whether `lineOffset` returns a DOCUMENT offset rather than one into this + * lexer's own text. + * + * True at the root, and for a sub-lexer whose lines were mapped back (see + * attachDocumentOffsets). An unmapped sub-lexer - a container whose lines were + * reconstructed rather than stripped - has offsets that are only meaningful + * locally, and emitting them as document positions is the invented value PART + * 12 section 4 forbids. + */ + get hasDocumentOffsets() { + return !this.nested || this.sourceOffsetMap !== void 0; + } + lineNumber(lineIndex) { + return this.sourceLineMap?.[lineIndex] ?? this.lineNumberOffset + lineIndex + 1; + } + reportUnclosedContainer(container) { + if (!this.hasDocumentOffsets) + return; + const seen = this.unclosedContainerKeys; + const key2 = `${container.startOffset}:${container.endOffset}`; + if (seen?.has(key2)) + return; + seen?.add(key2); + this.parseOptions.onUnclosedContainer?.(container); + } + }; + EMPTY_LINE_INDICES = /* @__PURE__ */ new Map(); + RE_DESCRIPTION_PREFIX = /^[ \t]*:[ \t]+/; + RE_AFTER_TERM = /^[ \t]*(?:::(?!:)|:)[ \t]/; + RE_PREPASS_MARKER = /^([ \t]*)(?:[-*]|(?:[0-9]+|[ivxlcdm]+|[IVXLCDM]+|[a-z]|[A-Z]|(?=\.))[.)])(?:\{([^}]*)\})? +/; + RE_PREPASS_MARKER_STRIP = /^([ \t]*)(?:[-*]|(?:[0-9]+|[ivxlcdm]+|[IVXLCDM]+|[a-z]|[A-Z]|(?=\.))[.)])(?:\{([^}]*)\})? +(?:\[[ xX\-_>?]\] +)?/; + RE_QUOTE_RUN = /^(?:[^\S ]*>(?: |$))+/; + RE_ANY_COLON_CLOSER = /^[ \t]*(:{3,})[ \t]*$/; + RE_ANY_FENCE_CLOSER = new RegExp("^[ \\t]*([`~]{3,})" + FENCE_TRAILING_WS); + RE_PREPASS_ANY_FENCE_CLOSER = new RegExp("^(?:[ \\t]*>)*[ \\t]*(?:(?:[-*+]|[0-9]+[.)]|[A-Za-z][.)])[ \\t]+)*[ \\t]*([`~]{3,})" + FENCE_TRAILING_WS); + DEFLIST_CONTENT_COL = 3; + blockQuoteParagraphOpen = (state) => { + let level = state; + while (level.mode.kind === "quote") + level = level.mode.inner; + return level.mode.kind === "paragraph"; + }; + closeBlockQuoteParagraph = (state) => { + state.mode = { kind: "closed" }; + }; + PREFIX_WINDOW = 32; + RE_INVISIBLE_BLOCK_LEAD = /^[ \t]*[%[]/; + TABLE_ALIGNMENT_MARKERS = /* @__PURE__ */ new Map([ + [">", "right"], + ["<", "left"], + ["~", "center"] + ]); + isGfmDelimiterCell = (c) => !c.span && !c.attrs && /^:?-+:?$/.test(trimCellPadding(c.raw)); + isGfmDelimiterRow = (row) => row.length > 0 && row.every(isGfmDelimiterCell); + RE_FOOTNOTE_REF = /^\[\^([^\]\r\n]+)\]/; + RE_EXTENSION = /^:([a-zA-Z_][\w-]*)\[([^\]]*)\](?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?/; + RE_RAW_INLINE = /^\{=([a-zA-Z][\w-]*)\}/; + RE_SYMBOL = /^:([a-zA-Z0-9+-][\w+-]*):/; + RE_AUTOLINK = new RegExp("^<([a-zA-Z][a-zA-Z0-9+.\\-]*:[^>" + AUTOLINK_BODY_EXCLUDED + '<"\\\\`{}|^]+|[A-Za-z0-9._+\\-]+@[A-Za-z0-9._+\\-]+\\.[A-Za-z]+)>', "u"); + RE_CROSSREF = /^<\/#([^> \t\n\r]+)>/; + RE_INLINE_ATTR = /^\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\}/; + ATTR_INERT_PREV = /* @__PURE__ */ new Set(["text", "soft_break", "hard_break", "mention", "tag", "heading_ref"]); + RE_LINK_REST = /^(?: "((?:[^"\\]|\\.)*)"| '((?:[^'\\]|\\.)*)')?\)(?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?/; + RE_REF_TAIL = /^\[([^\]]*)\](?:\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')+)\})?/; + RE_SPAN_TAIL = /^\{((?:[^}"'\n]|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')*)\}/; + WS_NO_NL = /[ \t\r]/; + RE_CRITIC_INS = /^\{\+((?:[^+]|\+(?!\}))*)\+\}/; + RE_CRITIC_DEL = /^\{-((?:[^-]|-(?!\}))*)-\}/; + RE_CRITIC_SUB = /^\{~([^}]*)~>([^}]*)~\}/; + RE_CRITIC_CMT = /^\{#([^}]*)#\}/; + RE_FORCED_EMPHASIS = /^\{([/*_^,~=])([\s\S]+?)\1\}/; + FORCED_TYPE = { + "/": "emphasis", + "*": "strong", + _: "underline", + "^": "superscript", + ",": "subscript", + "~": "strike", + "=": "highlight" + }; + RE_MENTION = /^@([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/; + RE_TAG = /^#([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/; + SMART_TOKENS = [ + ["<->", "\u2194", "left_right_arrow"], + ["(tm)", "\u2122", "trademark"], + ["...", "\u2026", "ellipsis"], + ["->", "\u2192", "rightwards_arrow"], + ["<-", "\u2190", "leftwards_arrow"], + ["=>", "\u21D2", "rightwards_double_arrow"], + ["<=", "\u2264", "less_than_or_equal"], + [">=", "\u2265", "greater_than_or_equal"], + ["!=", "\u2260", "not_equal"], + ["+-", "\xB1", "plus_minus"], + ["(c)", "\xA9", "copyright"], + ["(r)", "\xAE", "registered"] + ]; + isAlnum = (ch) => /[A-Za-z0-9]/.test(ch); + isQuoteOpenContext = (prev) => prev === "" || // `=` opens a quote so an attribute-like `key="value"` / `="x"` gets an + // opening curly quote; `:` opens too (`:"q"` -> `:“q”`), matching carve-rs. + // PART 7's four characters PLUS the NO-BREAK SPACE, not `\s`. + // + // The four are the whitespace clause. The NBSP is a deliberate addition and + // not an inherited one: this test picks a GLYPH for a character that is + // already content, so what it asks is "does a space stand here", and a + // no-break space is a space to the reader. The branch below already says so + // for the ESCAPED spelling (`\ `, carried as U+E000), and a rule that + // answered the two spellings of one character differently would be the drift + // PART 7 exists to stop. + // + // What comes OUT is the rest of the host's `\s`: a VERTICAL TAB, a FORM FEED + // and U+FEFF are not spaces under any reading, and a quote after one now + // closes exactly as a quote after a letter does. `a"x"` and `a"x"` + // used to curl differently, from one class. + /[ \t\n\r\u00a0([{\-–—/=:]/.test(prev) || prev === "\u201C" || prev === "\u2018" || // U+E000 is the internal non-breaking-space placeholder (escaped `\ ` / + // line-block indent); a nbsp is whitespace, so a quote after it opens. + prev === "\uE000"; + activeQuoteCharacters = ["\u201C", "\u201D", "\u2018", "\u2019"]; + inlineDepth = 0; + newlineIndexCache = /* @__PURE__ */ new Map(); + ATTR_ITEM_SRC = `(?:#[a-zA-Z_][\\w-]*)|(?:\\.[a-zA-Z_][\\w-]*)|(?:[a-zA-Z_][\\w-]*=(?:"(?:[^"\\\\]|\\\\.)*"|'(?:[^'\\\\]|\\\\.)*'|[^ \\t\\n\\r]+))|(?::(?:[A-Za-z0-9]{1,8}(?:-[A-Za-z0-9]{1,8})*)?)|(?:[a-zA-Z_][\\w-]*)`; + ATTR_PAYLOAD = new RegExp(`^[ \\t\\n\\r]*(?:(?:${ATTR_ITEM_SRC})(?:[ \\t\\n\\r]+(?:${ATTR_ITEM_SRC}))*[ \\t\\n\\r]*)?$`); + } +}); // node_modules/@markup-carve/carve/dist/translit-map.js -var TRANSLIT_MAP = { - "\xA0": " ", - "\xA1": "!", - "\xA9": "(C)", - "\xAB": "<<", - "\xAD": "-", - "\xAE": "(R)", - "\xB1": "+/-", - "\xBB": ">>", - "\xBC": " 1/4", - "\xBD": " 1/2", - "\xBE": " 3/4", - "\xBF": "?", - "\xC0": "A", - "\xC1": "A", - "\xC2": "A", - "\xC3": "A", - "\xC4": "A", - "\xC5": "A", - "\xC6": "AE", - "\xC7": "C", - "\xC8": "E", - "\xC9": "E", - "\xCA": "E", - "\xCB": "E", - "\xCC": "I", - "\xCD": "I", - "\xCE": "I", - "\xCF": "I", - "\xD0": "D", - "\xD1": "N", - "\xD2": "O", - "\xD3": "O", - "\xD4": "O", - "\xD5": "O", - "\xD6": "O", - "\xD7": "*", - "\xD8": "O", - "\xD9": "U", - "\xDA": "U", - "\xDB": "U", - "\xDC": "U", - "\xDD": "Y", - "\xDE": "TH", - "\xDF": "ss", - "\xE0": "a", - "\xE1": "a", - "\xE2": "a", - "\xE3": "a", - "\xE4": "a", - "\xE5": "a", - "\xE6": "ae", - "\xE7": "c", - "\xE8": "e", - "\xE9": "e", - "\xEA": "e", - "\xEB": "e", - "\xEC": "i", - "\xED": "i", - "\xEE": "i", - "\xEF": "i", - "\xF0": "d", - "\xF1": "n", - "\xF2": "o", - "\xF3": "o", - "\xF4": "o", - "\xF5": "o", - "\xF6": "o", - "\xF7": "/", - "\xF8": "o", - "\xF9": "u", - "\xFA": "u", - "\xFB": "u", - "\xFC": "u", - "\xFD": "y", - "\xFE": "th", - "\xFF": "y", - "\u0100": "A", - "\u0101": "a", - "\u0102": "A", - "\u0103": "a", - "\u0104": "A", - "\u0105": "a", - "\u0106": "C", - "\u0107": "c", - "\u0108": "C", - "\u0109": "c", - "\u010A": "C", - "\u010B": "c", - "\u010C": "C", - "\u010D": "c", - "\u010E": "D", - "\u010F": "d", - "\u0110": "D", - "\u0111": "d", - "\u0112": "E", - "\u0113": "e", - "\u0114": "E", - "\u0115": "e", - "\u0116": "E", - "\u0117": "e", - "\u0118": "E", - "\u0119": "e", - "\u011A": "E", - "\u011B": "e", - "\u011C": "G", - "\u011D": "g", - "\u011E": "G", - "\u011F": "g", - "\u0120": "G", - "\u0121": "g", - "\u0122": "G", - "\u0123": "g", - "\u0124": "H", - "\u0125": "h", - "\u0126": "H", - "\u0127": "h", - "\u0128": "I", - "\u0129": "i", - "\u012A": "I", - "\u012B": "i", - "\u012C": "I", - "\u012D": "i", - "\u012E": "I", - "\u012F": "i", - "\u0130": "I", - "\u0131": "i", - "\u0132": "IJ", - "\u0133": "ij", - "\u0134": "J", - "\u0135": "j", - "\u0136": "K", - "\u0137": "k", - "\u0138": "q", - "\u0139": "L", - "\u013A": "l", - "\u013B": "L", - "\u013C": "l", - "\u013D": "L", - "\u013E": "l", - "\u013F": "L", - "\u0140": "l", - "\u0141": "L", - "\u0142": "l", - "\u0143": "N", - "\u0144": "n", - "\u0145": "N", - "\u0146": "n", - "\u0147": "N", - "\u0148": "n", - "\u0149": "'n", - "\u014A": "N", - "\u014B": "n", - "\u014C": "O", - "\u014D": "o", - "\u014E": "O", - "\u014F": "o", - "\u0150": "O", - "\u0151": "o", - "\u0152": "OE", - "\u0153": "oe", - "\u0154": "R", - "\u0155": "r", - "\u0156": "R", - "\u0157": "r", - "\u0158": "R", - "\u0159": "r", - "\u015A": "S", - "\u015B": "s", - "\u015C": "S", - "\u015D": "s", - "\u015E": "S", - "\u015F": "s", - "\u0160": "S", - "\u0161": "s", - "\u0162": "T", - "\u0163": "t", - "\u0164": "T", - "\u0165": "t", - "\u0166": "T", - "\u0167": "t", - "\u0168": "U", - "\u0169": "u", - "\u016A": "U", - "\u016B": "u", - "\u016C": "U", - "\u016D": "u", - "\u016E": "U", - "\u016F": "u", - "\u0170": "U", - "\u0171": "u", - "\u0172": "U", - "\u0173": "u", - "\u0174": "W", - "\u0175": "w", - "\u0176": "Y", - "\u0177": "y", - "\u0178": "Y", - "\u0179": "Z", - "\u017A": "z", - "\u017B": "Z", - "\u017C": "z", - "\u017D": "Z", - "\u017E": "z", - "\u017F": "s", - "\u0180": "b", - "\u0181": "B", - "\u0182": "B", - "\u0183": "b", - "\u0187": "C", - "\u0188": "c", - "\u0189": "D", - "\u018A": "D", - "\u018B": "D", - "\u018C": "d", - "\u0190": "E", - "\u0191": "F", - "\u0192": "f", - "\u0193": "G", - "\u0195": "hv", - "\u0196": "I", - "\u0197": "I", - "\u0198": "K", - "\u0199": "k", - "\u019A": "l", - "\u019D": "N", - "\u019E": "n", - "\u01A0": "O", - "\u01A1": "o", - "\u01A2": "OI", - "\u01A3": "oi", - "\u01A4": "P", - "\u01A5": "p", - "\u01AB": "t", - "\u01AC": "T", - "\u01AD": "t", - "\u01AE": "T", - "\u01AF": "U", - "\u01B0": "u", - "\u01B2": "V", - "\u01B3": "Y", - "\u01B4": "y", - "\u01B5": "Z", - "\u01B6": "z", - "\u01C4": "DZ", - "\u01C5": "Dz", - "\u01C6": "dz", - "\u01C7": "LJ", - "\u01C8": "Lj", - "\u01C9": "lj", - "\u01CA": "NJ", - "\u01CB": "Nj", - "\u01CC": "nj", - "\u01CD": "A", - "\u01CE": "a", - "\u01CF": "I", - "\u01D0": "i", - "\u01D1": "O", - "\u01D2": "o", - "\u01D3": "U", - "\u01D4": "u", - "\u01D5": "U", - "\u01D6": "u", - "\u01D7": "U", - "\u01D8": "u", - "\u01D9": "U", - "\u01DA": "u", - "\u01DB": "U", - "\u01DC": "u", - "\u01DE": "A", - "\u01DF": "a", - "\u01E0": "A", - "\u01E1": "a", - "\u01E2": "AE", - "\u01E3": "ae", - "\u01E4": "G", - "\u01E5": "g", - "\u01E6": "G", - "\u01E7": "g", - "\u01E8": "K", - "\u01E9": "k", - "\u01EA": "O", - "\u01EB": "o", - "\u01EC": "O", - "\u01ED": "o", - "\u01F0": "j", - "\u01F1": "DZ", - "\u01F2": "Dz", - "\u01F3": "dz", - "\u01F4": "G", - "\u01F5": "g", - "\u01F8": "N", - "\u01F9": "n", - "\u01FA": "A", - "\u01FB": "a", - "\u01FC": "AE", - "\u01FD": "ae", - "\u01FE": "O", - "\u01FF": "o", - "\u0200": "A", - "\u0201": "a", - "\u0202": "A", - "\u0203": "a", - "\u0204": "E", - "\u0205": "e", - "\u0206": "E", - "\u0207": "e", - "\u0208": "I", - "\u0209": "i", - "\u020A": "I", - "\u020B": "i", - "\u020C": "O", - "\u020D": "o", - "\u020E": "O", - "\u020F": "o", - "\u0210": "R", - "\u0211": "r", - "\u0212": "R", - "\u0213": "r", - "\u0214": "U", - "\u0215": "u", - "\u0216": "U", - "\u0217": "u", - "\u0218": "S", - "\u0219": "s", - "\u021A": "T", - "\u021B": "t", - "\u021E": "H", - "\u021F": "h", - "\u0221": "d", - "\u0224": "Z", - "\u0225": "z", - "\u0226": "A", - "\u0227": "a", - "\u0228": "E", - "\u0229": "e", - "\u022A": "O", - "\u022B": "o", - "\u022C": "O", - "\u022D": "o", - "\u022E": "O", - "\u022F": "o", - "\u0230": "O", - "\u0231": "o", - "\u0232": "Y", - "\u0233": "y", - "\u0234": "l", - "\u0235": "n", - "\u0236": "t", - "\u0237": "j", - "\u0238": "db", - "\u0239": "qp", - "\u023A": "A", - "\u023B": "C", - "\u023C": "c", - "\u023D": "L", - "\u023E": "T", - "\u023F": "s", - "\u0240": "z", - "\u0243": "B", - "\u0244": "U", - "\u0246": "E", - "\u0247": "e", - "\u0248": "J", - "\u0249": "j", - "\u024C": "R", - "\u024D": "r", - "\u024E": "Y", - "\u024F": "y", - "\u0253": "b", - "\u0255": "c", - "\u0256": "d", - "\u0257": "d", - "\u025B": "e", - "\u025F": "j", - "\u0260": "g", - "\u0261": "g", - "\u0262": "G", - "\u0266": "h", - "\u0267": "h", - "\u0268": "i", - "\u026A": "I", - "\u026B": "l", - "\u026C": "l", - "\u026D": "l", - "\u0271": "m", - "\u0272": "n", - "\u0273": "n", - "\u0274": "N", - "\u0276": "OE", - "\u027C": "r", - "\u027D": "r", - "\u027E": "r", - "\u0280": "R", - "\u0282": "s", - "\u0288": "t", - "\u0289": "u", - "\u028B": "v", - "\u028F": "Y", - "\u0290": "z", - "\u0291": "z", - "\u0299": "B", - "\u029B": "G", - "\u029C": "H", - "\u029D": "j", - "\u029F": "L", - "\u02A0": "q", - "\u02A3": "dz", - "\u02A5": "dz", - "\u02A6": "ts", - "\u02AA": "ls", - "\u02AB": "lz", - "\u0400": "E", - "\u0401": "E", - "\u0402": "D", - "\u0403": "G", - "\u0404": "E", - "\u0405": "Z", - "\u0406": "I", - "\u0407": "I", - "\u0408": "J", - "\u0409": "L", - "\u040A": "N", - "\u040B": "C", - "\u040C": "K", - "\u040D": "I", - "\u040E": "U", - "\u040F": "D", - "\u0410": "A", - "\u0411": "B", - "\u0412": "V", - "\u0413": "G", - "\u0414": "D", - "\u0415": "E", - "\u0416": "Z", - "\u0417": "Z", - "\u0418": "I", - "\u0419": "J", - "\u041A": "K", - "\u041B": "L", - "\u041C": "M", - "\u041D": "N", - "\u041E": "O", - "\u041F": "P", - "\u0420": "R", - "\u0421": "S", - "\u0422": "T", - "\u0423": "U", - "\u0424": "F", - "\u0425": "H", - "\u0426": "C", - "\u0427": "C", - "\u0428": "S", - "\u0429": "S", - "\u042B": "Y", - "\u042D": "E", - "\u042E": "U", - "\u042F": "A", - "\u0430": "a", - "\u0431": "b", - "\u0432": "v", - "\u0433": "g", - "\u0434": "d", - "\u0435": "e", - "\u0436": "z", - "\u0437": "z", - "\u0438": "i", - "\u0439": "j", - "\u043A": "k", - "\u043B": "l", - "\u043C": "m", - "\u043D": "n", - "\u043E": "o", - "\u043F": "p", - "\u0440": "r", - "\u0441": "s", - "\u0442": "t", - "\u0443": "u", - "\u0444": "f", - "\u0445": "h", - "\u0446": "c", - "\u0447": "c", - "\u0448": "s", - "\u0449": "s", - "\u044A": '"', - "\u044B": "y", - "\u044C": "'", - "\u044D": "e", - "\u044E": "u", - "\u044F": "a", - "\u0450": "e", - "\u0451": "e", - "\u0452": "d", - "\u0453": "g", - "\u0454": "e", - "\u0455": "z", - "\u0456": "i", - "\u0457": "i", - "\u0458": "j", - "\u0459": "l", - "\u045A": "n", - "\u045B": "c", - "\u045C": "k", - "\u045D": "i", - "\u045E": "u", - "\u045F": "d", - "\u0490": "G", - "\u0491": "g", - "\u0492": "G", - "\u0493": "g", - "\u0494": "G", - "\u0495": "g", - "\u0498": "Z", - "\u0499": "z", - "\u04A2": "N", - "\u04A3": "n", - "\u04AE": "U", - "\u04AF": "u", - "\u04B0": "U", - "\u04B1": "u", - "\u04BA": "H", - "\u04BB": "h", - "\u04C1": "Z", - "\u04C2": "z", - "\u04D0": "A", - "\u04D1": "a", - "\u04D2": "A", - "\u04D3": "a", - "\u04D4": "AE", - "\u04D5": "ae", - "\u04D6": "E", - "\u04D7": "e", - "\u04DC": "Z", - "\u04DD": "z", - "\u04DE": "Z", - "\u04DF": "z", - "\u04E2": "I", - "\u04E3": "i", - "\u04E4": "I", - "\u04E5": "i", - "\u04E6": "O", - "\u04E7": "o", - "\u04E8": "O", - "\u04E9": "o", - "\u04EC": "E", - "\u04ED": "e", - "\u04EE": "U", - "\u04EF": "u", - "\u04F0": "U", - "\u04F1": "u", - "\u04F2": "U", - "\u04F3": "u", - "\u04F4": "C", - "\u04F5": "c", - "\u04F8": "Y", - "\u04F9": "y", - "\u1E00": "A", - "\u1E01": "a", - "\u1E02": "B", - "\u1E03": "b", - "\u1E04": "B", - "\u1E05": "b", - "\u1E06": "B", - "\u1E07": "b", - "\u1E08": "C", - "\u1E09": "c", - "\u1E0A": "D", - "\u1E0B": "d", - "\u1E0C": "D", - "\u1E0D": "d", - "\u1E0E": "D", - "\u1E0F": "d", - "\u1E10": "D", - "\u1E11": "d", - "\u1E12": "D", - "\u1E13": "d", - "\u1E14": "E", - "\u1E15": "e", - "\u1E16": "E", - "\u1E17": "e", - "\u1E18": "E", - "\u1E19": "e", - "\u1E1A": "E", - "\u1E1B": "e", - "\u1E1C": "E", - "\u1E1D": "e", - "\u1E1E": "F", - "\u1E1F": "f", - "\u1E20": "G", - "\u1E21": "g", - "\u1E22": "H", - "\u1E23": "h", - "\u1E24": "H", - "\u1E25": "h", - "\u1E26": "H", - "\u1E27": "h", - "\u1E28": "H", - "\u1E29": "h", - "\u1E2A": "H", - "\u1E2B": "h", - "\u1E2C": "I", - "\u1E2D": "i", - "\u1E2E": "I", - "\u1E2F": "i", - "\u1E30": "K", - "\u1E31": "k", - "\u1E32": "K", - "\u1E33": "k", - "\u1E34": "K", - "\u1E35": "k", - "\u1E36": "L", - "\u1E37": "l", - "\u1E38": "L", - "\u1E39": "l", - "\u1E3A": "L", - "\u1E3B": "l", - "\u1E3C": "L", - "\u1E3D": "l", - "\u1E3E": "M", - "\u1E3F": "m", - "\u1E40": "M", - "\u1E41": "m", - "\u1E42": "M", - "\u1E43": "m", - "\u1E44": "N", - "\u1E45": "n", - "\u1E46": "N", - "\u1E47": "n", - "\u1E48": "N", - "\u1E49": "n", - "\u1E4A": "N", - "\u1E4B": "n", - "\u1E4C": "O", - "\u1E4D": "o", - "\u1E4E": "O", - "\u1E4F": "o", - "\u1E50": "O", - "\u1E51": "o", - "\u1E52": "O", - "\u1E53": "o", - "\u1E54": "P", - "\u1E55": "p", - "\u1E56": "P", - "\u1E57": "p", - "\u1E58": "R", - "\u1E59": "r", - "\u1E5A": "R", - "\u1E5B": "r", - "\u1E5C": "R", - "\u1E5D": "r", - "\u1E5E": "R", - "\u1E5F": "r", - "\u1E60": "S", - "\u1E61": "s", - "\u1E62": "S", - "\u1E63": "s", - "\u1E64": "S", - "\u1E65": "s", - "\u1E66": "S", - "\u1E67": "s", - "\u1E68": "S", - "\u1E69": "s", - "\u1E6A": "T", - "\u1E6B": "t", - "\u1E6C": "T", - "\u1E6D": "t", - "\u1E6E": "T", - "\u1E6F": "t", - "\u1E70": "T", - "\u1E71": "t", - "\u1E72": "U", - "\u1E73": "u", - "\u1E74": "U", - "\u1E75": "u", - "\u1E76": "U", - "\u1E77": "u", - "\u1E78": "U", - "\u1E79": "u", - "\u1E7A": "U", - "\u1E7B": "u", - "\u1E7C": "V", - "\u1E7D": "v", - "\u1E7E": "V", - "\u1E7F": "v", - "\u1E80": "W", - "\u1E81": "w", - "\u1E82": "W", - "\u1E83": "w", - "\u1E84": "W", - "\u1E85": "w", - "\u1E86": "W", - "\u1E87": "w", - "\u1E88": "W", - "\u1E89": "w", - "\u1E8A": "X", - "\u1E8B": "x", - "\u1E8C": "X", - "\u1E8D": "x", - "\u1E8E": "Y", - "\u1E8F": "y", - "\u1E90": "Z", - "\u1E91": "z", - "\u1E92": "Z", - "\u1E93": "z", - "\u1E94": "Z", - "\u1E95": "z", - "\u1E96": "h", - "\u1E97": "t", - "\u1E98": "w", - "\u1E99": "y", - "\u1E9A": "a", - "\u1E9B": "s", - "\u1E9C": "s", - "\u1E9D": "s", - "\u1E9E": "SS", - "\u1EA0": "A", - "\u1EA1": "a", - "\u1EA2": "A", - "\u1EA3": "a", - "\u1EA4": "A", - "\u1EA5": "a", - "\u1EA6": "A", - "\u1EA7": "a", - "\u1EA8": "A", - "\u1EA9": "a", - "\u1EAA": "A", - "\u1EAB": "a", - "\u1EAC": "A", - "\u1EAD": "a", - "\u1EAE": "A", - "\u1EAF": "a", - "\u1EB0": "A", - "\u1EB1": "a", - "\u1EB2": "A", - "\u1EB3": "a", - "\u1EB4": "A", - "\u1EB5": "a", - "\u1EB6": "A", - "\u1EB7": "a", - "\u1EB8": "E", - "\u1EB9": "e", - "\u1EBA": "E", - "\u1EBB": "e", - "\u1EBC": "E", - "\u1EBD": "e", - "\u1EBE": "E", - "\u1EBF": "e", - "\u1EC0": "E", - "\u1EC1": "e", - "\u1EC2": "E", - "\u1EC3": "e", - "\u1EC4": "E", - "\u1EC5": "e", - "\u1EC6": "E", - "\u1EC7": "e", - "\u1EC8": "I", - "\u1EC9": "i", - "\u1ECA": "I", - "\u1ECB": "i", - "\u1ECC": "O", - "\u1ECD": "o", - "\u1ECE": "O", - "\u1ECF": "o", - "\u1ED0": "O", - "\u1ED1": "o", - "\u1ED2": "O", - "\u1ED3": "o", - "\u1ED4": "O", - "\u1ED5": "o", - "\u1ED6": "O", - "\u1ED7": "o", - "\u1ED8": "O", - "\u1ED9": "o", - "\u1EDA": "O", - "\u1EDB": "o", - "\u1EDC": "O", - "\u1EDD": "o", - "\u1EDE": "O", - "\u1EDF": "o", - "\u1EE0": "O", - "\u1EE1": "o", - "\u1EE2": "O", - "\u1EE3": "o", - "\u1EE4": "U", - "\u1EE5": "u", - "\u1EE6": "U", - "\u1EE7": "u", - "\u1EE8": "U", - "\u1EE9": "u", - "\u1EEA": "U", - "\u1EEB": "u", - "\u1EEC": "U", - "\u1EED": "u", - "\u1EEE": "U", - "\u1EEF": "u", - "\u1EF0": "U", - "\u1EF1": "u", - "\u1EF2": "Y", - "\u1EF3": "y", - "\u1EF4": "Y", - "\u1EF5": "y", - "\u1EF6": "Y", - "\u1EF7": "y", - "\u1EF8": "Y", - "\u1EF9": "y", - "\u1EFA": "LL", - "\u1EFB": "ll", - "\u1EFC": "V", - "\u1EFD": "v", - "\u1EFE": "Y", - "\u1EFF": "y", - "\u2000": " ", - "\u2001": " ", - "\u2002": " ", - "\u2003": " ", - "\u2004": " ", - "\u2005": " ", - "\u2006": " ", - "\u2007": " ", - "\u2008": " ", - "\u2009": " ", - "\u200A": " ", - "\u2010": "-", - "\u2011": "-", - "\u2012": "-", - "\u2013": "-", - "\u2014": "-", - "\u2015": "-", - "\u2016": "||", - "\u2018": "'", - "\u2019": "'", - "\u201A": ",", - "\u201B": "'", - "\u201C": '"', - "\u201D": '"', - "\u201E": ",,", - "\u201F": '"', - "\u2024": ".", - "\u2025": "..", - "\u2026": "...", - "\u2032": "'", - "\u2033": '"', - "\u2039": "<", - "\u203A": ">", - "\u203C": "!!", - "\u2044": "/", - "\u2045": "[", - "\u2046": "]", - "\u2047": "??", - "\u2048": "?!", - "\u2049": "!?", - "\u204E": "*", - "\u205F": " ", - "\u20A0": "CE", - "\u20A2": "Cr", - "\u20A3": "Fr.", - "\u20A4": "L.", - "\u20A7": "Pts", - "\u20B9": "Rs", - "\u20BA": "TL", - "\u2100": "a/c", - "\u2101": "a/s", - "\u2102": "C", - "\u2105": "c/o", - "\u2106": "c/u", - "\u210A": "g", - "\u210B": "H", - "\u210C": "x", - "\u210D": "H", - "\u210E": "h", - "\u2110": "I", - "\u2111": "I", - "\u2112": "L", - "\u2113": "l", - "\u2115": "N", - "\u2116": "No", - "\u2117": "(P)", - "\u2118": "P", - "\u2119": "P", - "\u211A": "Q", - "\u211B": "R", - "\u211C": "R", - "\u211D": "R", - "\u211E": "Rx", - "\u2121": "TEL", - "\u2124": "Z", - "\u2126": "O", - "\u2128": "Z", - "\u212A": "K", - "\u212B": "A", - "\u212C": "B", - "\u212D": "C", - "\u212F": "e", - "\u2130": "E", - "\u2131": "F", - "\u2133": "M", - "\u2134": "o", - "\u2139": "i", - "\u213B": "FAX", - "\u2145": "D", - "\u2146": "d", - "\u2147": "e", - "\u2148": "i", - "\u2149": "j" -}; +var TRANSLIT_MAP; +var init_translit_map = __esm({ + "node_modules/@markup-carve/carve/dist/translit-map.js"() { + TRANSLIT_MAP = { + "\xA0": " ", + "\xA1": "!", + "\xA9": "(C)", + "\xAB": "<<", + "\xAD": "-", + "\xAE": "(R)", + "\xB1": "+/-", + "\xBB": ">>", + "\xBC": " 1/4", + "\xBD": " 1/2", + "\xBE": " 3/4", + "\xBF": "?", + "\xC0": "A", + "\xC1": "A", + "\xC2": "A", + "\xC3": "A", + "\xC4": "A", + "\xC5": "A", + "\xC6": "AE", + "\xC7": "C", + "\xC8": "E", + "\xC9": "E", + "\xCA": "E", + "\xCB": "E", + "\xCC": "I", + "\xCD": "I", + "\xCE": "I", + "\xCF": "I", + "\xD0": "D", + "\xD1": "N", + "\xD2": "O", + "\xD3": "O", + "\xD4": "O", + "\xD5": "O", + "\xD6": "O", + "\xD7": "*", + "\xD8": "O", + "\xD9": "U", + "\xDA": "U", + "\xDB": "U", + "\xDC": "U", + "\xDD": "Y", + "\xDE": "TH", + "\xDF": "ss", + "\xE0": "a", + "\xE1": "a", + "\xE2": "a", + "\xE3": "a", + "\xE4": "a", + "\xE5": "a", + "\xE6": "ae", + "\xE7": "c", + "\xE8": "e", + "\xE9": "e", + "\xEA": "e", + "\xEB": "e", + "\xEC": "i", + "\xED": "i", + "\xEE": "i", + "\xEF": "i", + "\xF0": "d", + "\xF1": "n", + "\xF2": "o", + "\xF3": "o", + "\xF4": "o", + "\xF5": "o", + "\xF6": "o", + "\xF7": "/", + "\xF8": "o", + "\xF9": "u", + "\xFA": "u", + "\xFB": "u", + "\xFC": "u", + "\xFD": "y", + "\xFE": "th", + "\xFF": "y", + "\u0100": "A", + "\u0101": "a", + "\u0102": "A", + "\u0103": "a", + "\u0104": "A", + "\u0105": "a", + "\u0106": "C", + "\u0107": "c", + "\u0108": "C", + "\u0109": "c", + "\u010A": "C", + "\u010B": "c", + "\u010C": "C", + "\u010D": "c", + "\u010E": "D", + "\u010F": "d", + "\u0110": "D", + "\u0111": "d", + "\u0112": "E", + "\u0113": "e", + "\u0114": "E", + "\u0115": "e", + "\u0116": "E", + "\u0117": "e", + "\u0118": "E", + "\u0119": "e", + "\u011A": "E", + "\u011B": "e", + "\u011C": "G", + "\u011D": "g", + "\u011E": "G", + "\u011F": "g", + "\u0120": "G", + "\u0121": "g", + "\u0122": "G", + "\u0123": "g", + "\u0124": "H", + "\u0125": "h", + "\u0126": "H", + "\u0127": "h", + "\u0128": "I", + "\u0129": "i", + "\u012A": "I", + "\u012B": "i", + "\u012C": "I", + "\u012D": "i", + "\u012E": "I", + "\u012F": "i", + "\u0130": "I", + "\u0131": "i", + "\u0132": "IJ", + "\u0133": "ij", + "\u0134": "J", + "\u0135": "j", + "\u0136": "K", + "\u0137": "k", + "\u0138": "q", + "\u0139": "L", + "\u013A": "l", + "\u013B": "L", + "\u013C": "l", + "\u013D": "L", + "\u013E": "l", + "\u013F": "L", + "\u0140": "l", + "\u0141": "L", + "\u0142": "l", + "\u0143": "N", + "\u0144": "n", + "\u0145": "N", + "\u0146": "n", + "\u0147": "N", + "\u0148": "n", + "\u0149": "'n", + "\u014A": "N", + "\u014B": "n", + "\u014C": "O", + "\u014D": "o", + "\u014E": "O", + "\u014F": "o", + "\u0150": "O", + "\u0151": "o", + "\u0152": "OE", + "\u0153": "oe", + "\u0154": "R", + "\u0155": "r", + "\u0156": "R", + "\u0157": "r", + "\u0158": "R", + "\u0159": "r", + "\u015A": "S", + "\u015B": "s", + "\u015C": "S", + "\u015D": "s", + "\u015E": "S", + "\u015F": "s", + "\u0160": "S", + "\u0161": "s", + "\u0162": "T", + "\u0163": "t", + "\u0164": "T", + "\u0165": "t", + "\u0166": "T", + "\u0167": "t", + "\u0168": "U", + "\u0169": "u", + "\u016A": "U", + "\u016B": "u", + "\u016C": "U", + "\u016D": "u", + "\u016E": "U", + "\u016F": "u", + "\u0170": "U", + "\u0171": "u", + "\u0172": "U", + "\u0173": "u", + "\u0174": "W", + "\u0175": "w", + "\u0176": "Y", + "\u0177": "y", + "\u0178": "Y", + "\u0179": "Z", + "\u017A": "z", + "\u017B": "Z", + "\u017C": "z", + "\u017D": "Z", + "\u017E": "z", + "\u017F": "s", + "\u0180": "b", + "\u0181": "B", + "\u0182": "B", + "\u0183": "b", + "\u0187": "C", + "\u0188": "c", + "\u0189": "D", + "\u018A": "D", + "\u018B": "D", + "\u018C": "d", + "\u0190": "E", + "\u0191": "F", + "\u0192": "f", + "\u0193": "G", + "\u0195": "hv", + "\u0196": "I", + "\u0197": "I", + "\u0198": "K", + "\u0199": "k", + "\u019A": "l", + "\u019D": "N", + "\u019E": "n", + "\u01A0": "O", + "\u01A1": "o", + "\u01A2": "OI", + "\u01A3": "oi", + "\u01A4": "P", + "\u01A5": "p", + "\u01AB": "t", + "\u01AC": "T", + "\u01AD": "t", + "\u01AE": "T", + "\u01AF": "U", + "\u01B0": "u", + "\u01B2": "V", + "\u01B3": "Y", + "\u01B4": "y", + "\u01B5": "Z", + "\u01B6": "z", + "\u01C4": "DZ", + "\u01C5": "Dz", + "\u01C6": "dz", + "\u01C7": "LJ", + "\u01C8": "Lj", + "\u01C9": "lj", + "\u01CA": "NJ", + "\u01CB": "Nj", + "\u01CC": "nj", + "\u01CD": "A", + "\u01CE": "a", + "\u01CF": "I", + "\u01D0": "i", + "\u01D1": "O", + "\u01D2": "o", + "\u01D3": "U", + "\u01D4": "u", + "\u01D5": "U", + "\u01D6": "u", + "\u01D7": "U", + "\u01D8": "u", + "\u01D9": "U", + "\u01DA": "u", + "\u01DB": "U", + "\u01DC": "u", + "\u01DE": "A", + "\u01DF": "a", + "\u01E0": "A", + "\u01E1": "a", + "\u01E2": "AE", + "\u01E3": "ae", + "\u01E4": "G", + "\u01E5": "g", + "\u01E6": "G", + "\u01E7": "g", + "\u01E8": "K", + "\u01E9": "k", + "\u01EA": "O", + "\u01EB": "o", + "\u01EC": "O", + "\u01ED": "o", + "\u01F0": "j", + "\u01F1": "DZ", + "\u01F2": "Dz", + "\u01F3": "dz", + "\u01F4": "G", + "\u01F5": "g", + "\u01F8": "N", + "\u01F9": "n", + "\u01FA": "A", + "\u01FB": "a", + "\u01FC": "AE", + "\u01FD": "ae", + "\u01FE": "O", + "\u01FF": "o", + "\u0200": "A", + "\u0201": "a", + "\u0202": "A", + "\u0203": "a", + "\u0204": "E", + "\u0205": "e", + "\u0206": "E", + "\u0207": "e", + "\u0208": "I", + "\u0209": "i", + "\u020A": "I", + "\u020B": "i", + "\u020C": "O", + "\u020D": "o", + "\u020E": "O", + "\u020F": "o", + "\u0210": "R", + "\u0211": "r", + "\u0212": "R", + "\u0213": "r", + "\u0214": "U", + "\u0215": "u", + "\u0216": "U", + "\u0217": "u", + "\u0218": "S", + "\u0219": "s", + "\u021A": "T", + "\u021B": "t", + "\u021E": "H", + "\u021F": "h", + "\u0221": "d", + "\u0224": "Z", + "\u0225": "z", + "\u0226": "A", + "\u0227": "a", + "\u0228": "E", + "\u0229": "e", + "\u022A": "O", + "\u022B": "o", + "\u022C": "O", + "\u022D": "o", + "\u022E": "O", + "\u022F": "o", + "\u0230": "O", + "\u0231": "o", + "\u0232": "Y", + "\u0233": "y", + "\u0234": "l", + "\u0235": "n", + "\u0236": "t", + "\u0237": "j", + "\u0238": "db", + "\u0239": "qp", + "\u023A": "A", + "\u023B": "C", + "\u023C": "c", + "\u023D": "L", + "\u023E": "T", + "\u023F": "s", + "\u0240": "z", + "\u0243": "B", + "\u0244": "U", + "\u0246": "E", + "\u0247": "e", + "\u0248": "J", + "\u0249": "j", + "\u024C": "R", + "\u024D": "r", + "\u024E": "Y", + "\u024F": "y", + "\u0253": "b", + "\u0255": "c", + "\u0256": "d", + "\u0257": "d", + "\u025B": "e", + "\u025F": "j", + "\u0260": "g", + "\u0261": "g", + "\u0262": "G", + "\u0266": "h", + "\u0267": "h", + "\u0268": "i", + "\u026A": "I", + "\u026B": "l", + "\u026C": "l", + "\u026D": "l", + "\u0271": "m", + "\u0272": "n", + "\u0273": "n", + "\u0274": "N", + "\u0276": "OE", + "\u027C": "r", + "\u027D": "r", + "\u027E": "r", + "\u0280": "R", + "\u0282": "s", + "\u0288": "t", + "\u0289": "u", + "\u028B": "v", + "\u028F": "Y", + "\u0290": "z", + "\u0291": "z", + "\u0299": "B", + "\u029B": "G", + "\u029C": "H", + "\u029D": "j", + "\u029F": "L", + "\u02A0": "q", + "\u02A3": "dz", + "\u02A5": "dz", + "\u02A6": "ts", + "\u02AA": "ls", + "\u02AB": "lz", + "\u0400": "E", + "\u0401": "E", + "\u0402": "D", + "\u0403": "G", + "\u0404": "E", + "\u0405": "Z", + "\u0406": "I", + "\u0407": "I", + "\u0408": "J", + "\u0409": "L", + "\u040A": "N", + "\u040B": "C", + "\u040C": "K", + "\u040D": "I", + "\u040E": "U", + "\u040F": "D", + "\u0410": "A", + "\u0411": "B", + "\u0412": "V", + "\u0413": "G", + "\u0414": "D", + "\u0415": "E", + "\u0416": "Z", + "\u0417": "Z", + "\u0418": "I", + "\u0419": "J", + "\u041A": "K", + "\u041B": "L", + "\u041C": "M", + "\u041D": "N", + "\u041E": "O", + "\u041F": "P", + "\u0420": "R", + "\u0421": "S", + "\u0422": "T", + "\u0423": "U", + "\u0424": "F", + "\u0425": "H", + "\u0426": "C", + "\u0427": "C", + "\u0428": "S", + "\u0429": "S", + "\u042B": "Y", + "\u042D": "E", + "\u042E": "U", + "\u042F": "A", + "\u0430": "a", + "\u0431": "b", + "\u0432": "v", + "\u0433": "g", + "\u0434": "d", + "\u0435": "e", + "\u0436": "z", + "\u0437": "z", + "\u0438": "i", + "\u0439": "j", + "\u043A": "k", + "\u043B": "l", + "\u043C": "m", + "\u043D": "n", + "\u043E": "o", + "\u043F": "p", + "\u0440": "r", + "\u0441": "s", + "\u0442": "t", + "\u0443": "u", + "\u0444": "f", + "\u0445": "h", + "\u0446": "c", + "\u0447": "c", + "\u0448": "s", + "\u0449": "s", + "\u044A": '"', + "\u044B": "y", + "\u044C": "'", + "\u044D": "e", + "\u044E": "u", + "\u044F": "a", + "\u0450": "e", + "\u0451": "e", + "\u0452": "d", + "\u0453": "g", + "\u0454": "e", + "\u0455": "z", + "\u0456": "i", + "\u0457": "i", + "\u0458": "j", + "\u0459": "l", + "\u045A": "n", + "\u045B": "c", + "\u045C": "k", + "\u045D": "i", + "\u045E": "u", + "\u045F": "d", + "\u0490": "G", + "\u0491": "g", + "\u0492": "G", + "\u0493": "g", + "\u0494": "G", + "\u0495": "g", + "\u0498": "Z", + "\u0499": "z", + "\u04A2": "N", + "\u04A3": "n", + "\u04AE": "U", + "\u04AF": "u", + "\u04B0": "U", + "\u04B1": "u", + "\u04BA": "H", + "\u04BB": "h", + "\u04C1": "Z", + "\u04C2": "z", + "\u04D0": "A", + "\u04D1": "a", + "\u04D2": "A", + "\u04D3": "a", + "\u04D4": "AE", + "\u04D5": "ae", + "\u04D6": "E", + "\u04D7": "e", + "\u04DC": "Z", + "\u04DD": "z", + "\u04DE": "Z", + "\u04DF": "z", + "\u04E2": "I", + "\u04E3": "i", + "\u04E4": "I", + "\u04E5": "i", + "\u04E6": "O", + "\u04E7": "o", + "\u04E8": "O", + "\u04E9": "o", + "\u04EC": "E", + "\u04ED": "e", + "\u04EE": "U", + "\u04EF": "u", + "\u04F0": "U", + "\u04F1": "u", + "\u04F2": "U", + "\u04F3": "u", + "\u04F4": "C", + "\u04F5": "c", + "\u04F8": "Y", + "\u04F9": "y", + "\u1E00": "A", + "\u1E01": "a", + "\u1E02": "B", + "\u1E03": "b", + "\u1E04": "B", + "\u1E05": "b", + "\u1E06": "B", + "\u1E07": "b", + "\u1E08": "C", + "\u1E09": "c", + "\u1E0A": "D", + "\u1E0B": "d", + "\u1E0C": "D", + "\u1E0D": "d", + "\u1E0E": "D", + "\u1E0F": "d", + "\u1E10": "D", + "\u1E11": "d", + "\u1E12": "D", + "\u1E13": "d", + "\u1E14": "E", + "\u1E15": "e", + "\u1E16": "E", + "\u1E17": "e", + "\u1E18": "E", + "\u1E19": "e", + "\u1E1A": "E", + "\u1E1B": "e", + "\u1E1C": "E", + "\u1E1D": "e", + "\u1E1E": "F", + "\u1E1F": "f", + "\u1E20": "G", + "\u1E21": "g", + "\u1E22": "H", + "\u1E23": "h", + "\u1E24": "H", + "\u1E25": "h", + "\u1E26": "H", + "\u1E27": "h", + "\u1E28": "H", + "\u1E29": "h", + "\u1E2A": "H", + "\u1E2B": "h", + "\u1E2C": "I", + "\u1E2D": "i", + "\u1E2E": "I", + "\u1E2F": "i", + "\u1E30": "K", + "\u1E31": "k", + "\u1E32": "K", + "\u1E33": "k", + "\u1E34": "K", + "\u1E35": "k", + "\u1E36": "L", + "\u1E37": "l", + "\u1E38": "L", + "\u1E39": "l", + "\u1E3A": "L", + "\u1E3B": "l", + "\u1E3C": "L", + "\u1E3D": "l", + "\u1E3E": "M", + "\u1E3F": "m", + "\u1E40": "M", + "\u1E41": "m", + "\u1E42": "M", + "\u1E43": "m", + "\u1E44": "N", + "\u1E45": "n", + "\u1E46": "N", + "\u1E47": "n", + "\u1E48": "N", + "\u1E49": "n", + "\u1E4A": "N", + "\u1E4B": "n", + "\u1E4C": "O", + "\u1E4D": "o", + "\u1E4E": "O", + "\u1E4F": "o", + "\u1E50": "O", + "\u1E51": "o", + "\u1E52": "O", + "\u1E53": "o", + "\u1E54": "P", + "\u1E55": "p", + "\u1E56": "P", + "\u1E57": "p", + "\u1E58": "R", + "\u1E59": "r", + "\u1E5A": "R", + "\u1E5B": "r", + "\u1E5C": "R", + "\u1E5D": "r", + "\u1E5E": "R", + "\u1E5F": "r", + "\u1E60": "S", + "\u1E61": "s", + "\u1E62": "S", + "\u1E63": "s", + "\u1E64": "S", + "\u1E65": "s", + "\u1E66": "S", + "\u1E67": "s", + "\u1E68": "S", + "\u1E69": "s", + "\u1E6A": "T", + "\u1E6B": "t", + "\u1E6C": "T", + "\u1E6D": "t", + "\u1E6E": "T", + "\u1E6F": "t", + "\u1E70": "T", + "\u1E71": "t", + "\u1E72": "U", + "\u1E73": "u", + "\u1E74": "U", + "\u1E75": "u", + "\u1E76": "U", + "\u1E77": "u", + "\u1E78": "U", + "\u1E79": "u", + "\u1E7A": "U", + "\u1E7B": "u", + "\u1E7C": "V", + "\u1E7D": "v", + "\u1E7E": "V", + "\u1E7F": "v", + "\u1E80": "W", + "\u1E81": "w", + "\u1E82": "W", + "\u1E83": "w", + "\u1E84": "W", + "\u1E85": "w", + "\u1E86": "W", + "\u1E87": "w", + "\u1E88": "W", + "\u1E89": "w", + "\u1E8A": "X", + "\u1E8B": "x", + "\u1E8C": "X", + "\u1E8D": "x", + "\u1E8E": "Y", + "\u1E8F": "y", + "\u1E90": "Z", + "\u1E91": "z", + "\u1E92": "Z", + "\u1E93": "z", + "\u1E94": "Z", + "\u1E95": "z", + "\u1E96": "h", + "\u1E97": "t", + "\u1E98": "w", + "\u1E99": "y", + "\u1E9A": "a", + "\u1E9B": "s", + "\u1E9C": "s", + "\u1E9D": "s", + "\u1E9E": "SS", + "\u1EA0": "A", + "\u1EA1": "a", + "\u1EA2": "A", + "\u1EA3": "a", + "\u1EA4": "A", + "\u1EA5": "a", + "\u1EA6": "A", + "\u1EA7": "a", + "\u1EA8": "A", + "\u1EA9": "a", + "\u1EAA": "A", + "\u1EAB": "a", + "\u1EAC": "A", + "\u1EAD": "a", + "\u1EAE": "A", + "\u1EAF": "a", + "\u1EB0": "A", + "\u1EB1": "a", + "\u1EB2": "A", + "\u1EB3": "a", + "\u1EB4": "A", + "\u1EB5": "a", + "\u1EB6": "A", + "\u1EB7": "a", + "\u1EB8": "E", + "\u1EB9": "e", + "\u1EBA": "E", + "\u1EBB": "e", + "\u1EBC": "E", + "\u1EBD": "e", + "\u1EBE": "E", + "\u1EBF": "e", + "\u1EC0": "E", + "\u1EC1": "e", + "\u1EC2": "E", + "\u1EC3": "e", + "\u1EC4": "E", + "\u1EC5": "e", + "\u1EC6": "E", + "\u1EC7": "e", + "\u1EC8": "I", + "\u1EC9": "i", + "\u1ECA": "I", + "\u1ECB": "i", + "\u1ECC": "O", + "\u1ECD": "o", + "\u1ECE": "O", + "\u1ECF": "o", + "\u1ED0": "O", + "\u1ED1": "o", + "\u1ED2": "O", + "\u1ED3": "o", + "\u1ED4": "O", + "\u1ED5": "o", + "\u1ED6": "O", + "\u1ED7": "o", + "\u1ED8": "O", + "\u1ED9": "o", + "\u1EDA": "O", + "\u1EDB": "o", + "\u1EDC": "O", + "\u1EDD": "o", + "\u1EDE": "O", + "\u1EDF": "o", + "\u1EE0": "O", + "\u1EE1": "o", + "\u1EE2": "O", + "\u1EE3": "o", + "\u1EE4": "U", + "\u1EE5": "u", + "\u1EE6": "U", + "\u1EE7": "u", + "\u1EE8": "U", + "\u1EE9": "u", + "\u1EEA": "U", + "\u1EEB": "u", + "\u1EEC": "U", + "\u1EED": "u", + "\u1EEE": "U", + "\u1EEF": "u", + "\u1EF0": "U", + "\u1EF1": "u", + "\u1EF2": "Y", + "\u1EF3": "y", + "\u1EF4": "Y", + "\u1EF5": "y", + "\u1EF6": "Y", + "\u1EF7": "y", + "\u1EF8": "Y", + "\u1EF9": "y", + "\u1EFA": "LL", + "\u1EFB": "ll", + "\u1EFC": "V", + "\u1EFD": "v", + "\u1EFE": "Y", + "\u1EFF": "y", + "\u2000": " ", + "\u2001": " ", + "\u2002": " ", + "\u2003": " ", + "\u2004": " ", + "\u2005": " ", + "\u2006": " ", + "\u2007": " ", + "\u2008": " ", + "\u2009": " ", + "\u200A": " ", + "\u2010": "-", + "\u2011": "-", + "\u2012": "-", + "\u2013": "-", + "\u2014": "-", + "\u2015": "-", + "\u2016": "||", + "\u2018": "'", + "\u2019": "'", + "\u201A": ",", + "\u201B": "'", + "\u201C": '"', + "\u201D": '"', + "\u201E": ",,", + "\u201F": '"', + "\u2024": ".", + "\u2025": "..", + "\u2026": "...", + "\u2032": "'", + "\u2033": '"', + "\u2039": "<", + "\u203A": ">", + "\u203C": "!!", + "\u2044": "/", + "\u2045": "[", + "\u2046": "]", + "\u2047": "??", + "\u2048": "?!", + "\u2049": "!?", + "\u204E": "*", + "\u205F": " ", + "\u20A0": "CE", + "\u20A2": "Cr", + "\u20A3": "Fr.", + "\u20A4": "L.", + "\u20A7": "Pts", + "\u20B9": "Rs", + "\u20BA": "TL", + "\u2100": "a/c", + "\u2101": "a/s", + "\u2102": "C", + "\u2105": "c/o", + "\u2106": "c/u", + "\u210A": "g", + "\u210B": "H", + "\u210C": "x", + "\u210D": "H", + "\u210E": "h", + "\u2110": "I", + "\u2111": "I", + "\u2112": "L", + "\u2113": "l", + "\u2115": "N", + "\u2116": "No", + "\u2117": "(P)", + "\u2118": "P", + "\u2119": "P", + "\u211A": "Q", + "\u211B": "R", + "\u211C": "R", + "\u211D": "R", + "\u211E": "Rx", + "\u2121": "TEL", + "\u2124": "Z", + "\u2126": "O", + "\u2128": "Z", + "\u212A": "K", + "\u212B": "A", + "\u212C": "B", + "\u212D": "C", + "\u212F": "e", + "\u2130": "E", + "\u2131": "F", + "\u2133": "M", + "\u2134": "o", + "\u2139": "i", + "\u213B": "FAX", + "\u2145": "D", + "\u2146": "d", + "\u2147": "e", + "\u2148": "i", + "\u2149": "j" + }; + } +}); + +// node_modules/@markup-carve/carve/dist/unresolved-reference.js +function isUnresolvedReference(node) { + if (node.type === "link") + return node.ref !== void 0 && !node.href; + if (node.type === "image") + return node.ref !== void 0 && !node.src; + return false; +} +function referenceSourceText(rawRef) { + if (rawRef === void 0) + return ""; + if (!rawRef.includes("%%")) + return rawRef; + return rawRef.split("\n").map((line2) => RE_COMMENT_ONLY_LINE.test(line2) ? "" : line2).join("\n"); +} +var RE_COMMENT_ONLY_LINE; +var init_unresolved_reference = __esm({ + "node_modules/@markup-carve/carve/dist/unresolved-reference.js"() { + RE_COMMENT_ONLY_LINE = /^[ \t]*%%/; + } +}); // node_modules/@markup-carve/carve/dist/heading-ids.js function normalizeHeadingRefLabel(label) { - return normalizeRefLabel(label).toLowerCase(); + return normalizeRefLabel(label).normalize("NFC").toLowerCase(); +} +function headingRefKeyFromLabel(label) { + return normalizeHeadingRefLabel(derivedRefLabel(label)); +} +function derivedRefLabel(label) { + return inlineText(parseRefLabelInlines(label)); +} +function deepCloneInlines(nodes) { + return JSON.parse(JSON.stringify(nodes)); +} +function unwrapNestedAnchors(nodes, insideLink5) { + const out = []; + for (const n of nodes) { + switch (n.type) { + case "link": { + if (insideLink5 && isUnresolvedReference(n)) { + out.push({ type: "text", value: n.rawRef ?? "" }); + break; + } + const children = unwrapNestedAnchors(n.children, true); + if (insideLink5) { + for (const c of children) + out.push(c); + } else { + n.children = children; + out.push(n); + } + break; + } + case "heading_ref": + if (n.resolvedText) + n.resolvedText = unwrapNestedAnchors(n.resolvedText, true); + out.push(n); + break; + case "autolink": + if (insideLink5) { + const value = n.href.startsWith("mailto:") ? n.href.slice("mailto:".length) : n.href; + out.push({ type: "text", value }); + } else { + out.push(n); + } + break; + case "inline_footnote": + if (n.inline) + n.inline = unwrapNestedAnchors(n.inline, false); + out.push(n); + break; + case "emphasis": + case "strong": + case "underline": + case "strike": + case "superscript": + case "subscript": + case "highlight": + case "span": + case "insert": + case "delete": + n.children = unwrapNestedAnchors(n.children, insideLink5); + out.push(n); + break; + case "inline_extension": + n.content = unwrapNestedAnchors(n.content, insideLink5); + out.push(n); + break; + default: + out.push(n); + break; + } + } + return out; +} +function deriveDisplayNodes(nodes, insideLink5) { + return unwrapNestedAnchors(stripResolutionApparatus(deepCloneInlines(nodes)), insideLink5); +} +function stripResolutionApparatus(nodes) { + const out = []; + for (const n of nodes) { + if (n.type === "footnote_ref" || n.type === "inline_footnote") + continue; + if (n.type === "inline_extension" && n.name === "index") + continue; + if (n.type === "abbreviation") { + out.push({ type: "text", value: n.abbr }); + continue; + } + const record = n; + for (const key2 of Object.keys(record)) { + if (key2 === "pos") + continue; + const value = record[key2]; + if (Array.isArray(value)) + record[key2] = stripResolutionApparatus(value); + } + out.push(n); + } + return out; +} +function isCollapsedRef(ref, rawRef) { + return rawRef !== void 0 && rawRef.startsWith(`[${ref}][]`); } function transliterate(s) { let out = ""; @@ -13144,33 +15582,12 @@ function transliterate(s) { out += TRANSLIT_MAP[ch] ?? ch; return out; } -var SMART_TO_ASCII = { - "\u2194": "<->", - "\u2122": "(tm)", - "\u2026": "...", - "\u2192": "->", - "\u2190": "<-", - "\u21D2": "=>", - "\u2264": "<=", - "\u2265": ">=", - "\u2260": "!=", - "\xB1": "+-", - "\xA9": "(c)", - "\xAE": "(r)", - "\u2013": "-", - "\u2014": "-", - "\u2018": "'", - "\u2019": "'", - "\u201C": '"', - "\u201D": '"' -}; function deTypography(s) { let out = ""; for (const ch of s) out += SMART_TO_ASCII[ch] ?? ch; return out; } -var ID_STRIP_RE = /[\u202A-\u202E\u2066-\u2069\u200B\u200C\u200D\u2060\uFEFF\u00AD]/gu; function sanitizeIdSource(s) { return s.normalize("NFC").replace(ID_STRIP_RE, ""); } @@ -13188,8 +15605,8 @@ function headingIdSlugOpts(opts) { asciiStrict: v === "strict" }; } -function slugify(plainText2, opts = {}) { - let s = slugRun(deTypography(sanitizeIdSource(plainText2))); +function slugify(plainText3, opts = {}) { + let s = slugRun(deTypography(sanitizeIdSource(plainText3))); if (opts.asciiFold || opts.asciiStrict) { s = transliterate(s); s = opts.asciiStrict ? slugRunAscii(s) : slugRun(s); @@ -13209,8 +15626,18 @@ function inlineText(nodes) { switch (n.type) { case "text": case "code": + // The escape is authoring syntax; the heading still contains the + // character, and the id has always been slugified from what the reader + // sees. + case "escaped_text": out += n.value; break; + // The visible glyph, not the source run: a heading id has always been + // slugified from the rendered character (`Don't` -> `Don-t`), and moving + // the substitution into a node must not change that. + case "smart_punctuation": + out += n.glyph ?? SMART_PUNCTUATION_GLYPHS[n.kind] ?? n.value; + break; case "math": // An inline literal renders as visible prose (§27), so it contributes // its content to the heading text -- otherwise `` # !`Cat` `` would @@ -13243,10 +15670,16 @@ function inlineText(nodes) { out += n.abbr; break; case "mention": - out += n.user; + out += `@${n.user}`; break; case "tag": - out += n.name; + out += `#${n.name}`; + break; + case "autolink": + out += n.text; + break; + case "image": + out += n.alt; break; case "soft_break": case "hard_break": @@ -13255,7 +15688,7 @@ function inlineText(nodes) { case "caption_number": out += n.n === void 0 ? "" : String(n.n); break; - // image, autolink, footnote, crossref, critic-comment: no slug text + // footnote, crossref, critic_comment: no slug text default: break; } @@ -13297,9 +15730,9 @@ function resolveHeadingIds(doc, opts = {}) { if (inBlockquote) return; const plain = inlineText(heading.children); - const key = normalizeHeadingRefLabel(plain); - if (key && !headingRefs.has(key)) - headingRefs.set(key, id); + const key2 = normalizeHeadingRefLabel(plain); + if (key2 && !headingRefs.has(key2)) + headingRefs.set(key2, id); }; const assignIds = (blocks, inBlockquote) => { for (const b of blocks) { @@ -13327,6 +15760,9 @@ function resolveHeadingIds(doc, opts = {}) { if (b.target.type === "block_quote") assignIds(b.target.children, true); break; + case "figure_group": + assignIds(b.children, inBlockquote); + break; default: break; } @@ -13338,10 +15774,10 @@ function resolveHeadingIds(doc, opts = {}) { const id = node.attrs?.id; if (typeof id === "string") used.add(id); - for (const key of Object.keys(node)) { - if (key === "pos") + for (const key2 of Object.keys(node)) { + if (key2 === "pos") continue; - const v = node[key]; + const v = node[key2]; if (Array.isArray(v)) for (const el of v) reserveExplicitIds(el); @@ -13351,25 +15787,30 @@ function resolveHeadingIds(doc, opts = {}) { }; for (const b of doc.children) reserveExplicitIds(b); + for (const body of Object.values(doc.footnoteDefs ?? {})) + for (const b of body) + reserveExplicitIds(b); assignIds(doc.children, false); + for (const body of Object.values(doc.footnoteDefs ?? {})) + assignIds(body, false); const resolveRefs = (nodes) => { for (let i = 0; i < nodes.length; i++) { const n = nodes[i]; - if (n.type === "link" && n.ref !== void 0) { - const id = headingRefs.get(normalizeHeadingRefLabel(n.ref)); - if (id) { - n.href = `#${id}`; - delete n.ref; - delete n.rawRef; - } else { - nodes[i] = { type: "text", value: n.rawRef ?? "" }; - continue; + if (n.type === "link" && isUnresolvedReference(n)) { + if (isCollapsedRef(n.ref, n.rawRef)) { + const asWritten = headingRefs.get(normalizeHeadingRefLabel(n.ref)); + if (asWritten !== void 0) { + n.href = `#${asWritten}`; + } else { + const derived = derivedRefLabel(n.ref); + const id = headingRefs.get(normalizeHeadingRefLabel(derived)); + if (id !== void 0) { + n.href = `#${id}`; + n.ref = derived; + } + } } } - if (n.type === "image" && n.ref !== void 0) { - nodes[i] = { type: "text", value: n.rawRef ?? "" }; - continue; - } switch (n.type) { case "emphasis": case "strong": @@ -13387,7 +15828,7 @@ function resolveHeadingIds(doc, opts = {}) { case "inline_extension": resolveRefs(n.content); break; - case "footnote": + case "inline_footnote": if (n.inline) resolveRefs(n.inline); break; @@ -13422,7 +15863,7 @@ function resolveHeadingIds(doc, opts = {}) { case "inline_extension": flattenNestedCrossrefs(n.content); break; - case "footnote": + case "inline_footnote": if (n.inline) flattenNestedCrossrefs(n.inline); break; @@ -13431,6 +15872,14 @@ function resolveHeadingIds(doc, opts = {}) { } } }; + const stripPositions2 = (nodes) => { + for (const node of nodes) { + delete node.pos; + const children = node.children; + if (Array.isArray(children)) + stripPositions2(children); + } + }; const resolveCrossrefs = (nodes) => { for (let i = 0; i < nodes.length; i++) { const n = nodes[i]; @@ -13441,20 +15890,13 @@ function resolveHeadingIds(doc, opts = {}) { let children = crossrefCloneCache.get(tgtId); if (!children) { const source = pristineTargets.get(tgtId) ?? tgt; - children = JSON.parse(JSON.stringify(source)); + children = deepCloneInlines(source); flattenNestedCrossrefs(children); + stripPositions2(children); crossrefCloneCache.set(tgtId, children); } - const link = { - type: "link", - href: `#${tgtId}`, - children, - fromCrossref: true - }; - nodes[i] = link; - } else { - const txt = { type: "text", value: `` }; - nodes[i] = txt; + n.href = `#${tgtId}`; + n.resolvedText = children; } continue; } @@ -13475,7 +15917,7 @@ function resolveHeadingIds(doc, opts = {}) { case "inline_extension": resolveCrossrefs(n.content); break; - case "footnote": + case "inline_footnote": if (n.inline) resolveCrossrefs(n.inline); break; @@ -13484,35 +15926,39 @@ function resolveHeadingIds(doc, opts = {}) { } } }; - const walkBlock = (b, fn) => { + const walkBlock2 = (b, fn) => { switch (b.type) { case "heading": case "paragraph": + // A bibliography entry's inlines are rendered - in the references list - + // so a `` crossref or a `[Heading][]` reference in one resolves + // like any other. The line reached this walk as a paragraph before PART + // 12 §18 made it its own node, and skipping it here would leave the + // reference rendering as its own source text. + case "citation_definition": fn(b.children); break; case "block_quote": - if (b.attribution) - fn(b.attribution); - b.children.forEach((c) => walkBlock(c, fn)); + b.children.forEach((c) => walkBlock2(c, fn)); break; case "list": - for (const item of b.items) - item.children.forEach((c) => walkBlock(c, fn)); + for (const item2 of b.items) + item2.children.forEach((c) => walkBlock2(c, fn)); break; case "admonition": if (b.title) fn(b.title); - b.children.forEach((c) => walkBlock(c, fn)); + b.children.forEach((c) => walkBlock2(c, fn)); break; case "div": - b.children.forEach((c) => walkBlock(c, fn)); + b.children.forEach((c) => walkBlock2(c, fn)); break; case "definition_list": for (const it of b.items) { for (const t of it.terms) fn(t); for (const d of it.definitions) - d.forEach((c) => walkBlock(c, fn)); + d.forEach((c) => walkBlock2(c, fn)); } break; case "table": @@ -13525,7 +15971,12 @@ function resolveHeadingIds(doc, opts = {}) { case "figure": fn(b.caption); if (b.target.type === "block_quote" || b.target.type === "table") - walkBlock(b.target, fn); + walkBlock2(b.target, fn); + break; + case "figure_group": + if (b.caption) + fn(b.caption); + b.children.forEach((c) => walkBlock2(c, fn)); break; default: break; @@ -13533,145 +15984,42 @@ function resolveHeadingIds(doc, opts = {}) { }; const footnoteBodies = doc.footnoteDefs ? Object.values(doc.footnoteDefs) : []; const counters = /* @__PURE__ */ new Map(); - const numberCaption = (caption, attrs) => { - const idx = caption.findIndex((n) => n.type === "caption_number"); - if (idx === -1) - return; - const labelNodes = caption.slice(0, idx); - const label = inlineText(labelNodes).replace(/\s+$/, ""); - const next = (counters.get(label) ?? 0) + 1; - counters.set(label, next); - caption[idx].n = next; - const id = attrs?.id; - if (id !== void 0 && !targets.has(id)) { + const numberBlocks = (blocks) => { + numberCaptionsIn(blocks, counters, (labelNodes, next, attrs, suffix) => { + const id = attrs?.id; + if (id === void 0 || targets.has(id)) + return; const autoNodes = labelNodes.map((n) => ({ ...n })); const last = autoNodes[autoNodes.length - 1]; if (last && last.type === "text") { - last.value = last.value.replace(/\s+$/, ""); + last.value = last.value.replace(RE_TRAILING_LABEL_WS, ""); } - autoNodes.push({ type: "text", value: ` ${next}` }); + autoNodes.push({ type: "text", value: ` ${next}${suffix ?? ""}` }); targets.set(id, autoNodes); - } - }; - const numberBlocks = (blocks) => { - for (const b of blocks) { - if (b.type === "figure") { - numberCaption(b.caption, b.attrs); - } else if (b.type === "table" && b.caption) { - numberCaption(b.caption, b.attrs); - } - switch (b.type) { - case "block_quote": - case "admonition": - case "div": - numberBlocks(b.children); - break; - case "list": - for (const it of b.items) - numberBlocks(it.children); - break; - case "definition_list": - for (const it of b.items) - for (const d of it.definitions) - numberBlocks(d); - break; - case "figure": - if (b.target.type === "block_quote") - numberBlocks(b.target.children); - else if (b.target.type === "table" && b.target.caption) - numberCaption(b.target.caption, b.target.attrs); - break; - default: - break; - } - } + }); }; for (const block of doc.children) - walkBlock(block, resolveRefs); + walkBlock2(block, resolveRefs); for (const body of footnoteBodies) for (const b of body) - walkBlock(b, resolveRefs); + walkBlock2(b, resolveRefs); numberBlocks(doc.children); for (const body of footnoteBodies) numberBlocks(body); for (const [id, children] of targets) - pristineTargets.set(id, JSON.parse(JSON.stringify(children))); + pristineTargets.set(id, deepCloneInlines(children)); for (const children of targets.values()) resolveCrossrefs(children); for (const block of doc.children) - walkBlock(block, resolveCrossrefs); - for (const body of footnoteBodies) - for (const b of body) - walkBlock(b, resolveCrossrefs); - const enforceNoNesting = (nodes, insideLink) => { - const out = []; - for (const n of nodes) { - switch (n.type) { - case "link": { - const children = enforceNoNesting(n.children, true); - if (insideLink) { - for (const c of children) - out.push(c); - } else { - n.children = children; - out.push(n); - } - break; - } - case "autolink": - if (insideLink) { - const value = n.href.startsWith("mailto:") ? n.href.slice("mailto:".length) : n.href; - out.push({ type: "text", value }); - } else { - out.push(n); - } - break; - case "footnote": - if (n.inline) - n.inline = enforceNoNesting(n.inline, false); - out.push(n); - break; - case "emphasis": - case "strong": - case "underline": - case "strike": - case "superscript": - case "subscript": - case "highlight": - case "span": - case "insert": - case "delete": - n.children = enforceNoNesting(n.children, insideLink); - out.push(n); - break; - case "inline_extension": - n.content = enforceNoNesting(n.content, insideLink); - out.push(n); - break; - default: - out.push(n); - break; - } - } - return out; - }; - const applyNoNesting = (xs) => { - const next = enforceNoNesting(xs, false); - xs.length = 0; - for (const n of next) - xs.push(n); - }; - for (const block of doc.children) - walkBlock(block, applyNoNesting); + walkBlock2(block, resolveCrossrefs); for (const body of footnoteBodies) for (const b of body) - walkBlock(b, applyNoNesting); + walkBlock2(b, resolveCrossrefs); promoteBlockImages(doc.children); for (const body of footnoteBodies) promoteBlockImages(body); return doc; } -var RE_HAS_CONTENT = /[^ \t\n\r\f]/; function captionFirstLineHasContent(children) { const afterMarker = children[2].value.replace(/^\^ +/, ""); if (RE_HAS_CONTENT.test(afterMarker)) @@ -13689,10 +16037,12 @@ function promoteBlockImages(blocks, figuresOnly = false) { for (let i = 0; i < blocks.length; i++) { const b = blocks[i]; if (!figuresOnly && b.type === "paragraph" && b.children.length === 1 && b.children[0].type === "image" && // Only a REAL image (direct or resolved reference) promotes; an - // unresolved reference image keeps its `ref` and renders as literal text - // (in HTML mode it is already a Text node here, so this only matters for - // the parse-only formatter path, where the unresolved Image survives). - !b.children[0].ref) { + // unresolved reference image renders as literal text (in HTML mode it is + // already a Text node here, so this only matters for the parse-only + // formatter path, where the unresolved Image survives). UNRESOLVED means + // no destination: PART 12 §3a keeps `ref` on a resolved reference too + // (carve#596). + !isUnresolvedReference(b.children[0])) { const img = b.children[0]; if (b.attrs) img.attrs = mergeAttrs(b.attrs, img.attrs ?? {}); @@ -13701,7 +16051,7 @@ function promoteBlockImages(blocks, figuresOnly = false) { } if (b.type === "paragraph" && b.children.length >= 3 && b.children[0].type === "image" && // A REAL image only (see above): an unresolved reference is literal text, // not a figure target. - !b.children[0].ref && // Strict column-0 rule: an image+caption forms a
    ONLY when the + !isUnresolvedReference(b.children[0]) && // Strict column-0 rule: an image+caption forms a
    ONLY when the // image begins at its container's content column. parseParagraph strips a // paragraph's leading indentation, so the AST text alone can't tell an // indented image+caption (which must stay literal) from a flush one; the @@ -13723,9 +16073,20 @@ function promoteBlockImages(blocks, figuresOnly = false) { const stripped = first.value.replace(/^\^ +/, ""); if (stripped === "") caption.shift(); - else - caption[0] = { ...first, value: stripped }; + else { + const removed = first.value.length - stripped.length; + const pos = first.pos ? { + ...first.pos, + // Each field is optional on its own, so advance only what is there + // rather than inventing a zero origin for a missing one. + ...first.pos.startOffset !== void 0 ? { startOffset: first.pos.startOffset + removed } : {}, + ...first.pos.startColumn !== void 0 ? { startColumn: first.pos.startColumn + removed } : {} + } : void 0; + caption[0] = pos ? { ...first, value: stripped, pos } : { ...first, value: stripped }; + } const figure = { type: "figure", target: b.children[0], caption }; + if (b.pos) + figure.pos = b.pos; if (b.attrs) figure.attrs = b.attrs; blocks[i] = figure; @@ -13735,11 +16096,12 @@ function promoteBlockImages(blocks, figuresOnly = false) { case "block_quote": case "admonition": case "div": + case "figure_group": promoteBlockImages(b.children, figuresOnly); break; case "list": - for (const item of b.items) - promoteBlockImages(item.children, figuresOnly); + for (const item2 of b.items) + promoteBlockImages(item2.children, figuresOnly); break; case "definition_list": for (const it of b.items) @@ -13751,961 +16113,26241 @@ function promoteBlockImages(blocks, figuresOnly = false) { } } } +function panelLetter(k) { + let s = ""; + k++; + while (k > 0) { + k--; + s = String.fromCharCode(97 + k % 26) + s; + k = Math.floor(k / 26); + } + return s; +} +function figureGroupPanels(group) { + return group.children.filter((c) => c.type === "figure" || c.type === "table"); +} +function numberCaptionsIn(blocks, counters, onNumbered) { + const numberCaption = (caption, attrs) => { + const idx = caption.findIndex((n) => n.type === "caption_number"); + if (idx === -1) + return void 0; + const labelNodes = caption.slice(0, idx); + const label = inlineText(labelNodes).replace(RE_TRAILING_LABEL_WS, ""); + const next = (counters.get(label) ?? 0) + 1; + counters.set(label, next); + caption[idx].n = next; + onNumbered?.(labelNodes, next, attrs); + return idx; + }; + const walk2 = (bs, inPanel) => { + for (const b of bs) { + if (b.type === "figure") { + if (!inPanel) + numberCaption(b.caption, b.attrs); + } else if (b.type === "table" && b.caption) { + if (!inPanel) + numberCaption(b.caption, b.attrs); + } + switch (b.type) { + case "block_quote": + case "admonition": + case "div": + walk2(b.children, inPanel); + break; + case "list": + for (const it of b.items) + walk2(it.children, inPanel); + break; + case "definition_list": + for (const it of b.items) + for (const d of it.definitions) + walk2(d, inPanel); + break; + case "figure": + if (b.target.type === "block_quote") + walk2(b.target.children, inPanel); + else if (b.target.type === "table" && b.target.caption && !inPanel) { + numberCaption(b.target.caption, b.target.attrs); + } + break; + case "figure_group": { + const panels = figureGroupPanels(b); + if (!inPanel && b.caption) { + const labelIdx = numberCaption(b.caption, b.attrs); + if (labelIdx !== void 0 && onNumbered) { + const labelNodes = b.caption.slice(0, labelIdx); + const n = b.caption[labelIdx].n; + panels.forEach((panel, k) => { + onNumbered(labelNodes, n, panel.attrs, panelLetter(k)); + }); + } + } + for (const c of b.children) { + const isPanel2 = c.type === "figure" || c.type === "table"; + walk2([c], inPanel || isPanel2); + } + break; + } + default: + break; + } + } + }; + walk2(blocks, false); +} +var SMART_TO_ASCII, ID_STRIP_RE, RE_HAS_CONTENT, RE_TRAILING_LABEL_WS; +var init_heading_ids = __esm({ + "node_modules/@markup-carve/carve/dist/heading-ids.js"() { + init_ast(); + init_parse(); + init_translit_map(); + init_unresolved_reference(); + SMART_TO_ASCII = { + "\u2194": "<->", + "\u2122": "(tm)", + "\u2026": "...", + "\u2192": "->", + "\u2190": "<-", + "\u21D2": "=>", + "\u2264": "<=", + "\u2265": ">=", + "\u2260": "!=", + "\xB1": "+-", + "\xA9": "(c)", + "\xAE": "(r)", + "\u2013": "-", + "\u2014": "-", + "\u2018": "'", + "\u2019": "'", + "\u201C": '"', + "\u201D": '"' + }; + ID_STRIP_RE = /[\u202A-\u202E\u2066-\u2069\u200B\u200C\u200D\u2060\uFEFF\u00AD]/gu; + RE_HAS_CONTENT = /[^ \t\n\r]/; + RE_TRAILING_LABEL_WS = /[ \t\n\r]+$/; + } +}); -// node_modules/@markup-carve/carve/dist/profile.js -var CANONICAL_BLOCK_TYPES = [ - "paragraph", - "heading", - "code_block", - "block_quote", - "list", - "list_item", - "table", - "table_row", - "table_cell", - "thematic_break", - "div", - "raw_block", - "footnote", - "definition_list", - "definition_term", - "definition_description", - "section", - "line_block", - "comment", - "figure", - "caption" -]; -var CANONICAL_INLINE_TYPES = [ - "text", - "emphasis", - "strong", - "underline", - "strike", - "inline_extension", - "mention", - "code", - "link", - "image", - "soft_break", - "hard_break", - "raw_inline", - "escaped_text", - "footnote_ref", - "inline_footnote", - "span", - "superscript", - "subscript", - "highlight", - "insert", - "delete", - "symbol", - "math", - "abbreviation" -]; -var BLOCK_SET = new Set(CANONICAL_BLOCK_TYPES); -var INLINE_SET = new Set(CANONICAL_INLINE_TYPES); - -// node_modules/@markup-carve/carve/dist/render-html.js -var DANGEROUS_URL_SCHEMES = [ - // Script / inline-content / local-file vectors. - "javascript", - "vbscript", - "data", - "file", - // OS protocol-handler / command-execution schemes (CVE-2026-20841 class). - "ms-msdt", - "ms-office", - "ms-word", - "ms-excel", - "ms-powerpoint", - "ms-access", - "ms-visio", - "ms-project", - "ms-publisher", - "ms-infopath", - "ms-spd", - "ms-search", - "search-ms", - "ms-cxh", - "ms-cxh-full", - "shell", - "vscode", - "vscode-insiders", - "jar" -]; -var DANGEROUS_VALUE_SCHEMES = new Set(DANGEROUS_URL_SCHEMES); - -// node_modules/@markup-carve/carve/dist/djot-migrate.js -var RULES = [ - // `C(x)` = a content run that may cross soft line breaks (Carve's - // parseInline parses emphasis across them) but never a blank line, - // and never the delimiter char `x`. - { - id: "markdown-strong-double-star", - category: "carve-breakage", - family: "*", - pattern: /\*\*(?!\s)((?:(?!\n[ \t]*\n)[^*])+?)(? "Djot/Markdown `**strong**` is not Carve bold \u2014 Carve bold is a single `*`, so this renders with literal asterisks.", - suggestion: (m) => `*${m[1]}*`, - delims: ["*", "*"] - }, - { - id: "markdown-strikethrough-double-tilde", - category: "carve-breakage", - family: "~", - pattern: /~~(?!\s)((?:(?!\n[ \t]*\n)[^~])+?)(? "Markdown `~~strikethrough~~` is not Carve \u2014 Carve strikethrough is a single `~`.", - suggestion: (m) => `~${m[1]}~`, - delims: ["~", "~"] - }, - { - id: "djot-subscript-tilde", - category: "djot-shift", - family: "~", - pattern: /~(?!\s)((?:(?!\n[ \t]*\n)[^~])+?)(? "Djot subscript `~x~` renders as *strikethrough* in Carve.", - // Forced brace form: a Djot `~x~` is often intraword (e.g. H~2~O), where a - // bare `,x,` would be literal in Carve; `{,x,}` renders in every position. - suggestion: (m) => `{,${m[1]},}`, - delims: ["{,", ",}"] - }, - { - id: "djot-superscript-caret", - // Breakage: `^x^` silently drops the superscript (Carve superscript is the - // braced `{^x^}`), so the intended markup never renders. - category: "carve-breakage", - family: "^", - // Exclude `^[` (a Carve inline footnote, not a superscript opener), the - // braced `{^x^}` form, which is valid in both languages, and carets that - // belong to footnote references (`[^x] … [^y]` must not pair up as a - // superscript span across the paragraph). - pattern: /(? "Djot superscript `^x^` is literal text in Carve \u2014 Carve superscript is the braced `{^x^}` only.", - suggestion: (m) => `{^${m[1]}^}`, - delims: ["{^", "^}"] - }, - { - id: "djot-emphasis-underscore", - category: "djot-shift", - family: "_", - pattern: /(? "Djot emphasis `_x_` renders as *underline* in Carve.", - suggestion: (m) => `/${m[1]}/`, - delims: ["/", "/"] - }, - { - id: "djot-highlight-braces", - category: "djot-shift", - family: "{", - pattern: /\{=(?!\s)((?:(?!\n[ \t]*\n)[\s\S])+?)(? "Djot highlight `{=x=}` is also Carve highlight (`{=x=}`).", - // Identity: the braced highlight form is valid Carve as-is and renders in - // every position, so it is kept rather than reduced to a bare `=x=` (which - // would be literal intraword). - suggestion: (m) => `{=${m[1]}=}`, - delims: ["{=", "=}"] - }, - // Block-level (line-anchored): a leading `+ content` is a bullet in - // Djot/Markdown but NOT in Carve — `+` is the list-continuation marker, so - // the line renders as a paragraph. A lone `+` (no content) is excluded: that - // IS the Carve continuation marker and is intentional. - { - id: "djot-plus-bullet", - category: "carve-breakage", - family: "plus-bullet", - pattern: /(?<=^[ \t]*)(\+)(?=[ \t]+\S)/gmd, - message: () => "Djot/Markdown `+` bullet is not a Carve bullet (`+` is the list-continuation marker) \u2014 this line renders as a paragraph.", - suggestion: () => "-" - } - // NOTE: full Djot reference links `[text][ref]` are NOT flagged — Carve - // resolves them identically against a `[ref]: url` definition (corpus - // 34-reference-link), so there is no silent mis-render. Math (`$`x``) - // and editorial `{+ +}`/`{- -}` are likewise identical and unflagged. -]; -var blanks = (s) => s.replace(/[^\n]/g, " "); -function maskCode(src) { - const lines = src.split("\n"); - let fence = null; - const staged = lines.map((line) => { - if (fence) { - const close = line.match(/^ {0,3}([`~]{3,})[ \t]*$/); - if (close && close[1][0] === fence.ch && close[1].length >= fence.len) { - fence = null; +// node_modules/@markup-carve/carve/dist/citations.js +function isLabelBoundary(ch) { + if (ch === void 0 || ch === " " || ch === " ") + return true; + if (ch >= "0" && ch <= "9") + return true; + return ch === "\xA7" || ch === "\xB6"; +} +function parseLocator(loc) { + const s = loc.replace(/^\s+/, ""); + const lower = s.toLowerCase(); + let label; + let rest = s; + for (const [m, canon] of FLAT_TERMS) { + if (lower.startsWith(m.toLowerCase()) && isLabelBoundary(s[m.length])) { + label = canon; + rest = s.slice(m.length).replace(/^[ \t]+/, ""); + break; + } + } + if (label === void 0) { + const c = rest[0]; + if (c !== void 0 && c >= "0" && c <= "9") + label = "page"; + } + if (label === void 0) + return s === "" ? {} : { suffixText: s }; + let i = 0; + while (i < rest.length && VALUE_CHAR.test(rest[i])) + i++; + const value = rest.slice(0, i).replace(/[ ,&\-.]+$/, ""); + const suffixText = rest.slice(i).replace(/^[ \t]+/, ""); + const out = { label }; + if (value !== "") + out.value = value; + if (suffixText !== "") + out.suffixText = suffixText; + return out; +} +function citations(opts = {}) { + const mode = opts.mode ?? "numbered"; + const hasBib = opts.bibliography !== void 0; + const pool = opts.bibliography ?? []; + const defs = /* @__PURE__ */ new Map(); + const numbers = /* @__PURE__ */ new Map(); + const order = []; + const uses = /* @__PURE__ */ new Map(); + const citeIds = /* @__PURE__ */ new Map(); + const refIds = /* @__PURE__ */ new Map(); + let idsReserved = false; + const reserveIds = (ctx) => { + if (idsReserved) + return; + for (const [key2, count] of uses) { + for (let n = 1; n <= count; n++) { + citeIds.set(`${key2}-${n}`, ctx.uniqueId(`cite-${key2}-${n}`)); } - return blanks(line); } - const open = line.match(/^(\s*)(`{3,}|~{3,})\s*([a-zA-Z0-9_+#.-]*)\s*$/); - if (open) { - fence = { ch: open[2][0], len: open[2].length }; - return blanks(line); + for (const key2 of order) + refIds.set(key2, ctx.uniqueId(`ref-${key2}`)); + idsReserved = true; + }; + return { + name: "citations", + matchInline: matchCitation, + afterParse(doc) { + defs.clear(); + numbers.clear(); + order.length = 0; + uses.clear(); + citeIds.clear(); + refIds.clear(); + idsReserved = false; + collectDefs(doc.children, defs); + for (const e of pool) { + if (e && typeof e.id === "string" && !defs.has(e.id)) + defs.set(e.id, cslToDef(e)); + } + return doc; + }, + beforeRender(doc) { + const numberingTargets = [ + ...doc.children, + ...Object.values(doc.footnoteDefs ?? {}).flat() + ]; + for (const block of numberingTargets) { + if (block.type === "citation_definition") + continue; + walkCitationGroups(block, (g) => { + if (!g.items.every((it) => defs.has(it.key))) + return; + for (const item2 of g.items) { + if (!numbers.has(item2.key)) { + numbers.set(item2.key, numbers.size + 1); + order.push(item2.key); + } + item2.number = numbers.get(item2.key); + if (hasBib) { + const n = (uses.get(item2.key) ?? 0) + 1; + uses.set(item2.key, n); + item2.useIndex = n; + } + } + }); + } + if (order.length === 0) + return doc; + const carrier = { + type: "div", + attrs: { keyValues: { [REFS_MARK]: "" } }, + children: [] + }; + const explicit = doc.children.find((b) => b.type === "div" && hasClass(b, "references") || b.type === "admonition" && b.kind === "references"); + if (explicit) + explicit.children.push(carrier); + else + doc.children.push(carrier); + return doc; + }, + inlineRenderers: { + "citation_group": (node, ctx) => { + reserveIds(ctx); + return renderGroup(node, ctx, mode, numbers, defs, hasBib, citeIds, refIds); + } + }, + blockRenderers: { + div: (node, ctx) => { + const kv = node.attrs?.keyValues; + if (kv && REFS_MARK in kv) { + reserveIds(ctx); + return renderRefsList(ctx, mode, order, defs, uses, hasBib, citeIds, refIds); + } + return void 0; + } } - return line; - }); - const s = staged.join("\n"); - const out = s.split(""); - const runLen = (i2) => { - let n = 0; - while (s[i2 + n] === "`") - n++; - return n; }; - let i = 0; - while (i < s.length) { - if (s[i] !== "`") { +} +function buildBracketMap2(text) { + const stack = []; + const map = {}; + for (let i = 0; i < text.length; i++) { + const c = text[i]; + if (c === "\\") { i++; continue; } - const len = runLen(i); - let j = i + len; - let closed = -1; - while (j < s.length) { - if (s[j] === "`" && runLen(j) === len) { - closed = j; - break; - } - j++; + if (c === "[") + stack.push(i); + else if (c === "]") { + const open = stack.pop(); + if (open !== void 0) + map[open] = i; } - if (closed === -1) { - i += len; + } + return map; +} +function bracketMapFor(text) { + if (text !== lastBracketMapText) { + lastBracketMap = buildBracketMap2(text); + lastBracketMapText = text; + } + return lastBracketMap; +} +function parseItem(raw, ctx) { + const m = ITEM_RE.exec(raw.trim()); + if (!m) + return null; + const prefixText = m[1].replace(/\s+$/, ""); + const item2 = { key: m[3], suppressAuthor: m[2] === "-" }; + if (prefixText !== "") + item2.prefix = ctx.parseInlines(prefixText); + const locRaw = m[4]; + if (locRaw !== void 0 && locRaw.trim() !== "") { + item2.locator = ctx.parseInlines(locRaw.trim()); + const p = parseLocator(locRaw); + if (p.label !== void 0) + item2.locatorLabel = p.label; + if (p.value !== void 0) + item2.locatorValue = p.value; + if (p.suffixText !== void 0) + item2.suffix = ctx.parseInlines(p.suffixText); + } + return item2; +} +function runPieceText(n) { + if (n.type === "text") + return n.value; + if (n.type === "smart_punctuation") + return n.glyph ?? SMART_PUNCTUATION_GLYPHS[n.kind] ?? n.value; + return null; +} +function takeLeadingAttrBlock(rest) { + let flat = ""; + let spanned = 0; + for (const n of rest) { + const piece = runPieceText(n); + if (piece === null) + break; + flat += piece; + spanned++; + } + const am = ATTR_RE.exec(flat); + if (!am) + return null; + let remaining = am[0].length; + let index2 = 0; + while (index2 < spanned && remaining > 0) { + const piece = runPieceText(rest[index2]); + if (piece.length <= remaining) { + remaining -= piece.length; + index2++; continue; } - for (let k = i; k < closed + len; k++) - if (out[k] !== "\n") - out[k] = " "; - i = closed + len; + const node = rest[index2]; + if (node.type !== "text") + break; + node.value = piece.slice(remaining); + advanceStart(node, piece.slice(0, remaining)); + remaining = 0; } - let masked = out.join(""); - masked = masked.replace(/(?<=\])\([^()\n]*\)/g, (g) => blanks(g)); - return masked; -} -function stripHit(h) { - return { - line: h.line, - column: h.column, - rule: h.rule, - category: h.category, - message: h.message, - suggestion: h.suggestion, - start: h.start, - end: h.end - }; + rest.splice(0, index2); + return am[1]; } -function djotMigrationWarnings(source) { - return scanHits(source).map(stripHit); +function promoteCitationDefinitions(blocks) { + let out = null; + for (let i = 0; i < blocks.length; i++) { + const block = blocks[i]; + const promoted = block.type === "paragraph" ? promoteParagraph(block) : null; + if (promoted === null) { + out?.push(block); + continue; + } + if (!out) + out = blocks.slice(0, i); + for (const node of promoted) + out.push(node); + } + return out ?? blocks; } -function scanHits(source) { +function promoteParagraph(paragraph) { + if (!paragraph.children.some((n) => n.type === "citation_group")) + return null; + const lines = splitOnSoftBreaks(paragraph.children); const out = []; - const norm = source.replace(/\r\n?/g, "\n"); - const masked = maskCode(norm); - const nlAt = []; - for (let k = 0; k < masked.length; k++) - if (masked[k] === "\n") - nlAt.push(k); - const posOf = (idx) => { - let lo = 0; - let hi = nlAt.length; - while (lo < hi) { - const mid = lo + hi >> 1; - if (nlAt[mid] < idx) - lo = mid + 1; - else - hi = mid; - } - const lineStart = lo === 0 ? 0 : nlAt[lo - 1] + 1; - return { line: lo + 1, column: idx - lineStart + 1 }; - }; - const takenByFamily = /* @__PURE__ */ new Map(); - const sameFamilyOverlap = (s, e, fam) => { - const list = takenByFamily.get(fam); - if (!list || list.length === 0) - return false; - let lo = 0; - let hi = list.length; - while (lo < hi) { - const mid = lo + hi >> 1; - if (list[mid][0] < e) - lo = mid + 1; - else - hi = mid; - } - if (lo === 0) - return false; - return list[lo - 1][1] > s; - }; - const recordTaken = (s, e, fam) => { - let list = takenByFamily.get(fam); - if (!list) { - list = []; - takenByFamily.set(fam, list); - } - if (list.length === 0 || s >= list[list.length - 1][0]) { - list.push([s, e]); - return; - } - let lo = 0; - let hi = list.length; - while (lo < hi) { - const mid = lo + hi >> 1; - if (list[mid][0] < s) - lo = mid + 1; - else - hi = mid; - } - list.splice(lo, 0, [s, e]); - }; - for (const rule of RULES) { - rule.pattern.lastIndex = 0; - let m; - while (m = rule.pattern.exec(masked)) { - const start = m.index; - const end = m.index + m[0].length; - let bs = 0; - for (let k = start - 1; k >= 0 && masked[k] === "\\"; k--) - bs++; - if (bs % 2 === 1) - continue; - if (sameFamilyOverlap(start, end, rule.family)) - continue; - recordTaken(start, end, rule.family); - const { line, column } = posOf(start); - const span = m.indices?.[1]; - const orig = span ? norm.slice(span[0], span[1]) : m[1]; - const origM = m.slice(); - origM[1] = orig; - const suggestion = rule.suggestion(origM); - const edits = rule.delims && span ? [ - { start, end: span[0], text: rule.delims[0] }, - { start: span[1], end, text: rule.delims[1] } - ] : [{ start, end, text: suggestion }]; - out.push({ - line, - column, - rule: rule.id, - category: rule.category, - message: rule.message(m), - suggestion, - start, - end, - edits - }); + const kept = []; + let paragraphSlot = -1; + for (const line2 of lines) { + const def = definitionNode(line2); + if (def) { + out.push(def); + continue; } + if (kept.length === 0) + paragraphSlot = out.length; + kept.push(line2); + } + if (out.length === 0) + return null; + if (kept.length > 0) { + paragraph.children = joinWithSoftBreaks(kept); + repositionParagraph(paragraph); + out.splice(paragraphSlot, 0, paragraph); } - out.sort((a, b) => a.line - b.line || a.column - b.column); return out; } -function applyMigrationFixes(source) { - const hits = scanHits(source); - const crossed = /* @__PURE__ */ new Set(); - const active = []; - for (const b of hits) { - let drop = 0; - while (drop < active.length && active[drop].end <= b.start) - drop++; - if (drop > 0) - active.splice(0, drop); - for (const a of active) { - if (a.start === b.start) - continue; - if (a.end < b.end) { - crossed.add(a); - crossed.add(b); - } - } - let lo = 0; - let hi = active.length; - while (lo < hi) { - const mid = lo + hi >> 1; - if (active[mid].end < b.end) - lo = mid + 1; - else - hi = mid; - } - active.splice(lo, 0, b); +function repositionParagraph(paragraph) { + if (!paragraph.pos) + return; + const kids = paragraph.children; + if (!kids.every((child) => child.pos !== void 0)) + return; + const first = kids[0]?.pos; + const last = kids[kids.length - 1]?.pos; + if (!first || !last) + return; + paragraph.pos.startLine = first.startLine; + paragraph.pos.endLine = last.endLine; + if (first.startColumn !== void 0) + paragraph.pos.startColumn = first.startColumn; + if (first.startOffset !== void 0) + paragraph.pos.startOffset = first.startOffset; + if (last.endColumn !== void 0) + paragraph.pos.endColumn = last.endColumn; + if (last.endOffset !== void 0) + paragraph.pos.endOffset = last.endOffset; +} +function collectDefs(blocks, defs) { + for (const block of blocks) { + if (block.type !== "citation_definition") + continue; + const value = { entry: block.children }; + const kv = block.attrs?.keyValues; + if (kv?.author !== void 0) + value.author = kv.author; + if (kv?.year !== void 0) + value.year = kv.year; + defs.set(block.key, value); } - const applied = []; - const skipped = []; - for (const h of hits) { - if (crossed.has(h)) - skipped.push(h); +} +function splitOnSoftBreaks(nodes) { + const lines = [[]]; + for (const n of nodes) { + if (n.type === "soft_break") + lines.push([]); else - applied.push(h); + lines[lines.length - 1].push(n); } - const edits = applied.flatMap((h) => h.edits).sort((a, b) => b.start - a.start); - let output = source.replace(/\r\n?/g, "\n"); - for (const e of edits) { - output = output.slice(0, e.start) + e.text + output.slice(e.end); + return lines; +} +function joinWithSoftBreaks(lines) { + const out = []; + lines.forEach((line2, i) => { + if (i > 0) + out.push({ type: "soft_break" }); + for (const n of line2) + out.push(n); + }); + return out; +} +function definitionNode(kids) { + const g = kids[0]; + if (!g || g.type !== "citation_group") + return null; + const cg = g; + if (cg.items.length !== 1) + return null; + const it = cg.items[0]; + if (it.prefix || it.locator || it.suppressAuthor) + return null; + const second = kids[1]; + if (!second || second.type !== "text" || !second.value.startsWith(":")) + return null; + const span2 = lineSpan(kids); + const entry = [...kids.slice(1)]; + const separator = /^:\s*/.exec(second.value)[0]; + const head = { type: "text", value: second.value.slice(separator.length) }; + if (second.pos) + head.pos = { ...second.pos }; + advanceStart(head, separator); + entry[0] = head; + const node = { type: "citation_definition", key: it.key, children: entry }; + const inside = takeLeadingAttrBlock(entry); + if (inside !== null) { + const keyValues = {}; + for (const pair of inside.matchAll(KV_PAIR_RE)) + keyValues[pair[1]] = pair[2]; + if (Object.keys(keyValues).length > 0) + node.attrs = { keyValues }; + } + const first = entry[0]; + if (first?.type === "text") { + const lead = /^\s*/.exec(first.value)[0]; + if (lead !== "") { + first.value = first.value.slice(lead.length); + advanceStart(first, lead); + } + if (first.value === "") + entry.shift(); + } + if (span2) + node.pos = span2; + return node; +} +function lineSpan(kids) { + const first = kids[0]?.pos; + const last = kids[kids.length - 1]?.pos; + if (!first || !last) + return void 0; + const span2 = { startLine: first.startLine, endLine: last.endLine }; + if (first.startColumn !== void 0) + span2.startColumn = first.startColumn; + if (last.endColumn !== void 0) + span2.endColumn = last.endColumn; + if (first.startOffset !== void 0) + span2.startOffset = first.startOffset; + if (last.endOffset !== void 0) + span2.endOffset = last.endOffset; + return span2; +} +function advanceStart(node, removed) { + const pos = node.pos; + if (!pos || removed === "") + return; + const delta = [...removed].length; + if (pos.startColumn !== void 0) + pos.startColumn += delta; + if (pos.startOffset !== void 0) + pos.startOffset += delta; +} +function cslToDef(e) { + const list = Array.isArray(e.author) ? e.author : []; + const names = list.map(formatName).filter((n) => n !== ""); + const authors = names.join("; "); + const year = cslYear(e.issued); + let head = authors; + if (year) + head = head ? `${head} (${year})` : `(${year})`; + const segs = []; + if (head) + segs.push(head); + if (typeof e.title === "string" && e.title !== "") + segs.push(e.title); + let cslText = segs.join(". "); + if (cslText) + cslText += "."; + const def = { entry: [], cslText }; + const first = list[0]; + const author = first && typeof first === "object" ? first.literal ?? first.family : void 0; + if (author !== void 0) + def.author = author; + if (year) + def.year = year; + return def; +} +function formatName(n) { + if (!n || typeof n !== "object") + return ""; + if (n.literal) + return n.literal; + if (n.family && n.given) + return `${n.family}, ${n.given}`; + return n.family ?? ""; +} +function cslYear(issued) { + const y = issued?.["date-parts"]?.[0]?.[0]; + if (typeof y === "number") + return String(y); + return issued?.literal ?? ""; +} +function renderGroup(node, ctx, mode, numbers, defs, hasBib, citeIds, refIds) { + if (node.items.some((it) => !defs.has(it.key))) + return ctx.escapeHtml(node.raw); + const pre = (it) => it.prefix ? `${ctx.renderInlines(it.prefix)} ` : ""; + const loc = (it) => it.locator ? `, ${ctx.renderInlines(it.locator)}` : ""; + const idAttr = (it) => hasBib && it.useIndex ? `id="${ctx.escapeAttr(citeIds.get(`${it.key}-${it.useIndex}`) ?? `cite-${it.key}-${it.useIndex}`)}" ` : ""; + const refHref = (it) => ctx.escapeAttr(refIds.get(it.key) ?? `ref-${it.key}`); + const dataAttrs = (it) => { + const a = [`data-cite-key="${ctx.escapeAttr(it.key)}"`]; + if (it.suppressAuthor) + a.push('data-suppress-author="true"'); + const pfx = flattenText(it.prefix); + if (pfx) + a.push(`data-cite-prefix="${ctx.escapeAttr(pfx)}"`); + if (it.locatorLabel) + a.push(`data-locator-label="${ctx.escapeAttr(it.locatorLabel)}"`); + if (it.locatorValue) + a.push(`data-locator="${ctx.escapeAttr(it.locatorValue)}"`); + const sfx = flattenText(it.suffix); + if (sfx) + a.push(`data-suffix="${ctx.escapeAttr(sfx)}"`); + return a.join(" ") + " "; + }; + const wrap = (s) => node.mode === "integral" ? `${s}` : s; + if (mode === "author-date") { + const parts2 = node.items.map((it) => { + const d = defs.get(it.key); + const label = it.suppressAuthor ? d.year ?? String(it.number ?? "") : `${d.author ?? ""} ${d.year ?? ""}`.trim() || String(it.number ?? ""); + return `${pre(it)}${ctx.escapeHtml(label)}${loc(it)}`; + }); + const out2 = `(${parts2.join("; ")})`; + return wrap(out2); + } + const parts = node.items.map((it) => { + const n = numbers.get(it.key); + return `${pre(it)}${n}${loc(it)}`; + }); + const out = `[${parts.join(", ")}]`; + return wrap(out); +} +function renderRefsList(ctx, mode, order, defs, uses, hasBib, citeIds, refIds) { + const pad = ctx.indent(ctx.level); + const keys = [...order]; + if (mode === "author-date") { + keys.sort((a, b) => (defs.get(a)?.author ?? a).localeCompare(defs.get(b)?.author ?? b)); + } + const tag = mode === "author-date" ? "ul" : "ol"; + const items = keys.map((k) => { + const d = defs.get(k); + const body = d.cslText !== void 0 ? ctx.escapeHtml(d.cslText) : ctx.renderInlines(d.entry); + let backlinks = ""; + if (hasBib) { + const n = uses.get(k) ?? 0; + const links = []; + for (let m = 1; m <= n; m++) + links.push(`\u21A9`); + if (links.length) + backlinks = (body ? " " : "") + links.join(" "); + } + return `${pad}
  • ${body}${backlinks}
  • `; + }).join("\n"); + return `${pad}<${tag} class="references"> +${items} +${pad}`; +} +function flattenText(nodes) { + if (!nodes) + return ""; + let out = ""; + for (const n of nodes) { + if (n.type === "text") + out += n.value; + else if (n.type === "smart_punctuation") + out += n.glyph ?? SMART_PUNCTUATION_GLYPHS[n.kind] ?? n.value; + else if ("children" in n && Array.isArray(n.children)) + out += flattenText(n.children); + } + return out; +} +function hasClass(b, cls) { + const attrs = b.attrs; + return !!attrs?.classes?.includes(cls); +} +function walkCitationGroups(node, fn) { + if (!node || typeof node !== "object") + return; + if (node.type === "citation_group") { + fn(node); + return; + } + for (const key2 of Object.keys(node)) { + if (key2 === "pos") + continue; + const v = node[key2]; + if (Array.isArray(v)) + for (const el of v) + walkCitationGroups(el, fn); + else if (v && typeof v === "object") + walkCitationGroups(v, fn); } - return { output, applied: applied.map(stripHit), skipped: skipped.map(stripHit) }; } +var KEY, ITEM_RE, LOCATOR_VOCAB, FLAT_TERMS, VALUE_CHAR, REFS_MARK, lastBracketMapText, lastBracketMap, matchCitation, ATTR_RE, KV_PAIR_RE; +var init_citations = __esm({ + "node_modules/@markup-carve/carve/dist/citations.js"() { + init_ast(); + KEY = String.raw`[\w][\w:.#$%&+?<>~/-]*`; + ITEM_RE = new RegExp(String.raw`^(.*?)(-?)@(${KEY})(?:,\s*(.*))?$`); + LOCATOR_VOCAB = [ + ["book", ["book", "bk."]], + ["chapter", ["chapter", "chaps.", "chap."]], + ["column", ["column", "cols.", "col."]], + ["figure", ["figure", "figs.", "fig."]], + ["folio", ["folio", "fols.", "fol."]], + ["issue", ["issue", "no."]], + ["line", ["line", "ll.", "l."]], + ["note", ["note", "nn.", "n."]], + ["opus", ["opus", "opp.", "op."]], + ["page", ["pages", "page", "pp.", "p."]], + ["paragraph", ["paragraph", "paras.", "para.", "\xB6\xB6", "\xB6"]], + ["part", ["part", "pts.", "pt."]], + ["section", ["section", "secs.", "sec.", "\xA7\xA7", "\xA7"]], + ["sub verbo", ["sub verbo", "s.vv.", "s.v."]], + ["verse", ["verse", "vv.", "v."]], + ["volume", ["volume", "vols.", "vol."]] + ]; + FLAT_TERMS = LOCATOR_VOCAB.flatMap(([canon, ms]) => ms.map((m) => [m, canon])).sort((a, b) => b[0].length - a[0].length); + VALUE_CHAR = /[0-9IVXLCDMivxlcdm.,&\- ]/; + REFS_MARK = "data-cite-refs"; + lastBracketMapText = null; + lastBracketMap = {}; + matchCitation = (text, pos, ctx) => { + if (text[pos] !== "[") + return null; + const close = bracketMapFor(text)[pos]; + if (close === void 0) + return null; + const after = text[close + 1]; + if (after === "(" || after === "[" || after === "{") + return null; + let inner = text.slice(pos + 1, close); + if (!inner.includes("@")) + return null; + let mode; + if (inner[0] === "+") { + mode = "integral"; + inner = inner.slice(1); + } + const items = []; + for (const part of inner.split(";")) { + const item2 = parseItem(part, ctx); + if (!item2) + return null; + items.push(item2); + } + if (items.length === 0) + return null; + const node = { type: "citation_group", items, raw: text.slice(pos, close + 1) }; + if (mode) + node.mode = mode; + return { node, end: close + 1 }; + }; + ATTR_RE = /^\{([^}]*)\}\s*/; + KV_PAIR_RE = /([A-Za-z_][\w.:-]*)\s*=\s*["“”]([^"“”]*)["“”]/g; + } +}); -// node_modules/@markup-carve/carve/dist/markdown-migrate.js -function markerForm(marker) { - return (match, body, offset, full) => { - if (marker === "^" || marker === ",") - return `{${marker}${body}${marker}}`; - const before = full[offset - 1] ?? ""; - const after = full[offset + match.length] ?? ""; - const intraword = /[A-Za-z0-9]/.test(before) || /[A-Za-z0-9]/.test(after); - const padded = /^\s|\s$/.test(body); - return intraword || padded ? `{${marker}${body}${marker}}` : `${marker}${body}${marker}`; - }; +// node_modules/@markup-carve/carve/dist/render-depth.js +var MAX_RENDER_DEPTH, RenderDepthError; +var init_render_depth = __esm({ + "node_modules/@markup-carve/carve/dist/render-depth.js"() { + init_parse(); + MAX_RENDER_DEPTH = MAX_NESTING_DEPTH + 32; + RenderDepthError = class extends Error { + renderer; + depth; + constructor(renderer, depth) { + super(`${renderer}: tree nests ${depth} levels or deeper, past the render cap of ${MAX_RENDER_DEPTH}`); + this.renderer = renderer; + this.depth = depth; + this.name = "RenderDepthError"; + } + }; + } +}); + +// node_modules/@markup-carve/carve/dist/own-property.js +function ownValue(record, key2) { + if (record === void 0 || record === null) + return void 0; + return Object.hasOwn(record, key2) ? record[key2] : void 0; } -var HTML_TAG_RULES = [ - // Highlight/super/subscript use Carve's single-char markers, brace-forced - // only when needed: an HTML tag can sit intraword (e.g. `H2O`), - // where a bare `,2,` / `^2^` / `=2=` is literal in Carve, so `markerForm` - // emits `{,x,}` / `{^x^}` / `{=x=}` there and the bare form everywhere else. - [/([^<]+)<\/mark>/gi, markerForm("=")], - // `` has no bare Carve form (insertion is the CriticMarkup `{+x+}`), so - // it always uses the brace form — unlike the single-char markers below. - [/([^<]+)<\/ins>/gi, "{+$1+}"], - [/([^<]+)<\/del>/gi, "~$1~"], - [/([^<]+)<\/s>/gi, "~$1~"], - [/([^<]+)<\/sup>/gi, markerForm("^")], - [/([^<]+)<\/sub>/gi, markerForm(",")], - [/([^<]+)<\/strong>/gi, "*$1*"], - [/([^<]+)<\/b>/gi, "*$1*"], - [/([^<]+)<\/em>/gi, "/$1/"], - [/([^<]+)<\/i>/gi, "/$1/"] -]; +function hasOwnKey(record, key2) { + return record !== void 0 && record !== null && Object.hasOwn(record, key2); +} +function setOwn(record, key2, value) { + Object.defineProperty(record, key2, { + value, + writable: true, + enumerable: true, + configurable: true + }); +} +var init_own_property = __esm({ + "node_modules/@markup-carve/carve/dist/own-property.js"() { + } +}); -// node_modules/@markup-carve/carve/dist/lint.js -function locate(node) { - const p = node.pos; - return { - line: p?.startLine ?? 1, - column: p?.startColumn ?? 1, - start: p?.startOffset ?? 0, - end: p?.endOffset ?? p?.startOffset ?? 0 - }; +// node_modules/@markup-carve/carve/dist/footnote-numbering.js +function walkBlockInlines(node, visit4, depth = 0) { + if (depth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("numberFootnotes", MAX_RENDER_DEPTH); + switch (node.type) { + case "heading": + case "paragraph": + // A bibliography entry's inlines are rendered - in the references list - + // so a footnote reference in one is numbered like any other. It reached + // this walk as a paragraph before PART 12 §18 made the line its own node, + // and skipping it here would have unnumbered the reference and left it + // rendering as its own source text. + case "citation_definition": + visit4(node.children); + break; + case "block_quote": + node.children.forEach((c) => walkBlockInlines(c, visit4, depth + 1)); + break; + case "list": + for (const it of node.items) + it.children.forEach((c) => walkBlockInlines(c, visit4, depth + 1)); + break; + case "admonition": + if (node.title) + visit4(node.title); + node.children.forEach((c) => walkBlockInlines(c, visit4, depth + 1)); + break; + case "div": + // A LINE BLOCK HOLDS ORDINARY BLOCKS and differs from a div only in that + // its newlines are hard breaks (§4.4), so its inlines are numbered like any + // other. Falling to `default` here did not degrade the note, it deleted it: + // an inline footnote carries no `id`, so an unnumbered one renders as the + // literal `[^]` and its body reaches no endnotes section - the content is + // gone from the document rather than merely unlinked + // (markup-carve/carve-js#1117). + case "line_block": + node.children.forEach((c) => walkBlockInlines(c, visit4, depth + 1)); + break; + case "definition_list": + for (const it of node.items) { + for (const t of it.terms) + visit4(t); + for (const d of it.definitions) + for (const b of d) + walkBlockInlines(b, visit4, depth + 1); + } + break; + case "table": + if (node.caption) + visit4(node.caption); + for (const row of node.rows) + for (const cell of row.cells) + visit4(cell.children); + break; + case "figure": + visit4(node.caption); + if (node.target.type === "block_quote" || node.target.type === "table") + walkBlockInlines(node.target, visit4, depth + 1); + break; + case "figure_group": + if (node.caption) + visit4(node.caption); + node.children.forEach((c) => walkBlockInlines(c, visit4, depth + 1)); + break; + default: + break; + } } -function walkDocument(doc, visitNode) { - const visit = (value) => { - if (Array.isArray(value)) { - for (const item of value) - visit(item); +function visitInlineTree(nodes, fn, depth = 0, discarded = false) { + if (depth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("numberFootnotes", MAX_RENDER_DEPTH); + for (const n of nodes) { + fn(n, discarded); + const kids = n.children ?? n.content; + if (Array.isArray(kids)) + visitInlineTree(kids, fn, depth + 1, discarded || isUnresolvedReference(n)); + } +} +function numberFootnotes(ast) { + const defs = ast.footnoteDefs ?? {}; + const order = []; + const refs = []; + const labelIndexes = /* @__PURE__ */ new Map(); + const onNode = (n, discarded) => { + if (n.type !== "footnote_ref" && n.type !== "inline_footnote") + return; + if (discarded) { + delete n.number; return; } - if (!value || typeof value !== "object") + if (n.inline) { + const orderIndex = order.length; + const entry = { inline: n.inline }; + if (n.pos?.startLine !== void 0) + entry.sourceLine = n.pos.startLine; + order.push(entry); + n.number = orderIndex + 1; + refs.push({ node: n, orderIndex }); return; - const node = value; - visitNode(node); - for (const key of Object.keys(node)) { - if (key !== "pos" && key !== "attrs") - visit(node[key]); } + if (!n.id || ownValue(defs, n.id) === void 0) { + delete n.number; + return; + } + let idx = labelIndexes.get(n.id); + if (idx === void 0) { + const entry = { label: n.id }; + const sourceLine = ownValue(defs, n.id)?.[0]?.pos?.startLine; + if (sourceLine !== void 0) + entry.sourceLine = sourceLine; + order.push(entry); + idx = order.length - 1; + labelIndexes.set(n.id, idx); + } + n.number = idx + 1; + refs.push({ node: n, orderIndex: idx }); }; - visit(doc.children); - if (doc.footnoteDefs) - visit(Object.values(doc.footnoteDefs)); -} -function normalizeHeadingRefLabel2(label) { - return normalizeRefLabel(label).toLowerCase(); + for (const b of ast.children) + walkBlockInlines(b, (xs) => visitInlineTree(xs, onNode)); + for (let k = 0; k < order.length; k++) { + const label = order[k].label; + if (label === void 0) + continue; + for (const b of ownValue(defs, label) ?? []) + walkBlockInlines(b, (xs) => visitInlineTree(xs, onNode)); + } + return { order, refs }; } -function collectCrossrefs(doc) { - const found = []; - walkDocument(doc, (node) => { - if (node.type === "heading_ref" && typeof node.target === "string") { - found.push({ target: node.target, node }); +var init_footnote_numbering = __esm({ + "node_modules/@markup-carve/carve/dist/footnote-numbering.js"() { + init_render_depth(); + init_own_property(); + init_unresolved_reference(); + } +}); + +// node_modules/@markup-carve/carve/dist/document-ids.js +function collectDocumentIds(doc) { + const registry = new DocumentIdRegistry(); + const stack = [doc]; + while (stack.length > 0) { + const value = stack.pop(); + if (Array.isArray(value)) { + for (const v of value) + stack.push(v); + continue; } - }); - return found; + if (value === null || typeof value !== "object") + continue; + const attrs = value.attrs; + if (attrs && typeof attrs.id === "string") + registry.reserve(attrs.id); + for (const v of Object.values(value)) { + if (v !== null && typeof v === "object") + stack.push(v); + } + } + return registry; } -function collectUnresolvedRefLinks(doc) { - const found = []; - walkDocument(doc, (node) => { - if (node.type !== "link" || typeof node.ref !== "string") - return; - found.push({ - ref: node.ref, - rawRef: typeof node.rawRef === "string" ? node.rawRef : `[${node.ref}]`, - node - }); +var DocumentIdRegistry; +var init_document_ids = __esm({ + "node_modules/@markup-carve/carve/dist/document-ids.js"() { + DocumentIdRegistry = class { + /** id -> next 1-based suffix candidate (mirrors carve-php usedIds). */ + usedIds = /* @__PURE__ */ new Map(); + /** Reserve an id verbatim (explicit attribute or already-assigned id). */ + reserve(id) { + if (id !== "" && !this.usedIds.has(id)) + this.usedIds.set(id, 1); + } + /** + * Reserve `baseId` in the namespace, or the next free numeric suffix + * (`baseId-2`, `-3`, ...) when taken — skipping candidates already reserved + * by explicit attributes or previously generated ids. + */ + uniqueId(baseId) { + if (!this.usedIds.has(baseId)) { + this.usedIds.set(baseId, 1); + return baseId; + } + let n = this.usedIds.get(baseId); + let candidate; + do { + n++; + candidate = `${baseId}-${n}`; + } while (this.usedIds.has(candidate)); + this.usedIds.set(baseId, n); + this.usedIds.set(candidate, 1); + return candidate; + } + }; + } +}); + +// node_modules/@markup-carve/carve/dist/bidi-controls.js +function isBidiControl(codePoint) { + return codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8294 && codePoint <= 8297; +} +function stripBidiControls(value) { + return value.replace(BIDI_OVERRIDE_OR_ISOLATE, ""); +} +var BIDI_OVERRIDE_OR_ISOLATE; +var init_bidi_controls = __esm({ + "node_modules/@markup-carve/carve/dist/bidi-controls.js"() { + BIDI_OVERRIDE_OR_ISOLATE = /[\u202a-\u202e\u2066-\u2069]/gu; + } +}); + +// node_modules/@markup-carve/carve/dist/legacy-nodes.js +function normalizeLegacyInline(node) { + if (node.type !== "footnote") + return node; + const legacy = node; + return { + ...node, + type: Array.isArray(legacy.inline) ? "inline_footnote" : "footnote_ref" + }; +} +function adoptBlockFootnoteDefs(ast) { + const isDef = (n) => n.type === "footnote"; + if (!ast.children?.some(isDef)) + return ast; + const defs = { ...ast.footnoteDefs ?? {} }; + const children = ast.children.filter((child) => { + if (!isDef(child)) + return true; + const def = child; + const label = def.label; + if (label === void 0 || !Array.isArray(def.children)) + return false; + if (ownValue(defs, label) === void 0) + setOwn(defs, label, def.children); + return false; }); - return found; + return { ...ast, children, footnoteDefs: defs }; } -function collectFootnoteRefs(doc) { - const found = []; - walkDocument(doc, (node) => { - if (node.type === "footnote" && typeof node.id === "string") { - found.push({ id: node.id, node }); - } +var init_legacy_nodes = __esm({ + "node_modules/@markup-carve/carve/dist/legacy-nodes.js"() { + init_own_property(); + } +}); + +// node_modules/@markup-carve/carve/dist/render-html.js +function sanitizeUrl(url, opts) { + if (opts.sanitizeUrls === false) + return url; + const probe = url.replace(SCHEME_PROBE_STRIP_RE, ""); + const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(probe); + if (!scheme) + return url; + const s = scheme[1].toLowerCase(); + if (opts.allowedUrlSchemes) { + return opts.allowedUrlSchemes.some((a) => a.toLowerCase() === s) ? url : ""; + } + const denied = opts.deniedUrlSchemes ?? DANGEROUS_URL_SCHEMES; + return denied.some((d) => d.toLowerCase() === s) ? "" : url; +} +function isDangerousAttrName(name) { + const n = name.toLowerCase(); + return n.startsWith("on") || DANGEROUS_ATTR_NAMES.has(n); +} +function hasDeniedValueScheme(value) { + const colon = value.indexOf(":"); + if (colon === -1) + return false; + const scheme = value.slice(0, colon).replace(SCHEME_PROBE_STRIP_RE, "").toLowerCase(); + return DANGEROUS_VALUE_SCHEMES.has(scheme); +} +function sanitizeAttrValue(name, value) { + const n = name.toLowerCase(); + if (hasDeniedValueScheme(value)) + return ""; + const separator = URL_LIST_SEPARATORS.get(n); + if (separator && value.split(separator).some((token) => token !== "" && hasDeniedValueScheme(token))) { + return ""; + } + if (n === "style" && hasDangerousCss(value)) + return ""; + return value; +} +function renderedAttrValue(name, value) { + return sanitizeAttrValue(name, value); +} +function escapeAttrValue(value) { + return escapeAttr(value); +} +function hasDangerousCss(value) { + const compact = decodeCssEscapes(value.replace(/\/\*[\s\S]*?\*\//g, "")).toLowerCase().replace(/\s+/g, ""); + return compact.includes("expression(") || compact.includes("url(") || compact.includes("@import") || compact.includes("behavior:") || compact.includes("-moz-binding"); +} +function decodeCssEscapes(value) { + return value.replace(/\\([0-9a-f]{1,6}\s?|[\s\S])/gi, (_m, esc) => { + if (/^[0-9a-f]/i.test(esc)) { + const hex = esc.trim(); + const cp = Number.parseInt(hex, 16); + return Number.isFinite(cp) && cp <= 1114111 ? String.fromCodePoint(cp) : ""; + } + return esc; }); - return found; } -function captionHasNumber(value) { - return Array.isArray(value) && value.some((node) => node && typeof node === "object" && node.type === "caption_number"); +function withSourceLine(html, line2) { + if (line2 === void 0) + return html; + const open = /^\s*<[A-Za-z][A-Za-z0-9-]*(?:\s[^>]*)?>/.exec(html)?.[0]; + if (open && /\sdata-source-line(?:\s|=|>)/i.test(open)) + return html; + return html.replace(/^(\s*<[A-Za-z][A-Za-z0-9-]*(?:"[^"]*"|'[^']*'|[^>"'])*?)(\s*\/?>)/, `$1 data-source-line="${line2}"$2`); } -function lintCarve(source, opts = {}) { - const doc = parse(source, { positions: true }); - const slugOpts = headingIdSlugOpts(opts); - const foldId = (s) => Array.from(s, (c) => c.toLowerCase()).join(""); +function hasAuthoredSourceLine(attrs) { + return Object.keys(attrs?.keyValues ?? {}).some((k) => k.toLowerCase() === "data-source-line"); +} +function sourceLineAttr(opts, line2, attrs) { + return opts.sourceLine && line2 !== void 0 && !hasAuthoredSourceLine(attrs) ? ` data-source-line="${line2}"` : ""; +} +function renderHtml(ast, opts = {}) { + const declared = opts.extensions?.flatMap((e) => e.semanticSpanNames ?? []) ?? []; + if (declared.length > 0 && opts.semanticSpanNames === void 0) { + opts = { + ...opts, + semanticSpanNames: EXTENDED_SEMANTIC_SPAN_ORDER.filter((name) => CORE_SEMANTIC_SPAN_ORDER.includes(name) || declared.includes(name)) + }; + } + if (opts.mode !== void 0 && !RENDER_MODES.has(opts.mode)) { + throw new Error(`renderHtml: unknown render mode ${JSON.stringify(opts.mode)} (expected "interactive" or "static")`); + } + const prevBudget = abbrBudget2; + const prevDocIds = docIds; + const prevOptions = activeRenderOptions; + abbrBudget2 = budgetForDocument(ast); + docIds = collectDocumentIds(ast); + activeRenderOptions = opts; + try { + return renderDocumentBody(ast, opts); + } finally { + abbrBudget2 = prevBudget; + docIds = prevDocIds; + activeRenderOptions = prevOptions; + } +} +function renderDocumentBody(ast, opts) { const out = []; - const used = /* @__PURE__ */ new Set(); - const headingRefs = /* @__PURE__ */ new Map(); - const indexHeadings = (blocks, inBlockquote) => { - for (const block of blocks) { - switch (block.type) { - case "heading": { - const heading = block; - const explicit = heading.attrs?.id; - let id; - if (explicit !== void 0) { - id = explicit; - if (used.has(explicit)) { - out.push({ - ...locate(heading), - rule: "duplicate-heading-id", - message: `Duplicate heading id "${explicit}": the repeated HTML id is invalid, and cross-references to it resolve to the first occurrence.` - }); - } - used.add(explicit); - } else { - const base = slugify(inlineText(heading.children), slugOpts); - if (used.has(base)) { - let n = 2; - while (used.has(`${base}-${n}`)) - n++; - id = `${base}-${n}`; - out.push({ - ...locate(heading), - rule: "duplicate-heading-id", - message: `Heading slug "${base}" collides with an earlier heading; its auto id becomes "${id}", and ambiguous references to "${base}" resolve to the first occurrence.` - }); - used.add(id); - } else { - id = base; - used.add(base); - } - } - if (!inBlockquote) { - const key = normalizeHeadingRefLabel2(inlineText(heading.children)); - if (key && !headingRefs.has(key)) - headingRefs.set(key, id); - } - break; - } - case "block_quote": - indexHeadings(block.children, true); - break; - case "admonition": - case "div": - indexHeadings(block.children, inBlockquote); - break; - case "list": - for (const it of block.items) - indexHeadings(it.children, inBlockquote); - break; - case "definition_list": - for (const it of block.items) - for (const d of it.definitions) - indexHeadings(d, inBlockquote); - break; - case "figure": - if (block.target.type === "block_quote") - indexHeadings(block.target.children, true); - break; - default: - break; - } + const wrapSections = opts.sections !== false; + const sectionStack = []; + const closeTo = (level) => { + while (sectionStack.length && sectionStack[sectionStack.length - 1] >= level) { + sectionStack.pop(); + out.push(`${indent(sectionStack.length)}`); } }; - indexHeadings(doc.children, false); - walkDocument(doc, (node) => { - const attrs = node.attrs; - if (attrs?.id === void 0) - return; - if (node.type === "table" && captionHasNumber(node.caption)) - used.add(attrs.id); - if (node.type === "figure" && captionHasNumber(node.caption)) - used.add(attrs.id); - }); - const usedFolded = new Set([...used].map(foldId)); - for (const { target, node } of collectCrossrefs(doc)) { - if (used.has(target) || usedFolded.has(foldId(target))) + const footnotes = collectFootnotes(ast); + let footnotesPlaced = false; + const trailers = new Set(ast.trailerBlocks ?? []); + const documentChildren = new Set(ast.children); + for (const node of ast.children) { + if (node.type === "abbreviation_def") continue; - out.push({ - ...locate(node), - rule: "broken-crossref", - message: `Cross-reference has no matching heading id; it renders as the literal text "".` - }); - } - for (const { ref, rawRef, node } of collectUnresolvedRefLinks(doc)) { - if (headingRefs.has(normalizeHeadingRefLabel2(ref))) + if (trailers.has(node)) continue; - out.push({ - ...locate(node), - rule: "unresolved-reference-link", - message: `Reference link ${rawRef} has no matching link definition or heading; it renders as literal text.` - }); + if (isFootnotePlacement(node) && footnotes.order.length && !footnotesPlaced) { + for (const child of node.children) { + const r = renderBlock(child, opts, sectionStack.length); + if (r !== "") + out.push(r); + } + out.push(renderFootnoteSection(ast, footnotes, opts)); + footnotesPlaced = true; + continue; + } + if (node.type === "heading") { + closeTo(node.level); + const depth = sectionStack.length; + if (wrapSections) { + const id = node.attrs?.id; + const sectionId = id !== void 0 ? ` id="${escapeAttr(id)}"` : ""; + out.push(`${indent(depth)}`); + sectionStack.push(node.level); + } + const headingLevel = wrapSections ? depth + 1 : depth; + const custom = renderHeadingElement(node, opts, headingLevel); + if (custom !== void 0) { + out.push(opts.sourceLine ? withSourceLine(custom, node.pos?.startLine) : custom); + continue; + } + const headingAttrs = wrapSections ? stripId(node.attrs) : node.attrs; + const inner = renderInlines(node.children, opts); + const slAttr = sourceLineAttr(opts, node.pos?.startLine, headingAttrs); + out.push(`${indent(headingLevel)}${inner}`); + continue; + } + const rendered = renderBlock(node, opts, sectionStack.length); + if (rendered !== "") + out.push(rendered); } - const footnoteRefs = collectFootnoteRefs(doc); - const footnoteDefs = doc.footnoteDefs ?? {}; - const referencedFootnotes = /* @__PURE__ */ new Set(); - for (const { id, node } of footnoteRefs) { - referencedFootnotes.add(id); - if (footnoteDefs[id]) + closeTo(1); + if (footnotes.order.length && !footnotesPlaced) + out.push(renderFootnoteSection(ast, footnotes, opts)); + for (const node of trailers) { + if (!documentChildren.has(node)) continue; - out.push({ - ...locate(node), - rule: "unresolved-footnote", - message: `Footnote reference [^${id}] has no matching definition; it renders as literal text.` - }); + const rendered = renderBlock(node, opts, 0); + if (rendered !== "") + out.push(rendered); } - const verbatimLines = collectVerbatimLines(doc); - collectSilentFailures(source, doc, verbatimLines, out); - collectFootnoteDefinitionWarnings(source, doc, verbatimLines, referencedFootnotes, out); - out.sort((a, b) => a.start - b.start || a.line - b.line || a.column - b.column); - return out; + return out.join("\n"); } -var TRAILING_HEADING_ATTR = /(^|\s)(\{\s*[.#][^{}]*\})\s*$/; -var LEGACY_RAW_FENCE = /^(\s*)(`{3,}|~{3,})\s*raw\s+(\S+)/; -var LEAKED_BLOCK_MARKER = /^(\s*)(:{3,}|\{[.#])/; -var INDENTED_FENCE = /^([ \t]+)(`{3,}|~{3,})/; -var FOOTNOTE_DEF = /^\[\^([^\]]+)\]:\s+(.+)$/; -function collectVerbatimLines(doc) { - const verbatim = /* @__PURE__ */ new Set(); - const add = (pos, endLine) => { - if (!pos) - return; - const end = endLine ?? pos.startLine; - for (let ln = pos.startLine; ln <= end; ln++) - verbatim.add(ln); - }; - walkDocument(doc, (node) => { - const pos = node.pos; - const endLine = pos?.endLine; - if (node.type === "code_block" || node.type === "raw_block") { - add(pos, endLine); - } else if (node.type === "figure") { - const target = node.target?.type; - if (target === "code_block" || target === "raw_block") - add(pos, endLine); - } +function isFootnotePlacement(node) { + return node.type === "admonition" && node.kind === "footnotes"; +} +function collectFootnotes(ast) { + const { order: numbered, refs } = numberFootnotes(ast); + const order = numbered.map((e) => { + const entry = { backrefs: [] }; + if (e.label !== void 0) + entry.label = e.label; + if (e.inline !== void 0) + entry.inline = e.inline; + if (e.sourceLine !== void 0) + entry.sourceLine = e.sourceLine; + return entry; }); - return verbatim; + const seen = {}; + for (const { node: n, orderIndex } of refs) { + const number = orderIndex + 1; + const occ = seen[orderIndex] = (seen[orderIndex] ?? 0) + 1; + const refId = occ === 1 ? `fnref${number}` : `fnref${number}-${occ}`; + n.refId = refId; + order[orderIndex].backrefs.push(refId); + } + return { order }; } -function collectSilentFailures(source, doc, verbatimLines, out) { - const lines = source.split("\n"); - const lineStart = []; - for (let off = 0, i = 0; i < lines.length; i++) { - lineStart[i] = off; - off += lines[i].length + 1; - } - const push = (lineNo, col, len, rule, message) => { - const start = (lineStart[lineNo - 1] ?? 0) + (col - 1); - out.push({ line: lineNo, column: col, rule, message, start, end: start + len }); +function renderFootnoteSection(ast, st, opts) { + return outsideLink(() => renderFootnoteSectionInner(ast, st, opts)); +} +function renderFootnoteSectionInner(ast, st, opts) { + const defs = ast.footnoteDefs ?? {}; + const lines = ['
    ', `${indent(1)}
    `, `${indent(1)}
      `]; + st.order.forEach((entry, idx) => { + const number = idx + 1; + const body = entry.inline ? [`${indent(3)}

      ${renderInlines(entry.inline, opts)}

      `] : (ownValue(defs, entry.label) ?? []).map((b) => renderBlock(b, opts, 3)); + const multiRef = entry.backrefs.length > 1; + const blink = entry.backrefs.map((rid, k) => `\u21A9${multiRef ? `${k + 1}` : ""}`).join(multiRef ? " " : ""); + const last = body.length - 1; + if (last >= 0 && /<\/p>\s*$/.test(body[last])) { + body[last] = body[last].replace(/<\/p>(\s*)$/, `${blink}

      $1`); + } else { + body.push(`${indent(3)}

      ${blink}

      `); + } + lines.push( + // The endnote item carries the definition's source line so editor + // integrations can map the rendered footnote back to its source. + `${indent(2)}
    1. `, + ...body, + `${indent(2)}
    2. ` + ); + }); + lines.push(`${indent(1)}
    `, "
    "); + return lines.join("\n"); +} +function stripId(attrs) { + if (!attrs) + return void 0; + if (attrs.id === void 0) + return attrs; + const { id: _omit, ...rest } = attrs; + return rest; +} +function stripKeyValue(attrs, key2) { + if (!attrs?.keyValues) + return attrs; + const lower = key2.toLowerCase(); + const matches = (k) => k.toLowerCase() === lower; + if (!Object.keys(attrs.keyValues).some(matches)) + return attrs; + const kv = {}; + for (const [k, v] of Object.entries(attrs.keyValues)) + if (!matches(k)) + kv[k] = v; + const result = { ...attrs, keyValues: kv }; + if (attrs.order) + result.order = attrs.order.filter((s) => !matches(s)); + return result; +} +function indent(level) { + return " ".repeat(level); +} +function renderAttrs(attrs) { + if (!attrs) + return ""; + const parts = []; + const classAttr = () => attrs.classes && attrs.classes.length ? ( + // Merge into one class attribute, deduping repeats keeping first- + // occurrence order (`{.a .a}` -> `class="a"`), matching carve-php (§15). + `class="${[...new Set(attrs.classes)].map(escapeAttr).join(" ")}"` + ) : ""; + const idAttr = () => attrs.id !== void 0 ? `id="${escapeAttr(attrs.id)}"` : ""; + const kvAttr = (k) => { + if (isDangerousAttrName(k)) + return ""; + if (!HTML_ATTR_NAME_RE.test(k)) + return ""; + const v = attrs.keyValues?.[k]; + return v !== void 0 ? `${k}="${escapeAttr(sanitizeAttrValue(k, v))}"` : ""; }; - const headings = []; - const paragraphs = []; - const walk = (value) => { - if (Array.isArray(value)) { - for (const item of value) - walk(item); - return; + const seen = new Set(attrs.order ?? []); + if (attrs.order) { + for (const slot of attrs.order) { + const p = slot === ".class" ? classAttr() : slot === "#id" ? idAttr() : kvAttr(slot); + if (p) + parts.push(p); } - if (!value || typeof value !== "object") - return; - const node = value; - if (node.type === "heading") - headings.push(node); - else if (node.type === "paragraph") - paragraphs.push(node); - for (const key of Object.keys(node)) { - if (key !== "pos" && key !== "attrs") - walk(node[key]); + } + if (!seen.has(".class")) { + const c = classAttr(); + if (c) + parts.push(c); + } + if (!seen.has("#id")) { + const i = idAttr(); + if (i) + parts.push(i); + } + if (attrs.keyValues) { + for (const k of Object.keys(attrs.keyValues)) { + if (!seen.has(k)) { + const p = kvAttr(k); + if (p) + parts.push(p); + } } + } + return parts.length ? " " + parts.join(" ") : ""; +} +function renderSemanticSpanWith(node, opts, order) { + const values = node.attrs?.keyValues; + const names = order.filter((name) => values?.[name] !== void 0); + const previousSuppress = suppressAutomaticAbbreviation; + if (values?.abbr !== void 0) + suppressAutomaticAbbreviation = true; + let body; + try { + body = renderInlines(node.children, opts); + } finally { + suppressAutomaticAbbreviation = previousSuppress; + } + if (names.length === 0) + return `${body}`; + const isSemantic = (key2) => order.includes(key2); + const keyValues = Object.fromEntries(Object.entries(values ?? {}).filter(([key2]) => !isSemantic(key2))); + const riding = { ...node.attrs, keyValues }; + if (riding.order) + riding.order = riding.order.filter((key2) => !isSemantic(key2)); + let html = body; + const outermost = names[names.length - 1]; + for (const name of names) { + const value = values[name]; + const mapsTo = value !== "" ? SEMANTIC_VALUE_ATTRIBUTE[name] : void 0; + const attrs = name === outermost ? riding : {}; + const derived = mapsTo !== void 0 && attrs.keyValues?.[mapsTo] === void 0 ? ` ${mapsTo}="${escapeAttr(value)}"` : ""; + html = `<${name}${derived}${renderAttrs(attrs)}>${html}`; + } + return html; +} +function renderSemanticSpan(node, opts) { + return renderSemanticSpanWith(node, opts, opts.semanticSpanNames ?? CORE_SEMANTIC_SPAN_ORDER); +} +function renderAttrs2(attrs, opts = {}) { + if (!attrs && !opts.baseClass && !opts.trailingClass) + return ""; + const a = attrs ? { ...attrs } : {}; + if (opts.baseClass) { + a.classes = [opts.baseClass, ...a.classes ?? []]; + if (a.order && !a.order.includes(".class")) + a.order = [".class", ...a.order]; + } + if (opts.trailingClass) { + a.classes = [...a.classes ?? [], opts.trailingClass]; + if (a.order && !a.order.includes(".class")) + a.order = [...a.order, ".class"]; + } + if (opts.dropId) { + delete a.id; + if (a.order) + a.order = a.order.filter((s) => s !== "#id"); + } + return renderAttrs(a); +} +function renderLeadingBaseClassAttrs(attrs, baseClass) { + const a = attrs?.order?.includes(".class") ? { + ...attrs, + order: [".class", ...attrs.order.filter((slot) => slot !== ".class")] + } : attrs; + return renderAttrs2(a, { baseClass }); +} +function renderSocialLinkAttrs(attrs, baseClass, href) { + const rendered = renderLeadingBaseClassAttrs(stripKeyValue(attrs, "href"), baseClass); + return rendered.replace(/^ class="[^"]*"/, `$& href="${escapeAttr(href)}"`); +} +function blockCtx(opts, level) { + return { + level, + indent, + renderChildren: (nodes, lvl) => renderBlocks(nodes, opts, lvl), + renderInlines: (nodes) => renderInlines(nodes, opts), + escapeHtml, + escapeAttr, + renderAttrs, + uniqueId, + mode: opts.mode ?? "interactive", + renderers: opts.renderers ?? {}, + sections: opts.sections !== false }; - walk(doc.children); - for (const h of headings) { - const ln = h.pos?.endLine ?? h.pos?.startLine; - if (!ln) - continue; - const line = lines[ln - 1] ?? ""; - if (!/^\s*#{1,6}\s/.test(line)) - continue; - const m = TRAILING_HEADING_ATTR.exec(line); - if (!m) - continue; - const col = m.index + m[1].length + 1; - push(ln, col, m[2].length, "heading-trailing-attribute", `Trailing "${m[2]}" on a heading is literal text in Carve, not an attribute block. Move it to a "${m[2]}" line directly above the heading.`); +} +function inlineCtx(opts) { + return { + renderInlines: (nodes) => renderInlines(nodes, opts), + escapeHtml, + escapeAttr, + renderAttrs, + uniqueId, + mode: opts.mode ?? "interactive", + renderers: opts.renderers ?? {} + }; +} +function uniqueId(baseId) { + return docIds ? docIds.uniqueId(baseId) : baseId; +} +function renderHeadingElement(node, opts, level) { + if (!opts.extensions?.length) + return void 0; + const isStatic = opts.mode === "static"; + const ctx = blockCtx(opts, level); + for (const e of opts.extensions) { + const staticFn = isStatic ? e.staticBlockRenderers?.heading : void 0; + if (staticFn) { + const out = staticFn(node, ctx); + if (out !== void 0) + return out; + } + const fn = e.blockRenderers?.heading; + if (fn) { + const out = fn(node, ctx); + if (out !== void 0) + return out; + } + } + return void 0; +} +function renderBlocks(nodes, opts, level) { + return nodes.map((c) => renderBlock(c, opts, level)).filter((s) => s !== "").join("\n"); +} +function renderBlock(node, opts, level) { + if (blockDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderHtml", MAX_RENDER_DEPTH); + blockDepth++; + try { + return renderBlockNode(node, opts, level); + } finally { + blockDepth--; } - for (let i = 0; i < lines.length; i++) { - if (verbatimLines.has(i + 1)) - continue; - const m = LEGACY_RAW_FENCE.exec(lines[i]); - if (!m) - continue; - push(i + 1, m[1].length + 1, lines[i].length - m[1].length, "raw-block-syntax", `"${m[2]}raw ${m[3]}" is not a Carve raw block; it fails to open and desyncs the document's fences. Use "${m[2]}=${m[3]}" to pass content through to ${m[3]}.`); +} +function renderBlockNode(node, opts, level) { + const pad = indent(level); + const isStatic = opts.mode === "static"; + if (node.type !== "heading" && opts.extensions?.length) { + const ctx = blockCtx(opts, level); + for (const e of opts.extensions) { + const staticFn = isStatic ? ownValue(e.staticBlockRenderers, node.type) : void 0; + if (staticFn) { + const out = staticFn(node, ctx); + if (out !== void 0) + return opts.sourceLine ? withSourceLine(out, node.pos?.startLine) : out; + } + const fn = ownValue(e.blockRenderers, node.type); + if (fn) { + const out = fn(node, ctx); + if (out !== void 0) + return opts.sourceLine ? withSourceLine(out, node.pos?.startLine) : out; + } + } } - for (const p of paragraphs) { - const first = p.children?.[0]; - if (first?.type !== "text" || typeof first.value !== "string") - continue; - const m = LEAKED_BLOCK_MARKER.exec(first.value); - if (!m) - continue; - const loc = locate(first); - if (m[2].startsWith(":")) { - const lineText = lines[loc.line - 1] ?? ""; - const fm = /^(:{3,})[ \t]+([a-zA-Z_][\w-]*)[ \t]+(.+?)[ \t]*$/.exec(lineText); - if (fm) { - const fence = fm[1]; - const type = fm[2]; - const trailing = fm[3]; - const lm = /^(.*?)[ \t]+(\[[^\]\n]*\])$/.exec(trailing); - const titlePart = lm ? lm[1] : trailing; - const label = lm ? ` ${lm[2]}` : ""; - let message; - const curly = /^[“”](.*)[“”]$/.exec(titlePart); - if (curly) { - message = `The title after "${type}" uses typographic quotes - usually a CMS "smart quote" filter rewrote the source before Carve parsed it. A fence title needs straight double quotes: ${fence} ${type} "${curly[1]}"${label}.`; - } else if (titlePart.startsWith("{")) { - message = `A "{\u2026}" on the fence line is not an attribute block - it makes the whole line plain text. Put attributes on their own line directly above the ":::" opener.`; - } else if (!titlePart.startsWith('"') && !titlePart.startsWith("[")) { - message = `Text after the "${type}" fence type must be a quoted "title" or a [label] - unquoted it makes the whole line plain text. Did you mean ${fence} ${type} "${titlePart}"${label}?`; - } - if (message) { - out.push({ - line: loc.line, - column: loc.column, - rule: "fence-title-syntax", - message, - start: loc.start, - end: loc.start + lineText.length - }); - continue; + switch (node.type) { + case "heading": { + const inner = renderInlines(node.children, opts); + return `${pad}${inner}`; + } + case "paragraph": { + const inner = renderInlines(node.children, opts); + return `${pad}${inner}

    `; + } + case "thematic_break": + return `${pad}`; + case "code_block": { + const langAttr = node.lang ? ` class="language-${node.lang}"` : ""; + const escaped = escapeHtml(node.content); + return `${pad}${escaped} +`; + } + case "block_quote": + return renderBlockQuote(node, opts, level); + case "list": + return renderList(node, opts, level); + case "image": { + const rendered = `${pad}${renderImage(node, opts)}`; + return opts.sourceLine ? withSourceLine(rendered, node.pos?.startLine) : rendered; + } + case "table": + return renderTable(node, opts, level); + case "admonition": + return renderAdmonition(node, opts, level); + case "div": { + const open = `${pad}`; + const floor = labelFloor(node.label, level + 1); + const body = renderBlocks(node.children, opts, level + 1); + if (body === "") { + return floor ? `${open} +${floor} +${pad}` : `${open} +${pad}`; + } + return `${open} +${floor ? `${floor} +` : ""}${body} +${pad}`; + } + case "line_block": { + const open = `${pad}`; + const body = renderBlocks(node.children, opts, level + 1); + if (body === "") + return `${open} +${pad}`; + return `${open} +${body} +${pad}`; + } + case "definition_list": { + const lines = [ + `${pad}` + ]; + for (const it of node.items) { + for (const t of it.terms) + lines.push(`${pad} ${renderInlines(t, opts)}`); + for (const [di, d] of it.definitions.entries()) { + const ddLine = it.definitionLines?.[di] ?? d[0]?.pos?.startLine; + const visible = d.filter((child) => child.type !== "comment"); + if (visible.length === 1 && visible[0].type === "paragraph") { + lines.push(`${pad} ${renderInlines(visible[0].children, opts)}`); + } else { + const body = renderBlocks(d, opts, level + 2); + lines.push(body === "" ? `${pad} ` : `${pad} +${body} +${pad} `); + } } } + lines.push(`${pad}`); + return lines.join("\n"); + } + case "figure": + return renderFigure(node, opts, level); + case "figure_group": + return renderFigureGroup(node, opts, level); + case "abbreviation_def": + return ""; + case "raw_block": + return node.format === "html" ? opts.allowRawHtml === false ? `${pad}${escapeHtml(node.content)}` : `${pad}${node.content}` : ""; + case "comment": + return ""; + case "link_reference_definition": + return ""; + case "citation_definition": + return ""; + default: { + const t = node; + throw new Error(`renderHtml: unknown block ${t.type}`); } - const what = m[2].startsWith(":") ? `an admonition/div fence ("${m[2]}")` : `a block-attribute line ("${m[2]}\u2026")`; - out.push({ - line: loc.line, - column: loc.column, - rule: "block-marker-as-text", - message: `This line begins like ${what} but parsed as plain text - the block did not open. Check this line's syntax and any unterminated fence above it.`, - start: loc.start, - end: loc.start + m[2].length - }); - } - for (let i = 0; i < lines.length; i++) { - if (verbatimLines.has(i + 1)) - continue; - const m = INDENTED_FENCE.exec(lines[i]); - if (!m) - continue; - if (LEGACY_RAW_FENCE.test(lines[i])) - continue; - const fence = m[2]; - if (lines[i].slice(m[1].length + fence.length).includes(fence)) - continue; - push(i + 1, m[1].length + 1, fence.length, "fence-delimiter-indentation", `This ${fence[0] === "`" ? "backtick" : "tilde"} fence is indented; a Carve fenced-code delimiter is column-exact and must sit at its container's content column (column 0 at the top level). Indented, it does not open a code block - the run renders as inline code and the body as plain text. Move it to column 0, or to the enclosing list item's content column.`); } } -function collectFootnoteDefinitionWarnings(source, doc, verbatimLines, referenced, out) { - const lines = source.split("\n"); - const lineStart = []; - for (let off = 0, i = 0; i < lines.length; i++) { - lineStart[i] = off; - off += lines[i].length + 1; - } - const firstSites = /* @__PURE__ */ new Map(); - for (let i = 0; i < lines.length; i++) { - if (verbatimLines.has(i + 1)) - continue; - const line = lines[i]; - const m = FOOTNOTE_DEF.exec(line); - if (!m) - continue; - const label = m[1].trim(); - const col = line.indexOf("[^") + 1; - const start = (lineStart[i] ?? 0) + (col - 1); - const site = { line: i + 1, col, start, end: start + m[0].length }; - if (firstSites.has(label)) { - out.push({ - line: site.line, - column: site.col, - rule: "duplicate-footnote-definition", - message: `Duplicate footnote definition [^${label}] is ignored; the first definition for a label wins.`, - start: site.start, - end: site.end - }); +function renderBlockQuote(node, opts, level) { + const pad = indent(level); + const attrs = sourceLineAttr(opts, node.pos?.startLine, node.attrs) + renderAttrs(node.attrs); + const rendered = node.children.map((child) => child.type === "paragraph" ? null : renderBlock(child, opts, level + 1)); + const visible = node.children.filter((_, i) => rendered[i] !== ""); + if (visible.length === 1 && visible[0].type === "paragraph") { + const para = visible[0]; + const inner2 = renderInlines(para.children, opts); + return `${pad}${inner2}

    `; + } + const inner = node.children.map((child, i) => rendered[i] ?? renderBlock(child, opts, level + 1)).filter((piece) => piece !== "").join("\n"); + return `${pad} +${inner} +${pad}`; +} +function renderList(node, opts, level) { + const pad = indent(level); + const tag = node.ordered ? "ol" : "ul"; + const typeAttr = node.ordered && node.olType ? ` type="${node.olType}"` : ""; + const startAttr = node.ordered && node.start !== void 0 && node.start !== 1 ? ` start="${node.start}"` : ""; + const items = node.items.map((it) => renderListItem(it, opts, level + 1, node.tight)).join("\n"); + return `${pad}<${tag}${typeAttr}${startAttr}${renderAttrs(node.attrs)}${sourceLineAttr(opts, node.pos?.startLine, node.attrs)}> +${items} +${pad}`; +} +function renderListItem(item2, opts, level, tight) { + const pad = indent(level); + const checkbox = item2.checked === void 0 ? "" : item2.checked ? ' ' : ' '; + const wrapPara = (p, isLead) => { + const inner = renderInlines(p.children, opts); + if (tight && isLead && !p.attrs) + return inner; + return `${inner}

    `; + }; + const prerendered = item2.children.map((child) => child.type === "paragraph" ? null : renderBlock(child, opts, level + 1)); + const visible = item2.children.filter((_, i) => prerendered[i] !== ""); + if (visible.length === 1 && visible[0].type === "paragraph") { + return `${pad}${checkbox}${wrapPara(visible[0], true)}
  • `; + } + let head = `${pad}${checkbox}`; + const body = []; + let seenVisible = 0; + item2.children.forEach((child, i) => { + if (child.type === "paragraph") { + const rendered = wrapPara(child, true); + if (seenVisible === 0) + head += rendered; + else + body.push(`${indent(level + 1)}${rendered}`); + seenVisible++; } else { - firstSites.set(label, site); + const rendered = prerendered[i]; + if (rendered !== "") { + body.push(rendered); + seenVisible++; + } + } + }); + if (body.length === 0) + return `${head}`; + return `${head} +${body.join("\n")} +${pad}`; +} +function renderTable(node, opts, level) { + const pad = indent(level); + const tableAttrs = node.attrs ? { + ...node.attrs, + keyValues: Object.fromEntries(Object.entries(node.attrs.keyValues ?? {}).filter(([key2]) => !["aligns", "valigns", "widths"].includes(key2))), + ...node.attrs.order ? { order: node.attrs.order.filter((key2) => !["aligns", "valigns", "widths"].includes(key2)) } : {} + } : void 0; + const lines = [ + `${pad}` + ]; + if (node.caption) { + lines.push(`${pad} ${renderInlines(node.caption, opts)}`); + } + if (node.columns?.some((column) => column.width !== void 0)) { + lines.push(`${pad} `); + for (const column of node.columns) { + const style2 = column.width === void 0 ? "" : ` style="width: ${column.width * 100}%;"`; + lines.push(`${pad} `); + } + lines.push(`${pad} `); + } + const grid = []; + for (let r = 0; r < node.rows.length; r++) { + const row = node.rows[r]; + const gridRow = []; + for (let c = 0; c < row.cells.length; c++) { + const cell = row.cells[c]; + gridRow.push({ row, cell, rowspan: 1, colspan: 1, skip: false }); + } + grid.push(gridRow); + } + const base = []; + for (let r = 0; r < grid.length; r++) { + for (let c = 0; c < grid[r].length; c++) { + const entry = grid[r][c]; + if (entry.skip) + continue; + if (entry.cell.span === "rowspan" && r > 0) { + const up = base[c]; + const src = up !== void 0 ? grid[up]?.[c] : void 0; + if (src) { + src.rowspan++; + entry.skip = true; + } + } else if (entry.cell.span === "colspan" && c > 0) { + let left = c - 1; + while (left >= 0 && grid[r][left].skip) + left--; + const src = grid[r][left]; + if (src) { + src.colspan++; + entry.skip = true; + } + } + if (!entry.skip || entry.cell.span === "colspan") + base[c] = r; + } + } + let headerEnd = 0; + while (headerEnd < grid.length && grid[headerEnd].some((e) => !e.skip) && grid[headerEnd].every((e) => e.cell.header || e.skip)) { + headerEnd++; + } + const columnAlign = []; + const columnValign = []; + for (let r = 0; r < headerEnd; r++) { + const hr = grid[r]; + for (let c = 0; c < hr.length; c++) { + const entry = hr[c]; + if (entry.skip || !entry.cell.align) + continue; + for (let k = c; k < c + entry.colspan; k++) + columnAlign[k] = entry.cell.align; + } + for (let c = 0; c < hr.length; c++) { + const entry = hr[c]; + if (entry.skip || !entry.cell.valign) + continue; + for (let k = c; k < c + entry.colspan; k++) + columnValign[k] = entry.cell.valign; } } - for (const label of Object.keys(doc.footnoteDefs ?? {})) { - if (referenced.has(label)) - continue; - const site = firstSites.get(label); - out.push({ - line: site?.line ?? 1, - column: site?.col ?? 1, - rule: "unused-footnote-definition", - message: `Footnote definition [^${label}] is never referenced, so it is omitted from the rendered document.`, - start: site?.start ?? 0, - end: site?.end ?? 0 - }); + for (let r = 0; r < grid.length; r++) { + for (let c = 0; c < grid[r].length; c++) { + const a = grid[r][c].cell.align ?? columnAlign[c] ?? node.columns?.[c]?.align; + if (a) + grid[r][c].align = a; + const v = grid[r][c].cell.valign ?? columnValign[c] ?? node.columns?.[c]?.valign; + if (v) + grid[r][c].valign = v; + } } + if (headerEnd > 0) { + const rows = grid.slice(0, headerEnd).map((r) => renderTableRowFlat(r, opts, true)); + lines.push(`${pad} ${rows.join("")}`); + } + if (headerEnd < grid.length) { + lines.push(`${pad} `); + for (let r = headerEnd; r < grid.length; r++) { + lines.push(`${pad} ${renderTableRowFlat(grid[r], opts)}`); + } + lines.push(`${pad} `); + } + lines.push(`${pad}`); + return lines.join("\n"); } - -// node_modules/@markup-carve/carve/dist/citations.js -var KEY = String.raw`[\w][\w:.#$%&+?<>~/-]*`; -var ITEM_RE = new RegExp(String.raw`^(.*?)(-?)@(${KEY})(?:,\s*(.*))?$`); -var LOCATOR_VOCAB = [ - ["book", ["book", "bk."]], - ["chapter", ["chapter", "chaps.", "chap."]], - ["column", ["column", "cols.", "col."]], - ["figure", ["figure", "figs.", "fig."]], - ["folio", ["folio", "fols.", "fol."]], - ["issue", ["issue", "no."]], - ["line", ["line", "ll.", "l."]], - ["note", ["note", "nn.", "n."]], - ["opus", ["opus", "opp.", "op."]], - ["page", ["pages", "page", "pp.", "p."]], - ["paragraph", ["paragraph", "paras.", "para.", "\xB6\xB6", "\xB6"]], - ["part", ["part", "pts.", "pt."]], - ["section", ["section", "secs.", "sec.", "\xA7\xA7", "\xA7"]], - ["sub verbo", ["sub verbo", "s.vv.", "s.v."]], - ["verse", ["verse", "vv.", "v."]], - ["volume", ["volume", "vols.", "vol."]] -]; -var FLAT_TERMS = LOCATOR_VOCAB.flatMap(([canon, ms]) => ms.map((m) => [m, canon])).sort((a, b) => b[0].length - a[0].length); - -// node_modules/@markup-carve/carve/dist/color-swatch.js -var NAMED_COLORS = new Set("transparent currentcolor aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen".split(" ")); - -// node_modules/@markup-carve/carve/dist/index.js -function parse2(source, opts = {}) { - return parse(source, opts); -} -function resolve(doc, opts = {}) { - return resolveHeadingIds(doc, headingIdSlugOpts(opts)); +function stripStructuralAttrs(attrs, emitted) { + if (!attrs?.keyValues || emitted.size === 0) + return attrs; + const collides = (k) => emitted.has(k.toLowerCase()); + if (!Object.keys(attrs.keyValues).some(collides)) + return attrs; + const keyValues = Object.fromEntries(Object.entries(attrs.keyValues).filter(([k]) => !collides(k))); + const out = { ...attrs, keyValues }; + if (attrs.order) + out.order = attrs.order.filter((s) => !collides(s)); + return out; } - -// dist/inline-text.js -function smartPunctuationText(node) { - if (typeof node !== "object" || node === null) +function cellScopeAttr(cell, isHeaderCell, inHeaderRun) { + if (!isHeaderCell) return ""; - const candidate = node; - if (candidate.type !== "smart_punctuation") + const keys = Object.keys(cell.attrs?.keyValues ?? {}); + if (keys.some((key2) => key2.toLowerCase() === "scope")) return ""; - if (typeof candidate.glyph === "string") - return candidate.glyph; - return typeof candidate.value === "string" ? candidate.value : ""; + return ` scope="${inHeaderRun ? "col" : "row"}"`; } - -// dist/analyze.js -function analyzeCarve(source) { - const diagnostics = []; - let doc = null; - try { - doc = resolve(parse2(source)); - } catch (error) { - diagnostics.push({ - severity: import_node.DiagnosticSeverity.Error, - range: rangeAt(source, 0, 1), - source: "carve", - message: error instanceof Error ? error.message : String(error) - }); - } - const norm = source.replace(/\r\n?/g, "\n"); - for (const warning of djotMigrationWarnings(source)) { - if (warning.category !== "carve-breakage") +function renderTableRowFlat(cells, opts, inHeaderRun = false) { + const parts = [``]; + for (const entry of cells) { + if (entry.skip) continue; - diagnostics.push({ - severity: import_node.DiagnosticSeverity.Warning, - range: { - start: positionAt(norm, warning.start), - end: positionAt(norm, warning.end) - }, - source: "carve", - code: warning.rule, - message: `${warning.message} Suggestion: ${warning.suggestion}` - }); + const tag = entry.cell.header ? "th" : "td"; + const attrs = []; + const emitted = /* @__PURE__ */ new Set(); + if (entry.rowspan > 1) { + attrs.push(`rowspan="${entry.rowspan}"`); + emitted.add("rowspan"); + } + if (entry.colspan > 1) { + attrs.push(`colspan="${entry.colspan}"`); + emitted.add("colspan"); + } + if (entry.align || entry.valign) { + const styles = `${entry.align ? `text-align: ${entry.align};` : ""}${entry.align && entry.valign ? " " : ""}${entry.valign ? `vertical-align: ${entry.valign};` : ""}`; + attrs.push(`style="${styles}"`); + emitted.add("style"); + } + const attrStr = cellScopeAttr(entry.cell, tag === "th", inHeaderRun) + renderAttrs(stripStructuralAttrs(entry.cell.attrs, emitted)) + (attrs.length ? " " + attrs.join(" ") : ""); + parts.push(`<${tag}${attrStr}>${renderInlines(entry.cell.children, opts)}`); + } + parts.push(""); + return parts.join(""); +} +function labelFloor(label, level) { + if (label === void 0 || label === "") + return ""; + return `${indent(level)}

    ${escapeHtml(label)}

    `; +} +function renderAdmonition(node, opts, level) { + const pad = indent(level); + const titleLine = node.title !== void 0 ? `${pad}

    ${renderInlines(node.title, opts)}

    +` : ""; + const floor = labelFloor(node.label, level + 1); + const labelLine = floor ? `${floor} +` : ""; + const body = renderBlocks(node.children, opts, level + 1); + const canonical2 = CANONICAL_ADMONITION_KINDS.has(node.kind); + const baseClass = canonical2 ? `admonition ${node.kind}` : node.kind; + const classValue = [baseClass, ...node.attrs?.classes ?? []].map(escapeAttr).join(" "); + const restAttrs = {}; + if (node.attrs?.id !== void 0) + restAttrs.id = node.attrs.id; + if (node.attrs?.keyValues) + restAttrs.keyValues = node.attrs.keyValues; + if (node.attrs?.order) + restAttrs.order = node.attrs.order.filter((s) => s !== ".class"); + const rest = renderAttrs(restAttrs); + const tag = canonical2 ? "aside" : "div"; + return `${pad}<${tag}${sourceLineAttr(opts, node.pos?.startLine, restAttrs)} class="${classValue}"${rest}> +${titleLine}${labelLine}${body} +${pad}`; +} +function renderFigure(node, opts, level, leadClass) { + const pad = indent(level); + let inner; + if (node.target.type === "image") { + inner = `${pad} ${renderImage(node.target, opts)}`; + } else if (node.target.type === "block_quote") { + const bq = renderBlockQuote(node.target, opts, level + 1); + inner = bq; + } else if (node.target.type === "code_block" || node.target.type === "paragraph") { + inner = renderBlock(node.target, opts, level + 1); + } else { + inner = renderTable(node.target, opts, level + 1); + } + const open = leadClass === void 0 ? `${pad}` : `${pad}`; + return `${open} +${inner} +${pad}
    ${renderInlines(node.caption, opts)}
    +${pad}`; +} +function withoutClassSlot(attrs) { + const rest = {}; + if (attrs?.id !== void 0) + rest.id = attrs.id; + if (attrs?.keyValues) + rest.keyValues = attrs.keyValues; + if (attrs?.order) + rest.order = attrs.order.filter((s) => s !== ".class"); + return rest; +} +function renderFigureGroup(node, opts, level) { + const pad = indent(level); + const classValue = [.../* @__PURE__ */ new Set(["carve-figure-group", ...node.attrs?.classes ?? []])].map(escapeAttr).join(" "); + const rest = withoutClassSlot(node.attrs); + const lines = [ + `${pad}` + ]; + const inner = node.children.map((c) => { + if (c.type === "figure") + return renderFigure(c, opts, level + 1, "carve-figure-panel"); + if (c.type === "table") { + const t = renderTable(c, opts, level + 2); + return `${pad}
    +${t} +${pad}
    `; + } + return renderBlock(c, opts, level + 1); + }).filter((s) => s !== "").join("\n"); + if (inner !== "") + lines.push(inner); + if (node.caption !== void 0) { + lines.push(`${pad}
    ${renderInlines(node.caption, opts)}
    `); + } + lines.push(`${pad}`); + return lines.join("\n"); +} +function renderImage(img, opts) { + if (isUnresolvedReference(img)) + return escapeHtml(referenceSourceText(img.rawRef)); + const titleAttr = img.title !== void 0 ? ` title="${escapeAttr(img.title)}"` : ""; + const src = escapeAttr(sanitizeUrl(img.src, opts)); + return `${escapeAttr(img.alt)}`; +} +function chargeCrossrefLabel(label, target) { + if (abbrBudget2?.charge(utf8ByteLength(label)) ?? true) + return label; + return escapeHtml(target); +} +function withinLink(fn) { + const previous = insideLink; + insideLink = true; + try { + return fn(); + } finally { + insideLink = previous; } - for (const warning of lintCarve(source)) { - const len = Math.max(1, warning.end - warning.start); - diagnostics.push({ - severity: import_node.DiagnosticSeverity.Warning, - range: { - start: { line: warning.line - 1, character: warning.column - 1 }, - end: { line: warning.line - 1, character: warning.column - 1 + len } - }, - source: "carve", - code: warning.rule, - message: warning.message - }); +} +function outsideLink(fn) { + const previous = insideLink; + insideLink = false; + try { + return fn(); + } finally { + insideLink = previous; } - return { - diagnostics, - symbols: doc ? documentSymbols(doc) : [] - }; } -function documentSymbols(doc) { - const stack = []; - const roots = []; - for (const heading of walkHeadings(doc.children)) { - const symbol = headingSymbol(heading); - while (stack.length && stack[stack.length - 1].level >= heading.level) { - stack.pop(); - } - const parent = stack[stack.length - 1]; - if (parent) { - parent.symbol.children ??= []; - parent.symbol.children.push(symbol); - } else { - roots.push(symbol); - } - stack.push({ level: heading.level, symbol }); +function renderInlines(nodes, opts) { + return nodes.map((n) => renderInline(n, opts)).join(""); +} +function renderInlinesInLinkContext(nodes, opts) { + return withinLink(() => renderInlines(nodes, opts ?? activeRenderOptions)); +} +function renderInline(node, opts) { + if (inlineDepth2 >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderHtml", MAX_RENDER_DEPTH); + inlineDepth2++; + try { + return renderInlineNode(node, opts); + } finally { + inlineDepth2--; } - return roots; } -function* walkHeadings(nodes) { - for (const node of nodes) { - if (node.type === "heading") - yield node; - if ("children" in node && Array.isArray(node.children)) { - yield* walkHeadings(node.children.filter(isBlockNode)); +function renderInlineNode(node, opts) { + node = normalizeLegacyInline(node); + switch (node.type) { + case "text": + return escapeHtml(node.value); + case "escaped_text": + return escapeHtml(node.value); + case "emphasis": + return `${renderInlines(node.children, opts)}
    `; + case "strong": + return `${renderInlines(node.children, opts)}
    `; + case "underline": + return `${renderInlines(node.children, opts)}`; + case "strike": + return `${renderInlines(node.children, opts)}
    `; + case "superscript": + return `${renderInlines(node.children, opts)}`; + case "subscript": + return `${renderInlines(node.children, opts)}`; + case "highlight": + return `${renderInlines(node.children, opts)}`; + case "code": + return `${escapeHtml(node.value)}`; + case "link": { + if (isUnresolvedReference(node)) + return escapeHtml(referenceSourceText(node.rawRef)); + if (insideLink) + return renderInlines(node.children, opts); + const titleAttr = node.title !== void 0 ? ` title="${escapeAttr(node.title)}"` : ""; + const href = escapeAttr(sanitizeUrl(node.href, opts)); + const label = withinLink(() => renderInlines(node.children, opts)); + return `${label}`; } - if (node.type === "figure") { - if ("children" in node.target && Array.isArray(node.target.children)) { - yield* walkHeadings(node.target.children.filter(isBlockNode)); + case "image": + return renderImage(node, opts); + case "span": + return renderSemanticSpan(node, opts); + case "math": { + const base = node.display ? "math display" : "math inline"; + if (opts.mode === "static" && opts.renderers?.math) { + const ssr = opts.renderers.math(node.content, node.display); + return `${ssr}`; + } + const body = node.display ? `\\[${escapeHtml(node.content)}\\]` : `\\(${escapeHtml(node.content)}\\)`; + return `${body}`; + } + case "raw_inline": + return node.format === "html" ? opts.allowRawHtml === false ? escapeHtml(node.content) : node.content : ""; + case "literal_inline": { + const text = escapeHtml(node.content); + const attrs = renderAttrs(node.attrs); + return attrs ? `${text}` : text; + } + case "symbol": { + let body; + const isStatic = opts.mode === "static"; + if (opts.extensions?.length) { + const ctx = inlineCtx(opts); + for (const e of opts.extensions) { + const staticFn = isStatic ? ownValue(e.staticInlineRenderers, node.type) : void 0; + if (staticFn) { + const out = staticFn(node, ctx); + if (out !== void 0) { + body = out; + break; + } + } + const fn = ownValue(e.inlineRenderers, node.type); + if (fn) { + const out = fn(node, ctx); + if (out !== void 0) { + body = out; + break; + } + } + } + } + if (body === void 0) + body = ownValue(opts.symbols, node.name) ?? escapeHtml(`:${node.name}:`); + return node.attrs ? `${body}` : body; + } + case "autolink": { + const display = node.text ?? (node.href.startsWith("mailto:") ? node.href.slice(7) : node.href); + if (insideLink) { + return escapeHtml(node.href.startsWith("mailto:") ? node.href.slice(7) : display); + } + const href = escapeAttr(sanitizeUrl(node.href, opts)); + return `${escapeHtml(display)}`; + } + case "mention": { + const text = `@${escapeHtml(node.user)}`; + if (insideLink || !opts.mentionUrl) + return `${text}`; + const enc = encodeURIComponent(node.user); + const href = sanitizeUrl(opts.mentionUrl.replaceAll("{name}", enc).replaceAll("{user}", enc), opts); + return `${text}`; + } + case "tag": { + const text = `#${escapeHtml(node.name)}`; + if (insideLink || !opts.tagUrl) + return `${text}`; + const href = sanitizeUrl(opts.tagUrl.replaceAll("{name}", encodeURIComponent(node.name)).replaceAll("{tag}", encodeURIComponent(node.name)), opts); + return `${text}`; + } + case "inline_extension": { + const isStatic = opts.mode === "static"; + if (opts.extensions?.length) { + const ctx = inlineCtx(opts); + for (const e of opts.extensions) { + const staticFn = isStatic ? ownValue(e.staticInlineRenderers, node.type) : void 0; + if (staticFn) { + const out = staticFn(node, ctx); + if (out !== void 0) + return out; + } + const fn = ownValue(e.renderers, node.name); + if (fn) { + const out = fn(node, ctx); + if (out !== void 0) + return out; + } + } + } + return renderExtension(node.name, node.content, node.attrs, opts); + } + case "abbreviation": { + if (suppressAutomaticAbbreviation) + return escapeHtml(node.abbr); + const fit = abbrBudget2?.charge(utf8ByteLength(node.expansion)) ?? true; + if (!fit) + return escapeHtml(node.abbr); + return `${escapeHtml(node.abbr)}`; + } + case "footnote_ref": + case "inline_footnote": + return node.number === void 0 ? escapeHtml(`[^${node.id ?? ""}]`) : `${node.number}`; + case "soft_break": + return "\n"; + case "hard_break": + return "
    \n"; + case "insert": + return `${renderInlines(node.children, opts)}`; + case "delete": + return `${renderInlines(node.children, opts)}`; + case "substitution": + return `${escapeHtml(node.oldText)}${escapeHtml(node.newText)}`; + case "critic_comment": + return `${escapeHtml(node.text)}`; + case "heading_ref": + if (node.href && insideLink) + return chargeCrossrefLabel(renderInlines(node.resolvedText ?? [], opts), node.target); + if (node.href) { + const crossrefHref = escapeAttr(sanitizeUrl(node.href, opts)); + const label = chargeCrossrefLabel(withinLink(() => renderInlines(node.resolvedText ?? [], opts)), node.target); + return `${label}`; + } + return `</#${escapeHtml(node.target)}>`; + case "caption_number": + return node.n === void 0 ? "#" : String(node.n); + case "citation_group": { + const isStatic = opts.mode === "static"; + if (opts.extensions?.length) { + const ctx = inlineCtx(opts); + for (const e of opts.extensions) { + const staticFn = isStatic ? ownValue(e.staticInlineRenderers, node.type) : void 0; + if (staticFn) { + const out = staticFn(node, ctx); + if (out !== void 0) + return out; + } + const fn = ownValue(e.inlineRenderers, node.type); + if (fn) { + const out = fn(node, ctx); + if (out !== void 0) + return out; + } + } } + return escapeHtml(node.raw); + } + case "comment": + return ""; + case "smart_punctuation": + if (opts.smartTypography === false || opts.smartTypography === "source") + return escapeHtml(node.value); + return escapeHtml(node.glyph ?? SMART_PUNCTUATION_GLYPHS[node.kind] ?? node.value); + default: { + const t = node; + throw new Error(`renderHtml: unknown inline ${t.type}`); } } } -function isBlockNode(node) { - return Boolean(node && typeof node === "object" && "type" in node); +function renderExtension(name, content, attrs, opts) { + const inner = renderInlines(content, opts); + return `${inner}`; } -function headingSymbol(heading) { - const range = heading.pos ? { - start: { line: heading.pos.startLine - 1, character: 0 }, - end: { line: heading.pos.endLine - 1, character: 200 } - } : { - start: { line: 0, character: 0 }, - end: { line: 0, character: 0 } - }; - return { - name: plainText(heading.children) || `Heading ${heading.level}`, - kind: import_node.SymbolKind.String, - range, - selectionRange: range, - children: [] - }; +function escapeHtml(s) { + return stripBidiControls(s).replace(/[&<>\u00a0\ue000]/g, (c) => HTML_ESCAPE[c]); } -function plainText(nodes) { - let out = ""; - for (const node of nodes) { +function escapeAttr(s) { + return s.replace(/[&<>"']/g, (c) => c === '"' ? """ : c === "'" ? "'" : HTML_ESCAPE[c]); +} +var abbrBudget2, suppressAutomaticAbbreviation, docIds, DANGEROUS_URL_SCHEMES, SCHEME_PROBE_STRIP_RE, DANGEROUS_ATTR_NAMES, HTML_ATTR_NAME_RE, DANGEROUS_VALUE_SCHEMES, ASCII_WHITESPACE, URL_LIST_SEPARATORS, RENDER_MODES, CORE_SEMANTIC_SPAN_ORDER, EXTENDED_SEMANTIC_SPAN_ORDER, SEMANTIC_VALUE_ATTRIBUTE, blockDepth, inlineDepth2, insideLink, activeRenderOptions, HTML_ESCAPE; +var init_render_html = __esm({ + "node_modules/@markup-carve/carve/dist/render-html.js"() { + init_ast(); + init_abbr_budget(); + init_document_ids(); + init_bidi_controls(); + init_legacy_nodes(); + init_footnote_numbering(); + init_own_property(); + init_render_depth(); + init_unresolved_reference(); + abbrBudget2 = null; + suppressAutomaticAbbreviation = false; + docIds = null; + DANGEROUS_URL_SCHEMES = [ + // Script / inline-content / local-file vectors. + "javascript", + "vbscript", + "data", + "file", + // OS protocol-handler / command-execution schemes (CVE-2026-20841 class). + "ms-msdt", + "ms-office", + "ms-word", + "ms-excel", + "ms-powerpoint", + "ms-access", + "ms-visio", + "ms-project", + "ms-publisher", + "ms-infopath", + "ms-spd", + "ms-search", + "search-ms", + "ms-cxh", + "ms-cxh-full", + "shell", + "vscode", + "vscode-insiders", + "jar" + ]; + SCHEME_PROBE_STRIP_RE = /[\u0000-\u0008\u000e-\u001f\u007f-\u009f\s]+/gu; + DANGEROUS_ATTR_NAMES = /* @__PURE__ */ new Set(["srcdoc", "formaction"]); + HTML_ATTR_NAME_RE = /^[A-Za-z_:][A-Za-z0-9_.:-]*$/; + DANGEROUS_VALUE_SCHEMES = new Set(DANGEROUS_URL_SCHEMES); + ASCII_WHITESPACE = "\\t\\n\\f\\r "; + URL_LIST_SEPARATORS = /* @__PURE__ */ new Map([ + ["srcset", new RegExp(`[,${ASCII_WHITESPACE}]+`)], + ["imagesrcset", new RegExp(`[,${ASCII_WHITESPACE}]+`)], + ["ping", new RegExp(`[${ASCII_WHITESPACE}]+`)], + ["attributionsrc", new RegExp(`[${ASCII_WHITESPACE}]+`)] + ]); + RENDER_MODES = /* @__PURE__ */ new Set(["interactive", "static"]); + CORE_SEMANTIC_SPAN_ORDER = ["abbr", "time", "kbd"]; + EXTENDED_SEMANTIC_SPAN_ORDER = ["abbr", "time", "samp", "var", "kbd", "cite", "dfn"]; + SEMANTIC_VALUE_ATTRIBUTE = { + abbr: "title", + dfn: "title", + time: "datetime" + }; + blockDepth = 0; + inlineDepth2 = 0; + insideLink = false; + activeRenderOptions = {}; + HTML_ESCAPE = { + "&": "&", + "<": "<", + ">": ">", + "\xA0": " ", + // Internal non-breaking-space placeholder (line-block indent / escaped space). + "\uE000": " " + }; + } +}); + +// node_modules/@markup-carve/carve/dist/profile.js +function withSupertype(type) { + const parent = ownValue(SUPERTYPE, type); + return parent === void 0 ? [type] : [type, parent]; +} +function canonicalType(type) { + switch (type) { + // ----- block ----- + case "paragraph": + return "paragraph"; + case "heading": + return "heading"; + case "code_block": + return "code_block"; + case "block_quote": + return "block_quote"; + case "list": + return "list"; + case "list_item": + return "list_item"; + case "table": + return "table"; + case "table_row": + return "table_row"; + case "table_cell": + return "table_cell"; + case "thematic_break": + return "thematic_break"; + case "div": + return "div"; + case "admonition": + return "admonition"; + case "raw_block": + return "raw_block"; + case "definition_list": + return "definition_list"; + case "figure": + return "figure"; + case "figure_group": + return "figure_group"; + case "comment": + return "comment"; + // ----- inline ----- + case "text": + return "text"; + // Its own canonical name, NOT folded into `text`. profiles.md lists + // `escaped_text` in the normative inline vocabulary, and ast.ts explains + // why the type exists at all: the escape carries intent the bare character + // does not. Folding it here made `denyInline(['escaped_text'])` a silent + // no-op while the vocabulary said it was nameable (carve-js#474). Contrast + // `smart_punctuation` below, which profiles.md explicitly excludes. + case "escaped_text": + return "escaped_text"; + // Smart typography is ordinary visible prose, so it shares text's trust + // class rather than becoming a nameable type of its own (the same way the + // inline literal folds into `code`). + case "smart_punctuation": + return "text"; + case "emphasis": + return "emphasis"; + case "strong": + return "strong"; + case "underline": + return "underline"; + case "strike": + return "strike"; + case "inline_extension": + return "inline_extension"; + case "mention": + return "mention"; + // carve-php treats `#tag` under the mention feature. + case "tag": + return "mention"; + case "code": + return "code"; + case "link": + return "link"; + case "autolink": + return "autolink"; + case "image": + return "image"; + case "soft_break": + return "soft_break"; + case "hard_break": + return "hard_break"; + case "raw_inline": + return "raw_inline"; + case "literal_inline": + return "code"; + case "footnote_ref": + case "inline_footnote": + return type; + case "span": + return "span"; + case "superscript": + return "superscript"; + case "subscript": + return "subscript"; + case "highlight": + return "highlight"; + case "insert": + return "insert"; + case "delete": + return "delete"; + case "symbol": + return "symbol"; + case "math": + return "math"; + case "abbreviation": + return "abbreviation"; + default: + return type; + } +} +function parseHost(url) { + const m = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/([^/?#]*)/.exec(url); + if (!m) + return null; + let authority = m[1]; + const at = authority.lastIndexOf("@"); + if (at !== -1) + authority = authority.slice(at + 1); + const colon = authority.lastIndexOf(":"); + if (colon !== -1 && !authority.includes("]")) + authority = authority.slice(0, colon); + return authority === "" ? null : authority; +} +function formatProfileViolation(v) { + let msg = `'${v.nodeType}' is not allowed: ${v.reason}`; + if (v.reasonDescription !== null) + msg += ` (${v.reasonDescription})`; + return msg; +} +var CANONICAL_BLOCK_TYPES, CANONICAL_INLINE_TYPES, BLOCK_SET, INLINE_SET, SUPERTYPE, LinkPolicy, Profile, ProfileViolationError; +var init_profile = __esm({ + "node_modules/@markup-carve/carve/dist/profile.js"() { + init_own_property(); + init_render_html(); + CANONICAL_BLOCK_TYPES = [ + "paragraph", + "heading", + "code_block", + "block_quote", + "list", + "list_item", + "table", + "table_row", + "table_cell", + "thematic_break", + "div", + "raw_block", + "footnote", + "definition_list", + "definition_term", + "definition_description", + "section", + "admonition", + "line_block", + "comment", + "figure", + "figure_group", + "caption", + // PART 12 §18 gives a citation definition its own block type, and + // `spec/docs/profiles.md` lists it alongside the other two definition kinds. + // This engine already EMITS it (markup-carve/carve-js#1122); only the + // nameable vocabulary was behind, and a type the vocabulary does not know + // falls through the string-only `isTypeAllowed` as ALLOWED - the opposite of + // what the same profile answers with an axis. + "citation_definition", + // A DEFINITION LINE IS CONTENT, so both definition types are deniable + // (carve#826, the ruling on carve#771). They render nothing in HTML and are + // real output on the `carve`, `markdown` and `plain` targets, so a profile + // that cannot name them cannot describe those targets. + // + // The FILTER already did the right thing; what was wrong is the string-only + // query. `isTypeAllowed(t)` has no axis to resolve on, so it fell back to + // "not in the vocabulary, therefore allowed" and answered the opposite of + // `isTypeAllowed(t, true)` for the same profile - the exact drift carve-js#712 + // fixed for five other types, with this pair left out (carve-js#753). + "abbreviation_def", + "link_reference_definition", + // Listed by profiles.md's block vocabulary and missing here until carve-js#712: + // the page publishes frontmatter as a root field (PART 12 section 2), so denying it + // is a real decision about what leaves the engine even though the HTML is + // unchanged. carve-rs and carve-php both name it. + "frontmatter" + ]; + CANONICAL_INLINE_TYPES = [ + "text", + "autolink", + "emphasis", + "strong", + "underline", + "strike", + "inline_extension", + "mention", + "code", + "link", + "image", + "soft_break", + "hard_break", + "raw_inline", + "escaped_text", + "footnote_ref", + "inline_footnote", + "span", + "superscript", + "subscript", + "highlight", + "insert", + "delete", + "symbol", + "math", + "abbreviation", + // Listed by profiles.md's inline vocabulary and missing here until carve-js#712. + // `canonicalType`'s default arm already calls four of these "their own canonical + // names, not absences" (carve-js#472) - so the mapper and the vocabulary + // disagreed, and `isTypeAllowed(type)` with no axis fell through to step 3 and + // ALLOWED a type the caller had just denied. + "caption_number", + "citation_group", + "critic_comment", + "heading_ref", + "substitution" + ]; + BLOCK_SET = new Set(CANONICAL_BLOCK_TYPES); + INLINE_SET = new Set(CANONICAL_INLINE_TYPES); + SUPERTYPE = { + autolink: "link", + admonition: "div" + }; + LinkPolicy = class _LinkPolicy { + allowedSchemes = null; + deniedSchemes = ["javascript", "vbscript", "data", "file"]; + allowedDomains = null; + deniedDomains = []; + allowExternal = true; + allowInternal = true; + relAttributes = []; + /** Allow all URLs except dangerous schemes. */ + static unrestricted() { + return new _LinkPolicy(); + } + /** Allow only internal links (relative URLs, fragments). */ + static internalOnly() { + return new _LinkPolicy().setAllowExternal(false); + } + /** Allow only links to specific domains. */ + static allowlist(domains) { + return new _LinkPolicy().setAllowedDomains(domains); + } + getAllowedSchemes() { + return this.allowedSchemes; + } + setAllowedSchemes(schemes) { + this.allowedSchemes = schemes !== null ? schemes.map((s) => s.toLowerCase()) : null; + return this; + } + getDeniedSchemes() { + return this.deniedSchemes; + } + setDeniedSchemes(schemes) { + this.deniedSchemes = schemes.map((s) => s.toLowerCase()); + return this; + } + getAllowedDomains() { + return this.allowedDomains; + } + setAllowedDomains(domains) { + this.allowedDomains = domains; + return this; + } + getDeniedDomains() { + return this.deniedDomains; + } + setDeniedDomains(domains) { + this.deniedDomains = domains; + return this; + } + getAllowExternal() { + return this.allowExternal; + } + setAllowExternal(allow) { + this.allowExternal = allow; + return this; + } + getAllowInternal() { + return this.allowInternal; + } + setAllowInternal(allow) { + this.allowInternal = allow; + return this; + } + getRelAttributes() { + return this.relAttributes; + } + setRelAttributes(attrs) { + this.relAttributes = attrs; + return this; + } + /** Add a rel attribute applied to all surviving links. */ + addRelAttribute(attr) { + if (!this.relAttributes.includes(attr)) { + this.relAttributes.push(attr); + } + return this; + } + /** + * Check whether a URL is permitted by this policy. + * + * The scheme is read through `SCHEME_PROBE_STRIP_RE`, the renderer's own + * probe class, so this rule and PART 9 §25's answer the same way about a + * scheme split by a character a URL consumer discards. That is a NARROWING: + * stripping only removes characters, so the deny lists can recognize more and + * can never recognize less, and no legitimate scheme carries one (a scheme is + * a letter followed by letters, digits, `+`, `-` and `.`). + * + * Prefix classification follows the URL parser's alphabet: leading/trailing + * ASCII C0 controls and space are ignored, and `\\` is slash-equivalent for + * special URLs. JavaScript `trim()` is deliberately not used; it strips many + * Unicode spaces that a URL parser keeps as relative-path content. + * + * @param baseHost Current document's host (for external detection). + */ + isUrlAllowed(url, baseHost = null) { + url = url.replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/g, ""); + if (url === "") + return true; + const prefixUrl = url.replace(/\\/g, "/"); + if (url.startsWith("#")) + return this.allowInternal; + if (prefixUrl.startsWith("//")) + return this.isProtocolRelativeUrlAllowed(prefixUrl, baseHost); + if (prefixUrl.startsWith("/") || prefixUrl.startsWith("./") || prefixUrl.startsWith("../")) { + return this.allowInternal; + } + const colonPos = url.indexOf(":"); + if (colonPos !== -1) { + const rawScheme = url.slice(0, colonPos).toLowerCase(); + const scheme = rawScheme.replace(SCHEME_PROBE_STRIP_RE, ""); + if (this.deniedSchemes.includes(scheme)) + return false; + if (this.allowedSchemes !== null && !this.allowedSchemes.includes(rawScheme)) + return false; + if (scheme === "mailto" || scheme === "tel") + return true; + if (scheme === "http" || scheme === "https") { + const host = parseHost(scheme + url.slice(colonPos)); + if (host !== null) { + if (this.isDomainDenied(host)) + return false; + if (this.allowedDomains !== null && !this.isDomainAllowed(host)) + return false; + if (!this.allowExternal) { + if (baseHost !== null && !this.isSameHost(host, baseHost)) + return false; + if (baseHost === null) + return false; + } + } + } + } + return true; + } + isProtocolRelativeUrlAllowed(url, baseHost) { + if (this.allowedSchemes !== null) { + const schemes = this.allowedSchemes.map((s) => s.toLowerCase()); + if (!schemes.includes("http") && !schemes.includes("https")) + return false; + } + const host = parseHost("https:" + url); + if (host === null) + return false; + if (this.isDomainDenied(host)) + return false; + if (this.allowedDomains !== null && !this.isDomainAllowed(host)) + return false; + if (!this.allowExternal) { + if (baseHost !== null && !this.isSameHost(host, baseHost)) + return false; + if (baseHost === null) + return false; + } + return true; + } + isDomainDenied(host) { + host = host.toLowerCase(); + return this.deniedDomains.some((d) => host === d.toLowerCase() || host.endsWith("." + d.toLowerCase())); + } + isDomainAllowed(host) { + if (this.allowedDomains === null) + return true; + host = host.toLowerCase(); + return this.allowedDomains.some((d) => host === d.toLowerCase() || host.endsWith("." + d.toLowerCase())); + } + isSameHost(a, b) { + return a.toLowerCase() === b.toLowerCase(); + } + }; + Profile = class _Profile { + static ACTION_STRIP = "strip"; + static ACTION_TO_TEXT = "to_text"; + static ACTION_ERROR = "error"; + /** + * Default maximum input length (UTF-8 bytes) for the untrusted `comment` + * preset - a DoS backstop enforced pre-parse. Generous for a comment body; + * override with `setMaxLength(0)` to disable or another value to retune. + */ + static COMMENT_MAX_LENGTH = 1e5; + /** + * Default maximum input length (UTF-8 bytes) for the untrusted `minimal` + * preset (chat / micro-posts). Override with `setMaxLength(...)` as needed. + */ + static MINIMAL_MAX_LENGTH = 1e4; + name = "custom"; + description = ""; + featureReasons = {}; + allowedInline = null; + allowedBlock = null; + deniedInline = []; + deniedBlock = []; + linkPolicy = null; + maxNesting = 0; + maxLength = 0; + disallowedAction = _Profile.ACTION_TO_TEXT; + /** All features enabled. Use only for trusted content. */ + static full() { + const p = new _Profile(); + p.name = "full"; + p.description = "All features enabled. Use only for trusted content."; + return p; + } + /** Blog posts and articles: all formatting, no raw HTML. */ + static article() { + const p = new _Profile(); + p.name = "article"; + p.description = "Blog posts and articles. All formatting, no raw HTML."; + p.denyBlock(["raw_block"]).denyInline(["raw_inline"]); + p.featureReasons = { + raw_block: "Raw HTML blocks are disabled to prevent XSS attacks. Use djot markup instead.", + raw_inline: "Raw HTML is disabled to prevent XSS attacks. Use djot markup instead." + }; + return p; + } + /** User comments: basic formatting only, nofollow links. */ + static comment() { + const p = new _Profile(); + p.name = "comment"; + p.description = "User comments. Basic formatting only, nofollow links."; + p.allowInline([ + "text", + "emphasis", + "strong", + "underline", + "strike", + "inline_extension", + "mention", + "code", + "link", + "soft_break", + "hard_break", + "delete", + "insert", + "highlight", + "superscript", + "subscript" + ]).allowBlock(["paragraph", "list", "list_item", "block_quote", "code_block"]).setLinkPolicy(LinkPolicy.unrestricted().addRelAttribute("nofollow").addRelAttribute("ugc")).setMaxNesting(4).setMaxLength(_Profile.COMMENT_MAX_LENGTH); + p.featureReasons = { + heading: "Headings are disabled in comments to prevent disrupting page structure.", + image: "Images are disabled to prevent spam, inappropriate content, and bandwidth abuse.", + table: "Tables are disabled as they are too complex for comment formatting.", + footnote: "Footnotes are disabled as they are unnecessary for comments.", + footnote_ref: "Footnotes are disabled as they are unnecessary for comments.", + inline_footnote: "Footnotes are disabled as they are unnecessary for comments.", + raw_block: "Raw HTML is disabled for security reasons.", + raw_inline: "Raw HTML is disabled for security reasons.", + div: "Custom containers are disabled in comments.", + section: "Sections are disabled in comments.", + definition_list: "Definition lists are disabled in comments.", + definition_term: "Definition lists are disabled in comments.", + definition_description: "Definition lists are disabled in comments.", + thematic_break: "Horizontal rules are disabled in comments.", + line_block: "Line blocks are disabled in comments.", + span: "Custom spans are disabled in comments.", + symbol: "Symbol markup is disabled in comments.", + math: "Math markup is disabled in comments.", + abbreviation: "Abbreviations are disabled in comments." + }; + return p; + } + /** Chat / micro-posts: non-destructive inline formatting, paragraphs and lists. */ + static minimal() { + const p = new _Profile(); + p.name = "minimal"; + p.description = "Chat/micro-posts. Non-destructive inline formatting, paragraphs and lists."; + p.allowInline([ + "text", + "emphasis", + "strong", + "underline", + "strike", + "inline_extension", + "mention", + "code", + "delete", + "insert", + "superscript", + "subscript", + "soft_break", + "hard_break" + ]).allowBlock(["paragraph", "list", "list_item"]).setMaxNesting(2).setMaxLength(_Profile.MINIMAL_MAX_LENGTH); + p.featureReasons = { + link: "Links are disabled in this minimal context.", + highlight: "Highlighting is disabled in this minimal context.", + image: "Images are disabled in this minimal context.", + raw_inline: "Raw HTML is disabled for security reasons.", + footnote_ref: "Footnotes are disabled in this minimal context.", + inline_footnote: "Footnotes are disabled in this minimal context.", + span: "Custom spans are disabled in this minimal context.", + symbol: "Symbols are disabled in this minimal context.", + math: "Math is disabled in this minimal context.", + abbreviation: "Abbreviations are disabled in this minimal context.", + default: "Only basic text formatting and lists are allowed in this context." + }; + return p; + } + getName() { + return this.name; + } + getDescription() { + return this.description; + } + /** Reason a node type is disallowed, or null if it is allowed / no reason. */ + getReasonDisallowed(canonical2, isBlock2) { + if (this.isTypeAllowed(canonical2, isBlock2)) + return null; + return this.featureReasons[canonical2] ?? this.featureReasons["default"] ?? null; + } + getFeatureReasons() { + return this.featureReasons; + } + setFeatureReason(canonical2, reason) { + this.featureReasons[canonical2] = reason; + return this; + } + /** Set allowed inline types (null = all allowed). */ + allowInline(types) { + this.allowedInline = types; + return this; + } + /** Set allowed block types (null = all allowed). */ + allowBlock(types) { + this.allowedBlock = types; + return this; + } + denyInline(types) { + this.deniedInline = [...this.deniedInline, ...types]; + return this; + } + denyBlock(types) { + this.deniedBlock = [...this.deniedBlock, ...types]; + return this; + } + getAllowedInline() { + return this.allowedInline; + } + getAllowedBlock() { + return this.allowedBlock; + } + getDeniedInline() { + return this.deniedInline; + } + getDeniedBlock() { + return this.deniedBlock; + } + getLinkPolicy() { + return this.linkPolicy; + } + setLinkPolicy(policy) { + this.linkPolicy = policy; + return this; + } + getMaxNesting() { + return this.maxNesting; + } + /** Set maximum block-container nesting depth (0 = unlimited). */ + setMaxNesting(max) { + this.maxNesting = max; + return this; + } + getMaxLength() { + return this.maxLength; + } + /** Set maximum input length in bytes (0 = unlimited). */ + setMaxLength(max) { + this.maxLength = max; + return this; + } + getDisallowedAction() { + return this.disallowedAction; + } + /** Set action for disallowed elements. */ + onDisallowed(action) { + this.disallowedAction = action; + return this; + } + /** + * Whether a canonical type string is allowed by this profile. + * + * `isBlock` is the node's OWN axis, and is what makes a type outside the + * vocabulary resolvable: block-vs-inline cannot be read off a type string the + * vocabulary does not know, and it is unambiguous at the node. + * + * profiles.md "Resolution" makes the three steps exhaustive and forbids a + * fourth that denies unrecognized types. This used to have that fourth step, + * and it meant a construct whose type predated the vocabulary rendered as + * NOTHING - not degraded to text, gone - under any profile at all, including + * one that denies nothing. `{~old~>new~}` lost both the old wording and the + * new (carve#419). + * + * An allow list still excludes an unknown type, so a restrictive profile + * loses no safety: step 2 handles it by construction. + */ + isTypeAllowed(canonical2, isBlock2) { + if (canonical2 === "document") + return true; + if (INLINE_SET.has(canonical2)) + return this.isInlineAllowed(canonical2); + if (BLOCK_SET.has(canonical2)) + return this.isBlockAllowed(canonical2); + if (isBlock2 !== void 0) { + return isBlock2 ? this.isBlockAllowed(canonical2) : this.isInlineAllowed(canonical2); + } + return this.allowedInline === null && this.allowedBlock === null; + } + isInlineAllowed(type) { + const names = withSupertype(type); + if (names.some((n) => this.deniedInline.includes(n))) + return false; + if (this.allowedInline !== null) + return names.some((n) => this.allowedInline.includes(n)); + return true; + } + isBlockAllowed(type) { + const names = withSupertype(type); + if (names.some((n) => this.deniedBlock.includes(n))) + return false; + if (this.allowedBlock !== null) + return names.some((n) => this.allowedBlock.includes(n)); + return true; + } + /** Summary of what this profile allows/denies. */ + getSummary() { + return { + name: this.name, + description: this.description, + allowed_block: this.allowedBlock ?? "all", + allowed_inline: this.allowedInline ?? "all", + denied_block: this.deniedBlock, + denied_inline: this.deniedInline + }; + } + }; + ProfileViolationError = class extends Error { + violations; + constructor(violations) { + super("Profile violations: " + violations.map(formatProfileViolation).join("; ")); + this.violations = violations; + this.name = "ProfileViolationError"; + } + }; + } +}); + +// node_modules/@markup-carve/carve/dist/profile-filter.js +function resolveCanonical(node) { + if (node.type === "footnote_ref" || node.type === "inline_footnote") { + return node["inline"] !== void 0 ? "inline_footnote" : "footnote_ref"; + } + if (node.type === "admonition") { + const kind2 = node["kind"]; + if (kind2 === void 0 || !CANONICAL_ADMONITION_KINDS.has(kind2)) + return "div"; + } + return canonicalType(node.type); +} +function childArrays(node) { + const arrays = []; + const push3 = (v, block, wrap) => { + if (Array.isArray(v)) { + arrays.push(wrap ? { list: v, block, wrap } : { list: v, block }); + } + }; + switch (node.type) { + case "document": + push3(node["children"], true); + break; + case "list": + push3(node["items"], true, "list_item"); + break; + case "list_item": + push3(node["children"], true); + break; + case "table": + push3(node["rows"], true, "table_row"); + if (node["caption"]) + push3(node["caption"], false); + break; + case "table_row": + push3(node["cells"], true, "table_cell"); + break; + case "table_cell": + push3(node["children"], false); + break; + case "definition_list": + break; + case "figure": + if (node["caption"]) + push3(node["caption"], false); + break; + case "figure_group": + if (node["caption"]) + push3(node["caption"], false); + push3(node["children"], true); + break; + case "footnote_ref": + case "inline_footnote": + if (node["inline"]) + push3(node["inline"], false); + break; + case "inline_extension": + push3(node["content"], false); + break; + case "admonition": + if (node["title"]) + push3(node["title"], false); + push3(node["children"], true); + break; + case "block_quote": + push3(node["children"], true); + break; + case "heading": + case "paragraph": + push3(node["children"], false); + break; + default: + push3(node["children"], false); + break; + } + return arrays; +} +function isBlockNode(node) { + const c = resolveCanonical(node); + if (c === void 0) { + return BLOCK_JS_TYPES.has(node.type); + } + return BLOCK_CANONICAL.has(c); +} +function allChildNodes(node) { + if (node.type === "definition_list") { + const out2 = []; + const items = node["items"] ?? []; + for (const item2 of items) { + for (const term of item2.terms) + for (const n of term) + out2.push(n); + for (const def of item2.definitions) + for (const n of def) + out2.push(n); + } + return out2; + } + if (node.type === "figure") { + const out2 = []; + const target = node["target"]; + if (target) + out2.push(target); + const caption = node["caption"]; + if (caption) + for (const n of caption) + out2.push(n); + return out2; + } + const out = []; + for (const { list } of childArrays(node)) + for (const n of list) + out.push(n); + return out; +} +function textWithBreaks(content) { + const lines = content.split("\n"); + const out = []; + const last = lines.length - 1; + lines.forEach((line2, idx) => { + if (line2 !== "") + out.push({ type: "text", value: line2 }); + if (idx < last) + out.push({ type: "hard_break" }); + }); + return out; +} +function rendersNothing(node) { + return node.type === "comment" || node.type === "frontmatter" || // A definition line produces no output of its own - it feeds the inline + // `abbreviation` nodes that do. Degrading it to text has nothing to + // substitute, so it took the missing-extractor path and injected a literal + // `[abbreviation_def]` paragraph into the document. + node.type === "abbreviation_def" || // The same shape, and left behind when the line above was added: a link + // reference definition renders nothing where it was written either, it + // feeds the `link` or `image` that does. profiles.md names the two + // together - "`link_reference_definition` is the `abbreviation_def` case + // exactly" - so denying one injected `[link_reference_definition]` into the + // page while denying the other did not (carve-js#701). + node.type === "link_reference_definition"; +} +function extractTextContent(node) { + switch (node.type) { + case "image": { + const alt = node["alt"] ?? ""; + return alt !== "" ? `[img: ${alt}]` : "[img]"; + } + case "heading": { + const prefix = "#".repeat(node["level"]) + " "; + let text = ""; + for (const child of node["children"] ?? []) + text += extractTextContent(child); + return prefix + text; + } + case "code_block": { + const content = node["content"] ?? ""; + if (content.includes("\n")) + return "```\n" + content + "\n```"; + return "`" + content + "`"; + } + case "link": + case "autolink": { + let text = ""; + for (const child of node["children"] ?? []) + text += extractTextContent(child); + if (text === "" && node.type === "autolink") + return node["href"] ?? ""; + return text; + } + case "table": { + const rows = []; + for (const row of node["rows"] ?? []) { + if (row.type === "table_row") { + const cells = []; + for (const cell of row["cells"] ?? []) + cells.push(extractTextContent(cell)); + rows.push(cells.join(" | ")); + } + } + return rows.join("\n"); + } + case "block_quote": { + const paras = []; + for (const child of node["children"] ?? []) { + const t = extractTextContent(child); + if (t !== "") + paras.push("> " + t); + } + return paras.join("\n"); + } + case "definition_list": { + const parts2 = []; + const items = node["items"] ?? []; + for (const item2 of items) { + for (const term of item2.terms) { + let t = ""; + for (const tn of term) + t += extractTextContent(tn); + if (t !== "") + parts2.push(t); + } + for (const def of item2.definitions) { + const ds = []; + for (const dn of def) { + const t = extractTextContent(dn); + if (t !== "") + ds.push(t); + } + if (ds.length) + parts2.push("- " + ds.join(" ")); + } + } + return parts2.join("\n"); + } + case "list": { + const items = []; + const ordered = node["ordered"] === true; + let index2 = node["start"] ?? 1; + for (const it of node["items"] ?? []) { + if (it.type === "list_item") { + const t = extractTextContent(it); + if (t !== "") { + items.push((ordered ? `${index2}. ` : "- ") + t); + index2++; + } + } + } + return items.join("\n"); + } + case "symbol": + return ":" + node["name"] + ":"; + case "footnote_ref": + case "inline_footnote": { + if (node["inline"] === void 0) { + return "[^" + (node["id"] ?? "") + "]"; + } + let t = ""; + for (const child of node["inline"] ?? []) + t += extractTextContent(child); + return t; + } + case "thematic_break": + return "---"; + case "text": + case "escaped_text": + return node["value"] ?? ""; + case "code": + return node["value"] ?? ""; + case "math": + return node["content"] ?? ""; + case "raw_block": + case "raw_inline": + case "literal_inline": + return node["content"] ?? ""; + case "soft_break": + return " "; + case "hard_break": + return "\n"; + case "mention": + return "@" + node["user"]; + case "tag": + return "#" + node["name"]; + case "abbreviation": + return node["abbr"] ?? ""; + case "comment": + return ""; + // These keep their text in FIELDS rather than children, so the generic + // child walk below returns '' and the node is deleted - losing visible + // words. A substitution lost BOTH the old wording and the new one under + // any profile that disallowed it (carve#419). + case "substitution": + return (node["oldText"] ?? "") + (node["newText"] ?? ""); + case "critic_comment": + return node["text"] ?? ""; + // A citation group renders from its items; `raw` is the author's source + // form, which is the closest honest degradation. + case "citation_group": + return node["raw"] ?? ""; + default: + break; + } + const children = allChildNodes(node); + if (children.length === 0) + return ""; + const inlineConcat = INLINE_CONCAT.has(node.type); + const parts = []; + for (const child of children) { + const t = extractTextContent(child); + if (t !== "") + parts.push(t); + } + return parts.join(inlineConcat ? "" : " "); +} +function subtreeHasFootnote(node) { + const stack = [node]; + while (stack.length > 0) { + const cur = stack.pop(); + if (Array.isArray(cur)) { + for (const item2 of cur) + stack.push(item2); + continue; + } + if (cur === null || typeof cur !== "object") + continue; + const type = cur.type; + if (type === "footnote_ref" || type === "inline_footnote") + return true; + for (const value of Object.values(cur)) { + if (value !== null && typeof value === "object") + stack.push(value); + } + } + return false; +} +function applyProfile(doc, profile, baseHost = null) { + return new ProfileFilter(baseHost).filter(doc, profile); +} +var BLOCK_CANONICAL, BLOCK_JS_TYPES, ProfileFilter, INLINE_CONCAT; +var init_profile_filter = __esm({ + "node_modules/@markup-carve/carve/dist/profile-filter.js"() { + init_ast(); + init_footnote_numbering(); + init_profile(); + BLOCK_CANONICAL = /* @__PURE__ */ new Set([ + "paragraph", + "heading", + "code_block", + "block_quote", + "list", + "list_item", + "table", + "table_row", + "table_cell", + "thematic_break", + "div", + "raw_block", + "footnote", + "definition_list", + "definition_term", + "definition_description", + "section", + "line_block", + "comment", + "figure", + "figure_group", + "caption" + ]); + BLOCK_JS_TYPES = /* @__PURE__ */ new Set([ + "heading", + "paragraph", + "block_quote", + "list", + "code_block", + "thematic_break", + "table", + "admonition", + "div", + "definition_list", + "figure", + "figure_group", + "image", + "abbreviation_def", + "raw_block", + "comment" + ]); + ProfileFilter = class { + baseHost; + violations = []; + /** Whether this run removed something that changes footnote numbering. */ + footnotesChanged = false; + /** + * What each replaced node became, so a mark held by IDENTITY survives. + * + * Read only by {@link remapTrailers}. Keyed on the node object, so it costs + * nothing on a document with no denied nodes and holds at most one entry per + * conversion on one that has them. + */ + replacements = /* @__PURE__ */ new Map(); + constructor(baseHost) { + this.baseHost = baseHost; + } + filter(doc, profile) { + this.violations = []; + this.footnotesChanged = false; + this.replacements = /* @__PURE__ */ new Map(); + this.filterChildArrays(doc, profile, 0); + const defs = doc.footnoteDefs; + if (defs) { + for (const blocks of Object.values(defs)) { + this.filterArray(blocks, profile, 1, true); + } + } + this.filterRootFields(doc, profile); + this.cleanupEmptyContainers(doc); + if (defs) { + for (const blocks of Object.values(defs)) + this.cleanupArray(blocks); + } + if (this.footnotesChanged) + numberFootnotes(doc); + this.remapTrailers(doc); + return { doc, violations: this.violations }; + } + /** + * Filter every child array of `parent`. Each direct child sits at `depth`. + * Iterates a snapshot of each array (matching carve-php, which copies + * getChildren() before mutating), then locates the live slot per child so + * to_text/strip removals don't shift the walk. + */ + filterChildArrays(parent, profile, depth) { + if (parent.type === "definition_list") { + this.filterDefinitionList(parent, profile, depth); + return; + } + if (parent.type === "figure") { + this.filterFigure(parent, profile, depth); + return; + } + for (const { list, block, wrap } of childArrays(parent)) { + this.filterArray(list, profile, depth, block, wrap); + } + } + filterArray(list, profile, depth, block, wrap) { + const snapshot = [...list]; + for (const child of snapshot) { + const index2 = list.indexOf(child); + if (index2 === -1) + continue; + const slot = wrap ? { list, index: index2, block, wrap } : { list, index: index2, block }; + const maxNesting = profile.getMaxNesting(); + if (maxNesting > 0 && depth > maxNesting) { + this.handleViolation(child, slot, profile, "max_nesting_exceeded"); + continue; + } + const canonical2 = resolveCanonical(child); + const allowed = profile.isTypeAllowed(canonical2, block); + if (!allowed) { + this.handleViolation(child, slot, profile, "element_not_allowed"); + continue; + } + const policy = profile.getLinkPolicy(); + if (policy !== null && (child.type === "link" || child.type === "autolink")) { + if (!this.filterLink(child, slot, profile, policy)) + continue; + } + if (policy !== null && child.type === "image") { + if (!this.filterImage(child, slot, profile, policy)) + continue; + } + this.filterChildArrays(child, profile, depth + 1); + } + } + filterDefinitionList(parent, profile, depth) { + const items = parent["items"]; + if (!items) + return; + for (const item2 of items) { + for (const term of item2.terms) { + this.filterArray(term, profile, depth + 1, false); + } + for (const defBlocks of item2.definitions) { + this.filterArray(defBlocks, profile, depth + 1, true); + } + } + } + filterFigure(parent, profile, depth) { + const caption = parent["caption"]; + if (caption) + this.filterArray(caption, profile, depth + 1, false); + const target = parent["target"]; + if (!target) + return; + const wrapper = [target]; + this.filterArray(wrapper, profile, depth + 1, true); + if (wrapper.length === 0) { + delete parent["target"]; + return; + } + const newTarget = wrapper[0]; + if (newTarget !== target) + parent["target"] = newTarget; + } + /** Returns true if the link survives (allowed). */ + filterLink(node, slot, profile, policy) { + const url = node["href"]; + if (!policy.isUrlAllowed(url ?? "", this.baseHost)) { + this.handleViolation(node, slot, profile, "link_not_allowed"); + return false; + } + this.applyRelAttributes(node, policy); + return true; + } + /** Returns true if the image survives (allowed). */ + filterImage(node, slot, profile, policy) { + const url = node["src"] ?? ""; + if (!policy.isUrlAllowed(url, this.baseHost)) { + this.handleViolation(node, slot, profile, "image_not_allowed"); + return false; + } + return true; + } + applyRelAttributes(node, policy) { + const relAttrs = policy.getRelAttributes(); + if (relAttrs.length === 0) + return; + const attrs = node.attrs ??= {}; + const kv = attrs.keyValues ??= {}; + const existing = kv["rel"]; + const parts = existing !== void 0 && existing !== "" ? existing.split(" ") : []; + for (const rel of relAttrs) + if (!parts.includes(rel)) + parts.push(rel); + kv["rel"] = parts.join(" "); + attrs.order ??= []; + if (!attrs.order.includes("rel")) + attrs.order.push("rel"); + } + handleViolation(node, slot, profile, reason) { + const canonical2 = resolveCanonical(node); + const reasonDescription = profile.getReasonDisallowed(canonical2); + this.violations.push({ nodeType: canonical2, reason, reasonDescription }); + switch (profile.getDisallowedAction()) { + case Profile.ACTION_STRIP: + this.removeAt(slot); + return; + case Profile.ACTION_ERROR: + throw new ProfileViolationError(this.violations); + case Profile.ACTION_TO_TEXT: + default: + this.convertToText(node, slot); + return; + } + } + removeAt(slot) { + this.noteFootnoteLoss(slot.list[slot.index]); + slot.list.splice(slot.index, 1); + } + replaceAt(slot, replacement) { + const replaced = slot.list[slot.index]; + this.noteFootnoteLoss(replaced); + if (replaced !== void 0) + this.replacements.set(replaced, replacement); + slot.list[slot.index] = replacement; + } + /** + * A trailer's node after filtering, or undefined when it did not survive. + * + * Follows the chain rather than reading one step: nothing produces a second + * replacement of the same slot today, and a lookup that assumed so would fail + * silently rather than loudly if something ever did. The visited set is what + * keeps a cycle from hanging the render. + */ + survivorOf(node) { + let current = node; + const seen = /* @__PURE__ */ new Set(); + while (current !== void 0 && this.replacements.has(current)) { + if (seen.has(current)) + return void 0; + seen.add(current); + current = this.replacements.get(current); + } + return current; + } + /** + * Re-point the document's trailer marks at what survived the filter. + * + * REPLACEMENT only. A node that was STRIPPED is left in the list on purpose: + * dropping it here would be a second containment test, and the renderer + * already has to make that one - it is the only place a stale mark could + * resurrect removed content, so it is the only place the check can fail. + * A copy of it here would be a check that cannot fail, which is how most of + * the defects in this repo got in. + */ + remapTrailers(doc) { + if (doc.trailerBlocks === void 0) + return; + doc.trailerBlocks = doc.trailerBlocks.map((node) => this.survivorOf(node) ?? node); + } + /** + * Flag a removal that can change footnote numbering. + * + * Both mutating paths funnel through here, so a footnote nested inside a + * removed CONTAINER counts too - dropping a div that held `[^a]` renumbers + * every note after it, exactly as a dropped reference does. + * + * Scanning only what is being removed keeps this off the cost of an ordinary + * filter run: an unbounded depth here would be a scan of a subtree the walk + * has already descended once. + */ + noteFootnoteLoss(node) { + if (this.footnotesChanged || node === void 0) + return; + if (subtreeHasFootnote(node)) + this.footnotesChanged = true; + } + convertToText(node, slot) { + if (node.type === "comment") { + this.removeAt(slot); + return; + } + let textContent = extractTextContent(node); + if (textContent === "") { + if (rendersNothing(node)) { + this.removeAt(slot); + return; + } + const canonical2 = resolveCanonical(node); + this.violations.push({ + nodeType: canonical2, + reason: "to_text_yielded_nothing", + detail: null + }); + textContent = `[${canonical2}]`; + } + if (slot.block) { + const para = { + type: "paragraph", + children: textWithBreaks(textContent) + }; + this.replaceAt(slot, this.wrapForContainer(para, textContent, slot.wrap)); + } else { + const textNode = { type: "text", value: textContent }; + this.replaceAt(slot, textNode); + } + } + /** + * Keep a to_text replacement valid for a typed-wrapper container. carve-php + * inserts a bare paragraph here; carve-js' renderer assumes `list.items` are + * list-items, `table.rows` are rows, and `table-row.cells` are cells, so we + * re-wrap to that type (a deliberate, documented structural divergence). + */ + wrapForContainer(para, textContent, wrap) { + switch (wrap) { + case "list_item": + return { type: "list_item", children: [para] }; + case "table_cell": + return { + type: "table_cell", + header: false, + children: textWithBreaks(textContent) + }; + case "table_row": + return { + type: "table_row", + cells: [ + { + type: "table_cell", + header: false, + children: textWithBreaks(textContent) + } + ] + }; + default: + return para; + } + } + // ---- empty-container cleanup (mirrors carve-php) ---- + /** + * Check the two node types this engine keeps on the Document rather than in + * the tree: frontmatter, and footnote definitions. + * + * `profiles.md` lists `frontmatter` and `footnote` in the Block vocabulary, + * so a profile can name them - but the walk above only reaches `children`, + * so naming either did nothing at all: no violation, no change (carve#422). + * A silent no-op is the specific failure a normative vocabulary exists to + * prevent, and it is worst here, because frontmatter is exactly the content + * a host restricting untrusted input would want gone. + * + * Denial REMOVES rather than degrades. Both render nothing, so there is no + * text form to fall back to - the same reasoning `rendersNothing` already + * applies inside the tree. The rendered HTML is therefore unchanged either + * way; what changes is the serialized AST and the violation report, which + * `docs/profiles.md` now states explicitly. + */ + filterRootFields(doc, profile) { + const root = doc; + if (root.frontmatter !== void 0 && !profile.isTypeAllowed("frontmatter", true)) { + this.denyRootField(profile, "frontmatter"); + delete root.frontmatter; + } + if (root.footnoteDefs !== void 0 && !profile.isTypeAllowed("footnote", true)) { + this.denyRootField(profile, "footnote"); + delete root.footnoteDefs; + this.footnotesChanged = true; + } + } + /** Record the violation, honouring `error` exactly as the in-tree path does. */ + denyRootField(profile, canonical2) { + this.violations.push({ + nodeType: canonical2, + reason: "element_not_allowed", + reasonDescription: profile.getReasonDisallowed(canonical2) + }); + if (profile.getDisallowedAction() === Profile.ACTION_ERROR) { + throw new ProfileViolationError(this.violations); + } + } + cleanupEmptyContainers(parent) { + if (parent.type === "definition_list") { + const items = parent["items"]; + if (items) { + for (const item2 of items) { + for (const def of item2.definitions) + this.cleanupArray(def); + } + } + return; + } + if (parent.type === "figure") { + const caption = parent["caption"]; + if (caption) + this.cleanupArray(caption); + const target = parent["target"]; + if (target) + this.cleanupEmptyContainers(target); + return; + } + for (const { list } of childArrays(parent)) + this.cleanupArray(list); + } + cleanupArray(list) { + let i = 0; + while (i < list.length) { + const child = list[i]; + this.cleanupEmptyContainers(child); + if (this.isEmptyContainer(child)) { + list.splice(i, 1); + continue; + } + i++; + } + } + isEmptyContainer(node) { + if (node.type === "text") + return node["value"] === ""; + const contentTypes = ["code_block", "raw_block", "raw_inline", "literal_inline", "math", "code", "comment"]; + if (contentTypes.includes(node.type)) { + const content = node["content"] ?? node["value"] ?? ""; + if (content !== "") + return false; + } + const allChildren = allChildNodes(node); + if (allChildren.length === 0) { + if (node.type === "thematic_break" || node.type === "table_cell") + return false; + if (node.type === "image" || node.type === "mention" || node.type === "tag" || node.type === "symbol" || node.type === "abbreviation" || node.type === "heading_ref" || node.type === "caption_number" || node.type === "soft_break" || node.type === "hard_break" || contentTypes.includes(node.type)) { + return false; + } + return isBlockNode(node); + } + for (const child of allChildren) + if (!this.isEmptyContainer(child)) + return false; + return true; + } + }; + INLINE_CONCAT = /* @__PURE__ */ new Set([ + "emphasis", + "strong", + "underline", + "strike", + "superscript", + "subscript", + "highlight", + "span", + "insert", + "delete", + "inline_extension", + "paragraph" + ]); + } +}); + +// node_modules/@markup-carve/carve/dist/deny-listed-destination.js +function blankDeniedDestination(url) { + const probe = url.replace(SCHEME_PROBE_STRIP_RE, ""); + const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(probe); + if (!scheme) + return url; + const lowered = scheme[1].toLowerCase(); + return DANGEROUS_URL_SCHEMES.some((denied) => denied.toLowerCase() === lowered) ? "" : url; +} +var init_deny_listed_destination = __esm({ + "node_modules/@markup-carve/carve/dist/deny-listed-destination.js"() { + init_render_html(); + } +}); + +// node_modules/@markup-carve/carve/dist/render-markdown.js +function renderMarkdown(ast, opts = {}) { + const headingIds2 = /* @__PURE__ */ new Set(); + const referencedHeadingIds = /* @__PURE__ */ new Set(); + const allBlocks = [...ast.children, ...Object.values(ast.footnoteDefs ?? {}).flat()]; + walkBlocks(allBlocks, (node) => { + if (node.type === "heading" && node.attrs?.id) + headingIds2.add(node.attrs.id); + }); + walkBlocks(allBlocks, (_node, inlines) => { + if (!inlines) + return; + walkInlines(inlines, (node, insideLink5) => { + if (insideLink5) + return; + const href = node.type === "link" || node.type === "heading_ref" ? node.href : void 0; + if (href === void 0) + return; + const id = fragmentId(href); + if (id && headingIds2.has(id)) + referencedHeadingIds.add(id); + }); + }); + const ctx = { + headingIds: headingIds2, + referencedHeadingIds, + listDepth: 0, + blockDepth: 0, + inlineDepth: 0, + abbrBudget: budgetForDocument(ast), + smartTypography: opts.smartTypography === false || opts.smartTypography === "source" ? "source" : "glyph", + definedFootnotes: new Set(Object.keys(ast.footnoteDefs ?? {})), + authoredHashes: 0 + }; + const out = renderBlocks2(ast.children, ctx); + const footnotes = renderFootnoteDefs(ast, ctx); + return stripBidiControls(normalize(`${out}${footnotes}`)); +} +function containerContent(ctx, render) { + const before = ctx.authoredHashes; + const content = trimNonNbsp(render()); + if (ctx.authoredHashes === before) + return content; + ctx.authoredHashes = before; + return decideAuthoredHashes(content); +} +function renderBlocks2(blocks, ctx) { + if (ctx.blockDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderMarkdown", MAX_RENDER_DEPTH); + ctx.blockDepth++; + try { + return blocks.map((b) => renderBlock2(b, ctx)).join(""); + } finally { + ctx.blockDepth--; + } +} +function withMarker(marker, content) { + if (content !== "") + return `${marker}${content}`; + return marker.replace(/ +$/, ""); +} +function renderBlock2(node, ctx) { + switch (node.type) { + case "heading": { + const text = trimNonNbsp(renderInlines2(node.children, ctx).replace(/[ \t\r]*\n[ \t\r]*/g, " ")); + const id = node.attrs?.id; + const suffix = id && ctx.referencedHeadingIds.has(id) ? ` {#${id}}` : ""; + return `${withMarker(`${"#".repeat(node.level)} `, `${text}${suffix}`)} + +`; + } + case "paragraph": + return `${protectParagraphListMarkers(renderInlines2(node.children, ctx))} + +`; + case "code_block": { + const content = stripControls(node.content); + const fence = safeFence(content, 3); + const effectiveTitle = node.attrs?.keyValues?.["title"] ?? node.header; + const info = markdownFenceInfo(node.lang, effectiveTitle, node.label); + return `${fence}${info} +${content} +${fence} + +`; + } + case "block_quote": { + const lines = containerContent(ctx, () => renderBlocks2(node.children, ctx)).split("\n"); + return `${lines.map((line2) => withMarker("> ", line2)).join("\n")} + +`; + } + case "list": + return renderList2(node, ctx); + case "thematic_break": + return "---\n\n"; + case "table": + return renderTable2(node, ctx); + case "admonition": { + const body = renderBlocks2(node.children, ctx); + const title = node.title !== void 0 ? renderInlines2(unwrapStrong(node.title), ctx) : ""; + const labelLine = node.label ? `**${escapeText(node.label)}** + +` : ""; + if (title !== "") { + return `**${title}** + +${labelLine}${body}`; + } + return `${labelLine}${body}`; + } + case "div": + return node.label ? `**${escapeText(node.label)}** + +${renderBlocks2(node.children, ctx)}` : renderBlocks2(node.children, ctx); + case "line_block": + return renderBlocks2(node.children, ctx); + case "definition_list": + return renderDefinitionList(node.items, ctx, true); + case "figure": + return renderFigure2(node, ctx); + case "figure_group": { + let out = ""; + for (const child of node.children) { + out += child.type === "figure" ? renderPanelFigure(child, ctx) : renderBlock2(child, ctx); + } + if (node.caption !== void 0) { + out += `**${trimNonNbsp(renderInlines2(node.caption, ctx))}** + +`; + } + return out; + } + case "image": + return `${renderImage2(node)} + +`; + case "raw_block": + return node.format === "html" ? `${escapeMdHtml(stripControls(node.content))} + +` : ""; + case "abbreviation_def": + return `${withMarker(`*[${escapeMdHtml(stripControls(node.abbr))}]: `, escapeMdHtml(stripControls(node.expansion)))} + +`; + case "comment": + return ""; + case "link_reference_definition": + return ""; + case "citation_definition": + return ""; + default: { + const t = node; + throw new Error(`renderMarkdown: unknown block ${t.type}`); + } + } +} +function renderList2(node, ctx) { + ctx.listDepth++; + let out = ""; + let counter = node.start ?? 1; + const bullet = node.bulletChar ?? "-"; + const delim = node.delim === ")" ? ")" : "."; + for (const item2 of node.items) { + let prefix; + if (node.ordered) { + prefix = `${counter}${delim} `; + counter++; + } else if (item2.checked !== void 0) { + prefix = `${bullet} ${item2.checked ? "[x]" : "[ ]"} `; + } else { + prefix = `${bullet} `; + } + const content = containerContent(ctx, () => renderListItem2(item2, ctx)); + const lines = content.split("\n"); + out += `${withMarker(prefix, lines.shift() ?? "")} +`; + const continuation = " ".repeat(prefix.length); + for (const line2 of lines) + out += `${line2 === "" ? "" : continuation + line2} +`; + } + ctx.listDepth--; + return out + (ctx.listDepth === 0 ? "\n" : ""); +} +function renderListItem2(item2, ctx) { + return renderBlocks2(item2.children, ctx); +} +function renderDefinitionList(items, ctx, trailingBlank) { + let out = ""; + for (const item2 of items) { + for (const term of item2.terms) + out += `**${renderInlines2(term, ctx)}** +`; + for (const def of item2.definitions) + out += `${withMarker(": ", containerContent(ctx, () => renderBlocks2(def, ctx)))} +`; + } + return trailingBlank ? `${out} +` : out; +} +function renderTable2(node, ctx) { + let header; + let headerColumns = 0; + const rows = []; + const aligns = []; + for (const row of node.rows) { + const cells = row.cells.map((cell) => trimNonNbsp(renderInlines2(cell.children, ctx))); + const rendered = `| ${cells.join(" | ")} |`; + if (row.cells.every((cell) => cell.header)) { + header = rendered; + headerColumns = cells.length; + row.cells.forEach((cell, i) => { + if (aligns[i] === void 0) + aligns[i] = cell.align; + }); + } else { + rows.push(rendered); + if (header === void 0) { + row.cells.forEach((cell, i) => { + if (aligns[i] === void 0) + aligns[i] = cell.align; + }); + } + } + } + const separator = (i) => { + switch (aligns[i]) { + case "left": + return ":---"; + case "center": + return ":---:"; + case "right": + return "---:"; + default: + return "---"; + } + }; + let out = ""; + if (header !== void 0) { + out += `${header} +`; + out += `| ${Array.from({ length: headerColumns }, (_, i) => separator(i)).join(" | ")} | +`; + } + out += `${rows.join("\n")} +`; + if (node.caption && node.caption.length > 0) { + out += ` +${trimNonNbsp(renderInlines2(node.caption, ctx))} +`; + } + return `${out} +`; +} +function renderFigure2(node, ctx) { + const target = node.target.type === "image" ? renderImage2(node.target) : node.target.type === "table" ? trimNonNbsp(renderTable2(node.target, ctx)) : trimNonNbsp(renderBlock2(node.target, ctx)); + const sep = node.target.type === "block_quote" || node.target.type === "table" ? "\n\n" : "\n"; + return `${target}${sep}${renderInlines2(node.caption, ctx)} + +`; +} +function renderPanelFigure(node, ctx) { + const target = node.target.type === "image" ? renderImage2(node.target) : node.target.type === "table" ? trimNonNbsp(renderTable2(node.target, ctx)) : trimNonNbsp(renderBlock2(node.target, ctx)); + return `${target} + +*${trimNonNbsp(renderInlines2(node.caption, ctx))}* + +`; +} +function renderFootnoteDefs(ast, ctx) { + if (!ast.footnoteDefs) + return ""; + let out = ""; + for (const [label, blocks] of Object.entries(ast.footnoteDefs)) { + out += `${withMarker(`[^${escapeMdHtml(stripControls(label))}]: `, containerContent(ctx, () => outsideLink2(() => renderBlocks2(blocks, ctx))))} +`; + } + return out; +} +function renderInlines2(nodes, ctx) { + if (ctx.inlineDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderMarkdown", MAX_RENDER_DEPTH); + ctx.inlineDepth++; + try { + return nodes.map((node) => renderInline2(node, ctx)).join(""); + } finally { + ctx.inlineDepth--; + } +} +function renderInline2(node, ctx) { + node = normalizeLegacyInline(node); + switch (node.type) { + case "text": + return escapeUnresolvedCrossrefs(cleanEscapedText(node)); + case "escaped_text": + if (AUTHORED_INERT.has(node.value)) + return node.value; + if (node.value in AUTHORED_SENTINEL) { + ctx.authoredHashes++; + return AUTHORED_SENTINEL[node.value]; + } + return "\\" + node.value; + case "emphasis": + return `*${renderInlines2(node.children, ctx)}*`; + case "strong": + return `**${renderInlines2(node.children, ctx)}**`; + case "underline": + return `${renderInlines2(node.children, ctx)}`; + case "strike": + return `~~${renderInlines2(node.children, ctx)}~~`; + case "subscript": + return `${renderInlines2(node.children, ctx)}`; + case "superscript": + return `${renderInlines2(node.children, ctx)}`; + case "highlight": + return `${renderInlines2(node.children, ctx)}`; + case "code": + return renderCode(stripControls(node.value)); + case "link": + if (isUnresolvedReference(node)) + return escapeText(referenceSourceText(node.rawRef)); + if (insideLink2) + return renderInlines2(node.children, ctx); + return renderLink(node, ctx); + case "image": + return renderImage2(node); + case "span": { + const authoredAbbr = node.attrs?.keyValues?.abbr; + if (authoredAbbr !== void 0) { + const previous = suppressAutomaticAbbreviation2; + suppressAutomaticAbbreviation2 = true; + try { + const inner = renderInlines2(node.children, ctx); + if (authoredAbbr === "") + return inner; + if (!ctx.abbrBudget.charge(utf8ByteLength(authoredAbbr))) + return inner; + const title = escapeMdHtml(stripControls(authoredAbbr)).replace(/"/g, """); + return `${inner}`; + } finally { + suppressAutomaticAbbreviation2 = previous; + } + } + return renderInlines2(node.children, ctx); + } + case "math": { + const math = escapeMdHtml(stripControls(node.content)); + return node.display ? `$$${math}$$` : `$${math}$`; + } + case "raw_inline": + return node.format === "html" ? escapeMdHtml(stripControls(node.content)) : ""; + case "literal_inline": + return escapeText(node.content); + case "symbol": + return `:${stripControls(node.name)}:`; + case "autolink": { + const label = stripControls(node.text ?? node.href); + if (insideLink2) { + const display = node.href.startsWith("mailto:") ? node.href.slice(7) : label; + return escapeText(stripControls(display)); + } + return `[${label}](${markdownDestination(node.href)})`; + } + case "mention": + return `@${stripControls(node.user)}`; + case "tag": + return escapeText(`#${stripControls(node.name)}`); + case "inline_extension": + return renderInlines2(node.content, ctx); + case "abbreviation": { + const text = escapeMdHtml(stripControls(node.abbr)); + if (suppressAutomaticAbbreviation2) + return text; + if (!ctx.abbrBudget.charge(utf8ByteLength(node.expansion))) + return text; + const title = escapeMdHtml(stripControls(node.expansion)).replace(/"/g, """); + return `${text}`; + } + case "footnote_ref": + case "inline_footnote": { + if (node.inline) { + const inline = node.inline; + return `^[${outsideLink2(() => renderInlines2(inline, ctx))}]`; + } + const id = stripControls(node.id ?? ""); + if (!ctx.definedFootnotes.has(id)) + return `\\[^${escapeMdHtml(id)}\\]`; + return `[^${escapeMdHtml(id)}]`; + } + case "soft_break": + return "\n"; + case "hard_break": + return "\\\n"; + case "insert": + return `${renderInlines2(node.children, ctx)}`; + case "delete": + return `${renderInlines2(node.children, ctx)}`; + case "substitution": + return `${escapeText(node.oldText)}${escapeText(node.newText)}`; + case "critic_comment": + return escapeText(node.text); + case "heading_ref": { + if (!node.href) + return ``; + const rendered = withinLink2(() => renderInlines2(node.resolvedText ?? [], ctx)); + const crossrefText = ctx.abbrBudget.charge(utf8ByteLength(rendered)) ? rendered : escapeText(node.target); + const crossrefId = fragmentId(node.href); + if (insideLink2 || !crossrefId || !ctx.headingIds.has(crossrefId)) + return crossrefText; + return `[${crossrefText}](${markdownFragmentDestination(crossrefId)})`; + } + case "caption_number": + return node.n === void 0 ? "#" : String(node.n); + case "citation_group": + return stripControls(node.raw); + case "comment": + return ""; + case "smart_punctuation": + return stripControls(ctx.smartTypography === "source" ? node.value : node.glyph ?? SMART_PUNCTUATION_GLYPHS[node.kind] ?? node.value); + default: { + const t = node; + throw new Error(`renderMarkdown: unknown inline ${t.type}`); + } + } +} +function withinLink2(fn) { + const previous = insideLink2; + insideLink2 = true; + try { + return fn(); + } finally { + insideLink2 = previous; + } +} +function outsideLink2(fn) { + const previous = insideLink2; + insideLink2 = false; + try { + return fn(); + } finally { + insideLink2 = previous; + } +} +function renderLink(node, ctx) { + const text = withinLink2(() => renderInlines2(node.children, ctx)); + const id = fragmentId(node.href); + if (id && !ctx.headingIds.has(id)) + return text; + const destination = id ? markdownFragmentDestination(id) : markdownDestination(node.href); + return node.title === void 0 ? `[${text}](${destination})` : `[${text}](${destination} "${escapeMdTitle(node.title)}")`; +} +function renderImage2(node) { + if (isUnresolvedReference(node)) + return escapeText(referenceSourceText(node.rawRef)); + const src = markdownDestination(node.src); + const alt = escapeMarkdownLabel(node.alt); + return node.title === void 0 ? `![${alt}](${src})` : `![${alt}](${src} "${escapeMdTitle(node.title)}")`; +} +function markdownFenceInfo(lang, header, label) { + const rawToken = lang === void 0 ? "" : stripControls(lang).split(/[ \t\n\r]/)[0] ?? ""; + const token = rawToken.includes("`") ? "" : rawToken; + const grouping = label === void 0 || label === "" ? "" : ` [${stripControls(label).replace(/[[\]`]/g, "")}]`; + if (header === void 0 || token === "") + return `${token}${grouping}`; + return `${token} "${escapeMdTitle(header)}"${grouping}`; +} +function escapeMarkdownLabel(text) { + return stripControls(text).replace(/[\\[\]]/g, "\\$&"); +} +function escapeMdTitle(title) { + return stripControls(title).replace(/[\\"]/g, "\\$&"); +} +function safeFence(content, min) { + let longest = 0; + for (const match of content.matchAll(/`+/g)) + longest = Math.max(longest, match[0].length); + return "`".repeat(Math.max(min, longest + 1)); +} +function renderCode(content) { + const fence = safeFence(content, 1); + return content.startsWith("`") || content.endsWith("`") ? `${fence} ${content} ${fence}` : `${fence}${content}${fence}`; +} +function markdownFragmentDestination(id) { + if (!/[\s()<>]/.test(id)) + return `#${id}`; + return `<#${id.replace(/[\\<>]/g, (ch) => `\\${ch}`)}>`; +} +function markdownDestination(url) { + const probed = sanitizeMdUrl(stripDestinationControls(url)); + const encoded = (probed === "" ? probed : stripControls(url)).replace(/[ ()<>]/g, (ch) => { + switch (ch) { + case " ": + return "%20"; + case "(": + return "%28"; + case ")": + return "%29"; + case "<": + return "%3C"; + case ">": + return "%3E"; + default: + return ch; + } + }); + return neutralizeCharRefs(encoded); +} +function neutralizeCharRefs(url) { + return url.replace(CHAR_REF_OPENER_RE, "&"); +} +function fragmentId(href) { + return href.startsWith("#") ? href.slice(1) : void 0; +} +function escapeUnresolvedCrossrefs(value) { + const pattern = /<\/#[^> \t\n\r]+>/g; + let out = ""; + let last = 0; + for (const match of value.matchAll(pattern)) { + out += escapeText(value.slice(last, match.index)) + match[0]; + last = match.index + match[0].length; + } + return out + escapeText(value.slice(last)); +} +function escapeText(text) { + text = stripControls(text); + text = text.replace(/[\\`*_[\]#]/g, (ch) => NARROWED_SENTINEL[ch] ?? `\\${ch}`); + return text.replace(/<(?=[A-Za-z/!?])/g, "\\<"); +} +function protectParagraphListMarkers(text) { + let codeFence = 0; + const lines = text.split("\n"); + for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { + let line2 = lines[lineIndex]; + if (codeFence === 0) { + line2 = line2.replace(/^([ \t]{0,3})([-+])(?=[ \t])/, "$1\\$2").replace(/^([ \t]{0,3}\d{1,9})([.)])(?=[ \t])/, "$1\\$2"); + lines[lineIndex] = line2; + } + for (let i = 0; i < line2.length; ) { + if (line2[i] !== "`") { + i++; + continue; + } + let backslashes = 0; + for (let j = i - 1; j >= 0 && line2[j] === "\\"; j--) + backslashes++; + let run = 1; + while (line2[i + run] === "`") + run++; + if (backslashes % 2 === 0) { + if (codeFence === 0) + codeFence = run; + else if (codeFence === run) + codeFence = 0; + } + i += run; + } + } + return lines.join("\n"); +} +function sanitizeMdUrl(url) { + return blankDeniedDestination(url); +} +function stripControls(s) { + return s.replace(/[\u000d\u007f-\u009f\ue004-\ue008]/gu, ""); +} +function stripDestinationControls(s) { + return s.replace(new RegExp("\\p{Cc}|[\\ue004-\\ue008]", "gu"), (c) => c === " " || c === "\n" ? c : ""); +} +function escapeMdHtml(text) { + return text.replace(/&/g, "&").replace(//g, ">"); +} +function cleanEscapedText(node) { + return node.value; +} +function sentinelCharacter(s) { + return NARROWED_CHARACTER[s] ?? AUTHORED_CHARACTER[s]; +} +function adjacentToLiveDelimiter(line2, i, ch) { + if (line2[i + 1] === ch) + return true; + if (line2[i - 1] !== ch) + return false; + let backslashes = 0; + for (let j = i - 2; j >= 0 && line2[j] === "\\"; j--) + backslashes++; + return backslashes % 2 === 0; +} +function resolveNarrowedEscapes(text) { + if (!HAS_NARROWED_SENTINEL.test(text)) + return text; + const character = sentinelCharacter; + const line2 = text.replace(RE_NARROWED_SENTINEL, character); + return text.replace(RE_NARROWED_SENTINEL, (s, offset) => { + const ch = character(s); + const keep = s === AUTHORED_KEPT || (s in AUTHORED_CHARACTER ? opensAnAtxHeading(line2, offset) : adjacentToLiveDelimiter(line2, offset, ch)); + return keep ? `\\${ch}` : ch; + }); +} +function decideAuthoredHashes(text) { + if (!HAS_UNDECIDED_HASH.test(text)) + return text; + const line2 = text.replace(RE_NARROWED_SENTINEL, sentinelCharacter); + return text.replace(RE_UNDECIDED_HASH, (_s, offset) => opensAnAtxHeading(line2, offset) ? AUTHORED_KEPT : "#"); +} +function opensAnAtxHeading(line2, offset) { + let i = offset; + while (i > 0 && line2[i - 1] === " ") { + if (offset - i >= 3) + return false; + i--; + } + if (i > 0 && line2[i - 1] !== "\n") + return false; + let run = 0; + while (run <= 6 && line2[offset + run] === "#") + run++; + if (run > 6) + return false; + const after = line2[offset + run] ?? "\n"; + return after === " " || after === " " || after === "\n"; +} +function normalize(text) { + const collapsed = `${trimNonNbsp(text.replace(/\n{3,}/g, "\n\n"))} +`.replace(/\ue000/g, "\xA0"); + return resolveNarrowedEscapes(collapsed); +} +function walkBlocks(blocks, visit4, depth = 0) { + if (depth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderMarkdown", MAX_RENDER_DEPTH); + for (const block of blocks) { + visit4(block); + switch (block.type) { + case "heading": + case "paragraph": + visit4(block, block.children); + break; + case "block_quote": + case "admonition": + case "div": + case "line_block": + walkBlocks(block.children, visit4, depth + 1); + break; + case "list": + for (const item2 of block.items) + walkBlocks(item2.children, visit4, depth + 1); + break; + case "definition_list": + for (const item2 of block.items) { + for (const term of item2.terms) + visit4(block, term); + for (const def of item2.definitions) + walkBlocks(def, visit4, depth + 1); + } + break; + case "table": + if (block.caption) + visit4(block, block.caption); + for (const row of block.rows) + for (const cell of row.cells) + visit4(block, cell.children); + break; + case "figure": + visit4(block, block.caption); + if (block.target.type === "block_quote") + walkBlocks(block.target.children, visit4, depth + 1); + else if (block.target.type === "table") + walkBlocks([block.target], visit4, depth + 1); + break; + case "figure_group": + if (block.caption) + visit4(block, block.caption); + walkBlocks(block.children, visit4, depth + 1); + break; + default: + break; + } + } +} +function walkInlines(nodes, visit4, depth = 0, insideLink5 = false) { + if (depth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderMarkdown", MAX_RENDER_DEPTH); + for (const node of nodes) { + visit4(node, insideLink5); + switch (node.type) { + case "emphasis": + case "strong": + case "underline": + case "strike": + case "superscript": + case "subscript": + case "highlight": + case "link": + case "span": + case "insert": + case "delete": + walkInlines(node.children, visit4, depth + 1, insideLink5 || node.type === "link"); + break; + case "inline_extension": + walkInlines(node.content, visit4, depth + 1, insideLink5); + break; + case "footnote_ref": + case "inline_footnote": + if (node.inline) + walkInlines(node.inline, visit4, depth + 1, false); + break; + default: + break; + } + } +} +function unwrapStrong(nodes) { + return nodes.flatMap((n) => { + const kids = n.children; + if (n.type === "strong") + return unwrapStrong(kids ?? []); + if (Array.isArray(kids)) + return [{ ...n, children: unwrapStrong(kids) }]; + return [n]; + }); +} +var suppressAutomaticAbbreviation2, insideLink2, CHAR_REF_OPENER_RE, NARROWED_SENTINEL, NARROWED_CHARACTER, AUTHORED_INERT, AUTHORED_SENTINEL, AUTHORED_KEPT, AUTHORED_CHARACTER, RE_NARROWED_SENTINEL, HAS_NARROWED_SENTINEL, RE_UNDECIDED_HASH, HAS_UNDECIDED_HASH; +var init_render_markdown = __esm({ + "node_modules/@markup-carve/carve/dist/render-markdown.js"() { + init_render_depth(); + init_ast(); + init_abbr_budget(); + init_deny_listed_destination(); + init_legacy_nodes(); + init_trim_non_nbsp(); + init_bidi_controls(); + init_unresolved_reference(); + suppressAutomaticAbbreviation2 = false; + insideLink2 = false; + CHAR_REF_OPENER_RE = /&(?=#[0-9]{1,8};|#[xX][0-9a-fA-F]{1,8};|[a-zA-Z][a-zA-Z0-9]{0,31};)/g; + NARROWED_SENTINEL = { + _: "\uE004", + "#": "\uE005", + "[": "\uE006" + }; + NARROWED_CHARACTER = { + "\uE004": "_", + "\uE005": "#", + "\uE006": "[" + }; + AUTHORED_INERT = /* @__PURE__ */ new Set(["{", "}", "^", ",", "%", ":", "/", "@"]); + AUTHORED_SENTINEL = { + "#": "\uE007" + }; + AUTHORED_KEPT = "\uE008"; + AUTHORED_CHARACTER = { + "\uE007": "#", + "\uE008": "#" + }; + RE_NARROWED_SENTINEL = /[\ue004-\ue008]/g; + HAS_NARROWED_SENTINEL = /[\ue004-\ue008]/; + RE_UNDECIDED_HASH = /\ue007/g; + HAS_UNDECIDED_HASH = /\ue007/; + } +}); + +// node_modules/@markup-carve/carve/dist/thematic-break-marker.js +function thematicBreakSpelling(authored, override) { + return override ?? (authored ?? "-").repeat(3); +} +var init_thematic_break_marker = __esm({ + "node_modules/@markup-carve/carve/dist/thematic-break-marker.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/source-unspellable-error.js +var SourceUnspellableError; +var init_source_unspellable_error = __esm({ + "node_modules/@markup-carve/carve/dist/source-unspellable-error.js"() { + SourceUnspellableError = class extends Error { + nodeType; + reason; + constructor(nodeType, reason) { + super(`renderCarve cannot spell ${nodeType}: ${reason}`); + this.nodeType = nodeType; + this.reason = reason; + this.name = "SourceUnspellableError"; + } + }; + } +}); + +// node_modules/@markup-carve/carve/dist/render-carve.js +function isWsNonNbsp(ch) { + return ch === " " || ch === " " || ch === "\n" || ch === "\r"; +} +function trimEndNonNbsp2(text) { + let end = text.length; + while (end > 0 && isWsNonNbsp(text[end - 1])) + end--; + return end === text.length ? text : text.slice(0, end); +} +function trimStartNonNbsp(text) { + let start = 0; + while (start < text.length && isWsNonNbsp(text[start])) + start++; + return start === 0 ? text : text.slice(start); +} +function renderCarve(ast, _opts = {}) { + sentinels = pickSentinels(collectStrings(ast)); + redundantIds = findRedundantHeadingIds(ast); + definitionsByLine = /* @__PURE__ */ new Map(); + for (const child of ast.children) { + if (child.type !== "link_reference_definition") + continue; + const line2 = child.pos?.startLine; + if (line2 !== void 0 && !definitionsByLine.has(line2)) + definitionsByLine.set(line2, child); + } + footnoteDefsByLine = /* @__PURE__ */ new Map(); + documentFootnoteDefs = ast.footnoteDefs; + for (const [label, pos] of Object.entries(ast.footnoteDefPos ?? {})) { + const line2 = pos?.startLine; + if (line2 !== void 0 && !footnoteDefsByLine.has(line2)) + footnoteDefsByLine.set(line2, label); + } + const minimal = withFreshWriteBackState(() => renderWithEscapes(ast, "minimal")); + const conservative = withFreshWriteBackState(() => renderWithEscapes(ast, "conservative")); + if (minimal === conservative) + return minimal; + const minimalTree = treeOf(minimal); + if (minimalTree !== null && minimalTree === stableJson(ast)) + return minimal; + return escapingIsRedundant(minimalTree, conservative) ? minimal : conservative; +} +function treeOf(src) { + try { + return stableJson(parse(src)); + } catch { + return null; + } +} +function findRedundantHeadingIds(ast) { + const out = /* @__PURE__ */ new WeakSet(); + const headings = (root, into) => { + const stack = [root]; + while (stack.length > 0) { + const node = stack.pop(); + if (Array.isArray(node)) { + for (let i = node.length - 1; i >= 0; i -= 1) + stack.push(node[i]); + continue; + } + if (!node || typeof node !== "object") + continue; + const record = node; + if (record["type"] === "heading") + into.push(record); + const values = Object.values(record); + for (let i = values.length - 1; i >= 0; i -= 1) + stack.push(values[i]); + } + }; + const original = []; + headings(ast, original); + if (original.length === 0) + return out; + let copy; + try { + copy = JSON.parse(JSON.stringify(ast)); + } catch { + return out; + } + const copied = []; + headings(copy, copied); + for (const heading of copied) { + const attrs = heading["attrs"]; + if (attrs && attrs.id !== void 0 && !(attrs.order ?? []).includes("#id")) { + delete attrs.id; + } + } + resolveHeadingIds(copy); + for (const [index2, heading] of original.entries()) { + const attrs = heading["attrs"]; + if (!attrs || attrs.id === void 0 || (attrs.order ?? []).includes("#id")) + continue; + const fresh = copied[index2]?.["attrs"]?.id; + if (fresh === attrs.id) + out.add(heading); + } + return out; +} +function renderWithEscapes(ast, mode) { + const canonicalForm = renderOnePass(ast, mode); + if (ast.frontmatter || !opensFrontmatter(canonicalForm)) + return canonicalForm; + const previousMarker = thematicBreakMarker; + thematicBreakMarker = "***"; + try { + const fallback = renderOnePass(ast, mode); + return opensFrontmatter(fallback) ? canonicalForm : fallback; + } finally { + thematicBreakMarker = previousMarker; + } +} +function renderOnePass(ast, mode) { + const previous = escapeMode; + escapeMode = mode; + definitionsWrittenInPlace = /* @__PURE__ */ new WeakSet(); + footnotesWrittenInPlace = /* @__PURE__ */ new Set(); + try { + const ctx = { + blockDepth: 0, + inlineDepth: 0, + listDepth: 0, + lineBlockDepth: 0, + colonFenceDepth: 0, + afterCaptionHost: false, + paragraphStartsAfterCaptionHost: false + }; + const parts = []; + if (ast.frontmatter) + parts.push(renderFrontmatter(ast.frontmatter)); + const body = renderDocumentBody2(ast, ctx); + if (body) + parts.push(body); + return normalize2(parts.join("\n\n")); + } finally { + escapeMode = previous; + } +} +function escapingIsRedundant(minimalTree, conservative) { + if (minimalTree === null) + return false; + const conservativeTree = treeOf(conservative); + return conservativeTree !== null && minimalTree === conservativeTree; +} +function stableJson(value) { + return JSON.stringify(canonical(value)); +} +function canonical(value) { + if (Array.isArray(value)) + return mergeTextRuns(value).map(canonical); + if (value && typeof value === "object") { + const out = {}; + for (const key2 of Object.keys(value).sort()) { + if (key2 === "pos" || key2 === "footnoteDefPos" || key2 === "definitionSpans" || key2 === "termSpans" || key2 === "srcByteLength") + continue; + if (key2 === "escapedLeadingCaret") + continue; + out[key2] = canonical(value[key2]); + } + return out; + } + return value; +} +function mergeTextRuns(nodes) { + const out = []; + for (const node of nodes) { + const current = node; + const isTextish = current !== null && typeof current === "object" && (current["type"] === "text" || current["type"] === "escaped_text"); + const previous = out[out.length - 1]; + if (isTextish && previous !== void 0 && previous["type"] === "text") { + previous["value"] = String(previous["value"] ?? "") + String(current["value"] ?? ""); + continue; + } + if (isTextish) { + out.push({ type: "text", value: String(current["value"] ?? "") }); + continue; + } + out.push(node); + } + return out; +} +function indentLines(text, columns) { + const pad = " ".repeat(columns); + return text.split("\n").map((line2) => line2 === "" ? line2 : pad + line2).join("\n"); +} +function listsWouldMerge(a, b) { + if (a.ordered !== b.ordered) + return false; + if (isTaskList(a) !== isTaskList(b)) + return false; + if (a.ordered) + return (a.delim ?? ".") === (b.delim ?? ".") && a.olType === b.olType; + return (a.bulletChar ?? "-") === (b.bulletChar ?? "-"); +} +function isTaskList(list) { + return list.items.some((item2) => item2.checked !== void 0); +} +function renderBlocks3(blocks, ctx) { + if (ctx.blockDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderCarve", MAX_RENDER_DEPTH); + ctx.blockDepth++; + const previousHost = ctx.afterCaptionHost; + const previousParagraphStart = ctx.paragraphStartsAfterCaptionHost; + ctx.afterCaptionHost = false; + try { + const parts = []; + let previousList = null; + let listOffset = 0; + let previousBlock = null; + for (const block of blocks) { + ctx.paragraphStartsAfterCaptionHost = ctx.afterCaptionHost; + const rendered = renderBlock3(block, ctx); + ctx.afterCaptionHost = hostsCaption(block); + if (block.type === "list") { + listOffset = previousList !== null && listsWouldMerge(previousList, block) ? listOffset + 1 : 0; + previousList = block; + } else if (rendered.length > 0) { + previousList = null; + listOffset = 0; + } + if (rendered.length > 0) { + const text = listOffset > 0 ? indentLines(rendered, listOffset) : rendered; + if (previousBlock !== null && parts.length > 0 && writtenAsOneRun(previousBlock, block)) { + parts[parts.length - 1] += ` +${text}`; + } else { + parts.push(text); + } + previousBlock = block; + } + } + return parts.join("\n\n"); + } finally { + ctx.afterCaptionHost = previousHost; + ctx.paragraphStartsAfterCaptionHost = previousParagraphStart; + ctx.blockDepth--; + } +} +function writtenAsOneRun(previous, block) { + if (previous.type !== "citation_definition" || block.type !== "citation_definition") + return false; + const before = previous.pos; + const after = block.pos; + if (!before || !after) + return false; + return after.startLine === before.endLine + 1; +} +function hostsCaption(block) { + if (block.type === "table" || block.type === "code_block" || block.type === "block_quote" || block.type === "image" || block.type === "figure_group") + return true; + if (block.type !== "paragraph" || block.children.length !== 1) + return false; + const child = block.children[0]; + return child?.type === "image" || child?.type === "math" && child.display; +} +function withoutIdSlot(attrs) { + if (!attrs || attrs.id === void 0) + return attrs; + const next = { ...attrs }; + delete next.id; + if (next.order) + next.order = next.order.filter((slot) => slot !== "#id"); + return next; +} +function withoutKey(attrs, key2) { + if (!attrs?.keyValues || !(key2 in attrs.keyValues)) + return attrs; + const keyValues = { ...attrs.keyValues }; + delete keyValues[key2]; + const next = { ...attrs, keyValues }; + if (next.order) + next.order = next.order.filter((slot) => slot !== key2); + if (next.id === void 0 && (next.classes === void 0 || next.classes.length === 0) && Object.keys(keyValues).length === 0) { + return void 0; + } + return next; +} +function renderBlock3(node, ctx) { + const attrs = renderBlockAttrs(node.attrs); + const withAttrs = (body) => attrs ? `${attrs} +${body}` : body; + switch (node.type) { + case "heading": { + const text = trimNonNbsp2(trimNonNbsp2(renderInlines3(node.children, ctx)).replace(/(\\*)\n[ \t]*/g, (_m, slashes) => (slashes.length % 2 === 1 ? slashes.slice(1) : slashes) + " ")); + const headingBody = `${"#".repeat(node.level)} ${text}`; + if (redundantIds.has(node)) { + const withoutId = renderBlockAttrs(withoutIdSlot(node.attrs)); + return withoutId ? `${withoutId} +${headingBody}` : headingBody; + } + return withAttrs(headingBody); + } + case "paragraph": { + const text = guardThematicBreakLines(renderInlines3(node.children, ctx, attrs === "" && ctx.paragraphStartsAfterCaptionHost, ctx.lineBlockDepth > 0)); + if (ctx.lineBlockDepth > 0) { + return withAttrs(text.replace(/^$(?=\n)/gm, "%%")); + } + return withAttrs(text); + } + case "code_block": { + const fence = safeFence2(node.content, 3); + const info = codeFenceInfo(node.lang, node.header, node.label); + const attrsWithoutTitle = node.header !== void 0 && node.attrs?.keyValues?.["title"] === node.header ? renderBlockAttrs(withoutKey(node.attrs, "title")) : attrs; + const body = `${fence}${info} +${protectVerbatim(node.content)} +${fence}`; + return attrsWithoutTitle ? `${attrsWithoutTitle} +${body}` : body; + } + case "block_quote": { + const inner = renderHostedBlocks(node.children, ctx); + const body = inner.split("\n").map((line2) => line2 === "" ? ">" : `> ${line2}`).join("\n"); + return withAttrs(body); + } + case "list": + return withAttrs(renderList3(node, ctx)); + case "thematic_break": + return withAttrs(thematicBreakSpelling(node.marker, thematicBreakMarker)); + case "table": + return renderTableWithColumns(node, ctx); + case "admonition": { + const title = node.title !== void 0 ? ` "${renderInlines3(node.title, ctx)}"` : ""; + const label = node.label !== void 0 ? ` [${writeFlatBracketRun(node.label)}]` : ""; + const fence = colonFenceFor(ctx); + const body = renderColonFenceBody(node.children, ctx); + return withAttrs(`${fence} ${node.kind}${title}${label} +${body} +${fence}`); + } + case "line_block": { + const fence = colonFenceFor(ctx); + ctx.lineBlockDepth++; + ctx.colonFenceDepth++; + let body; + try { + body = renderBlocks3(node.children, ctx); + } finally { + ctx.colonFenceDepth--; + ctx.lineBlockDepth--; + } + const layout = lineBlockLayoutWhitespace(body); + return withAttrs(fence + " |\n" + layout + (layout.endsWith("\n") ? "" : "\n") + fence); + } + case "div": { + const label = node.label !== void 0 ? ` [${writeFlatBracketRun(node.label)}]` : ""; + const fence = colonFenceFor(ctx); + const body = renderColonFenceBody(node.children, ctx); + return withAttrs(`${fence}${label} +${body} +${fence}`); + } + case "definition_list": + return withAttrs(renderDefinitionList2(node.items, ctx)); + case "figure": + return withAttrs(renderFigure3(node, ctx)); + case "figure_group": { + const fence = colonFenceFor(ctx); + const body = renderColonFenceBody(node.children, ctx); + const caption = node.caption !== void 0 ? ` +^ ${renderInlines3(node.caption, ctx)}` : ""; + return withAttrs(`${fence} figure +${body} +${fence}${caption}`); + } + case "image": + return renderImage3(node); + case "raw_block": { + const fence = safeFence2(node.content, 3); + return withAttrs(`${fence}=${escapeFormat(node.format)} +${protectVerbatim(node.content)} +${fence}`); + } + case "abbreviation_def": + return `*[${escapeAbbr(node.abbr)}]: ${escapePlainLine(node.expansion)}`; + case "link_reference_definition": { + if (definitionsWrittenInPlace.has(node)) + return ""; + const title = node.title === void 0 ? "" : ` "${escapeQuoted(node.title)}"`; + const attrs2 = renderAttrs3(node.attrs); + return `[${node.label}]: ${node.href}${title}${attrs2 === "" ? "" : ` ${attrs2}`}`; + } + case "citation_definition": { + const metadata = renderCitationMetadata(node.attrs); + const entry = renderInlines3(node.children, ctx); + const tail = [metadata, entry].filter((part) => part !== "").join(" "); + return `[@${node.key}]:${tail === "" ? "" : ` ${tail}`}`; + } + case "comment": + return node.block ? renderBlockComment(node.content) : node.delimited ? `{% ${node.content} %}` : `%% ${node.content}`; + default: { + const t = node; + throw new Error(`renderCarve: unknown block ${t.type}`); + } + } +} +function renderTableWithColumns(node, ctx) { + if (!node.columns?.length) { + const attrs2 = renderBlockAttrs(node.attrs); + const body = renderTable3(node, ctx); + return attrs2 ? `${attrs2} +${body}` : body; + } + const keyValues = { ...node.attrs?.keyValues ?? {} }; + const join = (field, key2) => { + if (keyValues[key2] === void 0 && node.columns.some((column) => column[field] !== void 0)) { + keyValues[key2] = node.columns.map((column) => column[field] ?? "").join(","); + } + }; + join("align", "aligns"); + join("valign", "valigns"); + if (keyValues.widths === void 0 && node.columns.some((column) => column.width !== void 0)) { + keyValues.widths = node.columns.map((column) => column.width === void 0 ? "" : String(column.width * 100)).join(","); + } + const attrs = renderBlockAttrs({ ...node.attrs ?? {}, keyValues }); + return `${attrs} +${renderTable3(node, ctx)}`; +} +function renderList3(node, ctx) { + ctx.listDepth++; + try { + let out = ""; + let counter = node.start ?? 1; + const delim = node.delim ?? "."; + const bullet = node.bulletChar ?? "-"; + const bareDot = node.ordered && node.bareMarker === true && delim === "." && node.olType === void 0 && (node.start ?? 1) === 1; + node.items.forEach((item2, idx) => { + const indent2 = ""; + let prefix; + if (node.ordered) { + prefix = bareDot ? `${delim} ` : `${orderedMarker(counter, node.olType)}${delim} `; + counter++; + } else if (item2.checked !== void 0) { + prefix = `${bullet} ${item2.checked ? "[x]" : "[ ]"} `; + } else { + prefix = `${bullet} `; + } + const itemAttrs = renderAttrs3(item2.attrs); + if (itemAttrs) { + prefix = node.ordered ? `${prefix.trimEnd()}${itemAttrs} ` : `${bullet}${itemAttrs}${item2.checked !== void 0 ? ` [${item2.checked ? "x" : " "}] ` : " "}`; + } + let content = trimNonNbsp2(renderListItem3(item2, ctx, node.tight)); + const lines = content ? content.split("\n") : [""]; + const first = lines.shift() ?? ""; + out += `${indent2}${prefix}${first || "+"} +`; + const continuation = " ".repeat(prefix.length); + for (const line2 of lines) { + if (line2.startsWith(MARKER_COLUMN)) { + out += `${indent2}${line2.slice(MARKER_COLUMN.length)} +`; + continue; + } + out += line2 ? `${indent2}${continuation}${line2} +` : "\n"; + } + if (!node.tight && idx < node.items.length - 1) + out += "\n"; + }); + return trimEndNonNbsp2(out); + } finally { + ctx.listDepth--; + } +} +function withFreshWriteBackState(render) { + definitionsWrittenInPlace = /* @__PURE__ */ new WeakSet(); + footnotesWrittenInPlace = /* @__PURE__ */ new Set(); + return render(); +} +function definitionInGap(before, after, ctx) { + const from = before.pos?.endLine; + const to = after.pos?.startLine; + if (from === void 0 || to === void 0) + return void 0; + for (const [line2, node] of definitionsByLine) { + if (line2 > from && line2 < to && !definitionsWrittenInPlace.has(node)) { + const written = renderBlock3(node, ctx); + definitionsWrittenInPlace.add(node); + return written; + } + } + for (const [line2, label] of footnoteDefsByLine) { + if (line2 > from && line2 < to && !footnotesWrittenInPlace.has(label)) { + const blocks = ownValue(documentFootnoteDefs, label); + if (blocks === void 0) + continue; + const written = renderOneFootnoteDef(label, blocks, ctx); + footnotesWrittenInPlace.add(label); + return written; + } + } + return void 0; +} +function opensWithAnAttributeLine(rendered) { + return A_BLOCK_ATTRIBUTES_LINE.test(rendered.split("\n", 1)[0]); +} +function adjacentBlocksMerge(left, right) { + if (left.type !== right.type) + return false; + if (left.type === "list" && right.type === "list") { + if (left.ordered !== right.ordered) + return false; + return left.ordered ? (left.delim ?? ".") === (right.delim ?? ".") && left.olType === right.olType : (left.bulletChar ?? "-") === (right.bulletChar ?? "-"); + } + return (/* @__PURE__ */ new Set([ + "block_quote", + "table", + "line_block", + "definition_list" + ])).has(left.type); +} +function atMarkerColumn(text) { + return text.split("\n").map((line2) => MARKER_COLUMN + line2).join("\n"); +} +function renderListItem3(item2, ctx, tight) { + const outerFenceDepth = ctx.colonFenceDepth; + ctx.colonFenceDepth = 0; + try { + return renderListItemBody(item2, ctx, tight); + } finally { + ctx.colonFenceDepth = outerFenceDepth; + } +} +function renderListItemBody(item2, ctx, tight) { + if (!tight) + return renderBlocks3(item2.children, ctx); + if (ctx.blockDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderCarve", MAX_RENDER_DEPTH); + ctx.blockDepth++; + try { + const parts = []; + let previousAtMarkerColumn = false; + item2.children.forEach((b, i) => { + const previous = item2.children[i - 1]; + const next = item2.children[i + 1]; + let separated = false; + if (previous !== void 0) { + const written = definitionInGap(previous, b, ctx); + if (written !== void 0 && written.length > 0) { + parts.push(written); + separated = true; + } + } + const rendered = renderBlock3(b, ctx); + if (rendered.length === 0) + return; + if (previousAtMarkerColumn || next !== void 0 && adjacentBlocksMerge(b, next) || !separated && previous?.type === "paragraph" && FOLDS_INTO_AN_OPEN_PARAGRAPH.has(b.type) && !opensWithAnAttributeLine(rendered)) { + parts.push(atMarkerColumn("+"), atMarkerColumn(rendered)); + previousAtMarkerColumn = true; + return; + } + parts.push(rendered); + }); + return parts.join("\n"); + } finally { + ctx.blockDepth--; + } +} +function orderedMarker(n, type) { + switch (type) { + case "a": + return alphaMarker(n, false); + case "A": + return alphaMarker(n, true); + case "i": + return romanMarker(n).toLowerCase(); + case "I": + return romanMarker(n); + default: + return String(n); + } +} +function alphaMarker(n, upper) { + const base = String.fromCharCode((n - 1) % 26 + (upper ? 65 : 97)); + return base; +} +function romanMarker(n) { + const values = [ + [1e3, "M"], + [900, "CM"], + [500, "D"], + [400, "CD"], + [100, "C"], + [90, "XC"], + [50, "L"], + [40, "XL"], + [10, "X"], + [9, "IX"], + [5, "V"], + [4, "IV"], + [1, "I"] + ]; + let out = ""; + for (const [value, token] of values) { + while (n >= value) { + out += token; + n -= value; + } + } + return out || "I"; +} +function renderDefinitionList2(items, ctx) { + const out = []; + for (const item2 of items) { + for (const term of item2.terms) + out.push(`:: ${renderInlines3(term, ctx)}`); + item2.definitions.forEach((def, index2) => { + if (def.length === 0) { + const line2 = item2.definitionLines?.[index2]; + const definition = line2 === void 0 ? void 0 : definitionsByLine.get(line2); + if (definition !== void 0) { + const written = renderBlock3(definition, ctx); + definitionsWrittenInPlace.add(definition); + out.push(`: ${written}`); + return; + } + const label = line2 === void 0 ? void 0 : footnoteDefsByLine.get(line2); + const blocks = label === void 0 ? void 0 : ownValue(documentFootnoteDefs, label); + if (label !== void 0 && blocks !== void 0) { + const written = renderOneFootnoteDef(label, blocks, ctx); + footnotesWrittenInPlace.add(label); + const [first, ...rest] = written.split("\n"); + out.push(`: ${first}`); + for (const l of rest) + out.push(` ${l}`); + return; + } + } + const lines = trimNonNbsp2(renderHostedBlocks(def, ctx)).split("\n"); + out.push(`: ${lines.shift() ?? ""}`); + for (const line2 of lines) + out.push(` ${line2}`); + }); + } + return out.join("\n"); +} +function colonFenceFor(ctx) { + return ":".repeat(3 + ctx.colonFenceDepth); +} +function renderColonFenceBody(children, ctx) { + ctx.colonFenceDepth++; + try { + return renderBlocks3(children, ctx); + } finally { + ctx.colonFenceDepth--; + } +} +function renderHostedBlocks(children, ctx) { + const outer = ctx.colonFenceDepth; + ctx.colonFenceDepth = 0; + try { + return renderBlocks3(children, ctx); + } finally { + ctx.colonFenceDepth = outer; + } +} +function renderTable3(node, ctx) { + const rows = []; + const first = node.rows[0]; + const headerRow = first !== void 0 && first.cells.length > 0 && first.cells.every((c) => c.header); + const needsDelimiter = headerRow && first.cells.some((c) => c.span !== void 0); + node.rows.forEach((row, rowIndex) => { + const cells = []; + for (const cell of row.cells) { + const asHeader = !(needsDelimiter && rowIndex === 0); + cells.push(renderTableCell(cell, ctx, asHeader)); + } + rows.push(renderTableRow(cells, renderAttrs3(row.attrs))); + }); + if (needsDelimiter) { + rows.splice(1, 0, `|${Array.from({ length: first.cells.length }, () => "---").join("|")}|`); + } + if (node.caption) + rows.push(`^ ${renderInlines3(node.caption, ctx)}`); + return rows.join("\n"); +} +function padCell(prefix, content) { + return content === "" ? `${prefix} ` : `${prefix} ${content} `; +} +function renderTableRow(cells, attrs) { + return `|${cells.join("|")}|${attrs}`; +} +function renderTableCell(cell, ctx, markHeader = true) { + const attrs = renderAttrs3(cell.attrs); + const spanMarker = cell.span === "rowspan" ? "^" : "<"; + if (cell.span === "rowspan" || cell.span === "colspan") { + return padCell(attrs, spanMarker); + } + const align = alignMarker(cell.align); + const valign = cell.valign === "top" ? "^" : cell.valign === "middle" ? "~" : cell.valign === "bottom" ? "v" : ""; + const prefix = `${cell.header && markHeader ? "=" : ""}${align}${valign}${attrs}`; + return padCell(prefix, renderInlines3(cell.children, ctx)); +} +function renderFigure3(node, ctx) { + const target = node.target.type === "image" ? renderImage3(node.target) : node.target.type === "table" ? renderTable3(node.target, ctx) : renderBlock3(node.target, ctx); + return `${target} +^ ${renderInlines3(node.caption, ctx)}`; +} +function renderOneFootnoteDef(label, blocks, ctx) { + const rawBody = renderBlocks3(blocks, ctx); + const body = trimNonNbsp2(blocks.length === 1 ? rawBody.replace(/\n\n/g, "\n") : rawBody); + if (body === "") { + return `[^${writeFlatBracketRun(label)}]: ${EMPTY_FOOTNOTE_BODY}`; + } + const lines = body.split("\n"); + const defLines = [`[^${writeFlatBracketRun(label)}]: ${lines.shift() ?? ""}`]; + for (const line2 of lines) + defLines.push(` ${line2}`); + return defLines.join("\n"); +} +function renderDocumentBody2(ast, ctx) { + const body = []; + const hoisted = []; + for (const child of ast.children) { + if (HOISTED_DEFINITION_TYPES.has(child.type)) { + hoisted.push(child); + continue; + } + body.push(child); + } + const bodyText = renderBlocks3(body, ctx); + const definitions = hoisted.map((child) => ({ + at: child.pos?.startOffset, + text: renderBlockAtTop(child, ctx) + })); + for (const [label, blocks] of Object.entries(ast.footnoteDefs ?? {})) { + if (footnotesWrittenInPlace.has(label)) + continue; + definitions.push({ + at: ownValue(ast.footnoteDefPos, label)?.startOffset, + text: renderOneFootnoteDef(label, blocks, ctx) + }); + } + const ordered = definitions.every((piece) => piece.at !== void 0) ? definitions.map((piece, index2) => ({ piece, index: index2 })).sort((a, b) => a.piece.at - b.piece.at || a.index - b.index).map(({ piece }) => piece) : definitions; + return [bodyText, ...ordered.map((piece) => piece.text)].filter((text) => text.length > 0).join("\n\n"); +} +function renderBlockAtTop(block, ctx) { + if (ctx.blockDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderCarve", MAX_RENDER_DEPTH); + ctx.blockDepth++; + try { + return renderBlock3(block, ctx); + } finally { + ctx.blockDepth--; + } +} +function renderInlines3(nodes, ctx, captionCanOpen = false, isStanza = false) { + if (ctx.inlineDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderCarve", MAX_RENDER_DEPTH); + ctx.inlineDepth++; + try { + let out = ""; + let firstLine = true; + let lineNodeCount = 0; + let lineHostsCaption = false; + let lineLength = 0; + let lineTail = ""; + nodes.forEach((node, idx) => { + let piece = renderInline3(node, ctx, lastBoundary(nodes[idx - 1]), firstBoundary(nodes[idx + 1]), captionCanOpen, opensBacktickRun(nodes[idx + 1])); + const atLineStart = lineLength === 0; + if (node.type === "comment" && atLineStart && piece.startsWith(" %%")) + piece = piece.slice(1); + if (ctx.lineBlockDepth > 0 && node.type === "hard_break" && piece === "\n" && nodes[idx - 1]?.type !== "comment" && (atLineStart || /(?:^|[^ \t]) $/.test(lineTail) || isStanza && idx === nodes.length - 1)) { + piece = "\\\n"; + } + out += piece; + const lastNewline = piece.lastIndexOf("\n"); + if (lastNewline === -1) { + lineLength += piece.length; + lineTail = (lineTail + piece).slice(-2); + } else { + lineLength = piece.length - lastNewline - 1; + lineTail = piece.slice(lastNewline + 1).slice(-2); + } + if (node.type === "soft_break") { + captionCanOpen = firstLine && lineNodeCount === 1 && lineHostsCaption; + firstLine = false; + lineNodeCount = 0; + lineHostsCaption = false; + return; + } + lineNodeCount++; + lineHostsCaption = lineNodeCount === 1 && inlineHostsCaption(node); + captionCanOpen = false; + }); + return out; + } finally { + ctx.inlineDepth--; + } +} +function inlineHostsCaption(node) { + return node.type === "image" && node.src !== "" || node.type === "math" && node.display; +} +function renderInline3(node, ctx, prevChar = "", nextChar = "", captionCanOpen = false, nextOpensBacktickRun = false) { + node = normalizeLegacyInline(node); + const withAttrs = (body) => `${body}${renderAttrs3(node.attrs)}`; + switch (node.type) { + case "text": + return escapeText2(cleanEscapedText2(node), captionCanOpen, nextOpensBacktickRun); + case "escaped_text": + return "\\" + node.value; + case "emphasis": + return withAttrs(renderEmphasis("/", renderInlines3(node.children, ctx), prevChar, nextChar)); + case "strong": { + const inner = node.children[0]; + if (node.boldItalic === true && node.children.length === 1 && inner?.type === "emphasis") { + const content = renderInlines3(inner.children, ctx); + return withAttrs(`/*${content}*/`); + } + return withAttrs(renderEmphasis("*", renderInlines3(node.children, ctx), prevChar, nextChar)); + } + case "underline": + return withAttrs(renderEmphasis("_", renderInlines3(node.children, ctx), prevChar, nextChar)); + case "strike": + return withAttrs(renderEmphasis("~", renderInlines3(node.children, ctx), prevChar, nextChar)); + case "superscript": + return withAttrs(renderForcedEmphasis("^", renderInlines3(node.children, ctx))); + case "subscript": + return withAttrs(renderForcedEmphasis(",", renderInlines3(node.children, ctx))); + case "highlight": + return withAttrs(renderEmphasis("=", renderInlines3(node.children, ctx), prevChar, nextChar)); + case "code": + return withAttrs(renderCode2(node.value)); + case "link": + return renderLink2(node, ctx); + case "image": + return renderImage3(node); + case "span": + return `[${renderInlines3(node.children, ctx)}]${renderAttrs3(node.attrs) || "{}"}`; + case "math": + return withAttrs(renderMath(node.display, node.content)); + case "raw_inline": + if (node.content === "") { + throw new SourceUnspellableError("raw_inline", "an empty raw inline has no Carve source spelling"); + } + return `${renderCode2(node.content)}{=${escapeFormat(node.format)}}`; + case "literal_inline": + return `!${renderCode2(node.content)}${renderAttrs3(node.attrs)}`; + case "symbol": + return withAttrs(`:${escapeSymbolName(node.name)}:`); + case "autolink": + return withAttrs(`<${escapeAutolinkHref(node.text ?? (node.href.startsWith("mailto:") ? node.href.slice(7) : node.href))}>`); + case "mention": + return `@${escapeName(node.user)}`; + case "tag": + return `#${escapeName(node.name)}`; + case "inline_extension": + return withAttrs(`:${escapeIdentifier(node.name)}[${renderInlines3(node.content, ctx)}]`); + case "abbreviation": + return escapeText2(node.abbr); + case "footnote_ref": + case "inline_footnote": + return withAttrs(node.inline ? `^[${renderInlines3(node.inline, ctx)}]` : `[^${writeFlatBracketRun(node.id ?? "")}]`); + case "soft_break": + return "\n"; + case "hard_break": + return ctx.lineBlockDepth > 0 ? "\n" : "\\\n"; + case "insert": + return `{+${renderInlines3(node.children, ctx)}+}${renderAttrs3(node.attrs)}`; + case "delete": + return `{-${renderInlines3(node.children, ctx)}-}${renderAttrs3(node.attrs)}`; + case "substitution": + return `{~${escapeCriticText(node.oldText)}~>${escapeCriticText(node.newText)}~}`; + case "critic_comment": + return `{#${escapeCriticText(node.text)}#}`; + case "heading_ref": + return ``; + case "caption_number": + return "#"; + case "citation_group": + return node.raw; + case "comment": + if (node.delimited) + return `{% ${node.content} %}`; + return node.content.startsWith("%") ? ` %%${node.content}` : ` %% ${node.content}`; + case "smart_punctuation": + return node.value; + default: { + const t = node; + throw new Error(`renderCarve: unknown inline ${t.type}`); + } + } +} +function renderLink2(node, ctx) { + if (node.ref !== void 0 && node.rawRef !== void 0 && !node.href) { + return node.rawRef; + } + if (node.ref !== void 0 && node.rawRef !== void 0) { + return node.rawRef; + } + const text = renderInlines3(node.children, ctx); + const title = node.title === void 0 ? "" : ` "${escapeQuoted(node.title)}"`; + return `[${text}](${escapeDestination(node.href)}${title})${renderAttrs3(node.attrs)}`; +} +function renderImage3(node) { + if (node.ref !== void 0 && node.rawRef !== void 0 && !node.src) { + return node.rawRef; + } + if (node.ref !== void 0 && node.rawRef !== void 0) { + return node.rawRef; + } + const title = node.title === void 0 ? "" : ` "${escapeQuoted(node.title)}"`; + return `![${escapeImageAlt(node.alt)}](${escapeDestination(node.src)}${title})${renderAttrs3(node.attrs)}`; +} +function renderFrontmatter(frontmatter) { + return `---${escapeFormat(frontmatter.format)} +${protectVerbatim(frontmatter.content)} +---`; +} +function renderBlockComment(content) { + let longest = 0; + for (const match of content.matchAll(/%+/g)) + longest = Math.max(longest, match[0].length); + const fence = "%".repeat(Math.max(3, longest + 1)); + return `${fence} +${protectVerbatim(content)} +${fence}`; +} +function renderMath(display, content) { + const code = renderCode2(content); + return `${display ? "$$" : "$"}${code}`; +} +function renderForcedEmphasis(delim, content) { + return `{${delim}${content}${delim}}`; +} +function renderEmphasis(delim, content, prevChar, nextChar, closeDelim = delim) { + const needsForced = /[A-Za-z0-9_]/.test(prevChar) || /[A-Za-z0-9_]/.test(nextChar) || content.startsWith(delim) || content.endsWith(closeDelim) || content.startsWith(" ") || content.endsWith(" ") || content === ""; + return needsForced ? `{${delim}${content}${closeDelim}}` : `${delim}${content}${closeDelim}`; +} +function renderCode2(content) { + content = content.replace(/\ue000/g, sentinels[3]); + const fence = safeFence2(content, 1); + const needsPad = content.startsWith("`") || content.endsWith("`") || content.startsWith(" ") && content.endsWith(" ") && !isCarveBlank(content); + return needsPad ? `${fence} ${content} ${fence}` : `${fence}${content}${fence}`; +} +function codeFenceInfo(lang, header, label) { + const parts = []; + if (lang) + parts.push(escapeFenceToken(lang)); + if (header !== void 0) + parts.push(`"${header}"`); + if (label !== void 0) + parts.push(`[${writeFlatBracketRun(label)}]`); + return parts.join(" "); +} +function safeFence2(content, min) { + let longest = 0; + for (const match of content.matchAll(/`+/g)) + longest = Math.max(longest, match[0].length); + return "`".repeat(Math.max(min, longest + 1)); +} +function renderBlockAttrs(attrs) { + const rendered = renderAttrs3(attrs); + return rendered; +} +function renderAttrs3(attrs) { + if (!attrs) + return ""; + const parts = []; + const kv = attrs.keyValues ?? {}; + const idAsKey = attrs.id !== void 0 && !isAttrIdentifier(attrs.id); + const emitId = () => { + if (attrs.id === void 0) + return; + if (idAsKey) + parts.push(`id=${quoteAttrValue(attrs.id)}`); + else + parts.push(`#${escapeAttrNameValue(attrs.id)}`); + }; + const emitClasses = () => { + for (const cls of attrs.classes ?? []) + parts.push(`.${escapeAttrNameValue(cls)}`); + }; + const emitKey = (key2) => { + if (kv[key2] === void 0) + return; + const value = kv[key2]; + if (key2 === "lang" && isLanguageTag(value)) + parts.push(`:${value}`); + else if (value === "" && isAttrIdentifier(key2)) + parts.push(escapeAttrKey(key2)); + else + parts.push(`${escapeAttrKey(key2)}=${quoteAttrValue(value)}`); + }; + if (attrs.order) { + const seen = /* @__PURE__ */ new Set(); + for (const slot of attrs.order) { + if (slot === "#id") + emitId(); + else if (slot === ".class") + emitClasses(); + else if (!seen.has(slot)) { + emitKey(slot); + seen.add(slot); + } + } + for (const key2 of Object.keys(kv)) { + if (!seen.has(key2)) + emitKey(key2); + } + } else { + emitId(); + emitClasses(); + for (const key2 of Object.keys(kv)) + emitKey(key2); + } + return parts.length ? `{${parts.join(" ")}}` : ""; +} +function isLanguageTag(value) { + return value === "" || /^[A-Za-z0-9]{1,8}(?:-[A-Za-z0-9]{1,8})*$/.test(value); +} +function quoteAttrValue(value) { + if (/^[^ \t\n\r"'{}]+$/.test(value)) + return value; + return `"${value.replace(/[\\"]/g, "\\$&")}"`; +} +function renderCitationMetadata(attrs) { + const keyValues = attrs?.keyValues; + if (!keyValues) + return ""; + const parts = Object.entries(keyValues).map(([key2, value]) => `${escapeAttrKey(key2)}="${value.replace(/[\\"]/g, "\\$&")}"`); + return parts.length === 0 ? "" : `{${parts.join(" ")}}`; +} +function alignMarker(align) { + switch (align) { + case "left": + return "<"; + case "right": + return ">"; + case "center": + return "~"; + default: + return ""; + } +} +function isCarveBlank(text) { + return /^[ \t\n\r]*$/.test(text); +} +function lineBlockLayoutWhitespace(body) { + return body.replace(/(?:^\ue000+)|\ue000{2,}/gm, (run) => sentinels[0].repeat(run.length)); +} +function guardLeadingBom(text) { + return text.startsWith("\uFEFF") ? ` ${text}` : text; +} +function dropTrailingWs(line2) { + const run = /[ \t]+$/.exec(line2); + return run === null ? line2 : line2.slice(0, run.index); +} +function normalize2(text) { + const lines = trimNonNbspKeepingGuard(text.replace(/\ue000(?=[ \t]*(?:\n|$))/g, "\xA0").replace(/\ue000/g, "\\ ")).split("\n"); + const swept = lines.map((line2) => { + if (line2.length > 0 && RE_WRITER_BLANK.test(line2)) + return ""; + return dropTrailingWs(line2); + }); + const cleaned = trimNonNbspKeepingGuard(swept.join("\n").replace(/\n{3,}/g, "\n\n")); + return `${guardLeadingBom(restoreVerbatim(cleaned))} +`; +} +function collectStrings(root) { + const parts = []; + const stack = [root]; + while (stack.length > 0) { + const node = stack.pop(); + if (typeof node === "string") { + parts.push(node); + continue; + } + if (node === null || typeof node !== "object") + continue; + if (Array.isArray(node)) { + for (const item2 of node) + stack.push(item2); + continue; + } + for (const value of Object.values(node)) + stack.push(value); + } + return parts.join("\0"); +} +function pickSentinels(text) { + if (!DEFAULT_SENTINELS.some((c) => text.includes(c))) { + return ["\uE001", "\uE002", "\uE003", "\uE004"]; + } + for (let base = 57349; base <= 63740; base += 4) { + const quad = [ + String.fromCharCode(base), + String.fromCharCode(base + 1), + String.fromCharCode(base + 2), + String.fromCharCode(base + 3) + ]; + if (!quad.some((c) => text.includes(c))) + return quad; + } + return ["\uE001", "\uE002", "\uE003", "\uE004"]; +} +function protectVerbatim(content) { + const [sp, tab, blank, nbsp] = sentinels; + return content.replace(/\ue000/g, nbsp).replace(/[ \t]+(?=\n|$)/g, (run) => run.replace(/ /g, sp).replace(/\t/g, tab)).split("\n").map((line2) => line2 === "" ? blank : line2).join("\n"); +} +function restoreVerbatim(text) { + return text.replace(new RegExp(`^[ \\t]+${sentinels[2]}$`, "gm"), "").replace(new RegExp(sentinels[0], "g"), " ").replace(new RegExp(sentinels[1], "g"), " ").replace(new RegExp(sentinels[2], "g"), "").replace(new RegExp(sentinels[3], "g"), "\uE000"); +} +function trimNonNbsp2(text) { + return trimEndNonNbsp2(trimStartNonNbsp(text)); +} +function trimNonNbspKeepingGuard(text) { + if (/^[ \t]+-{3,}[ \t]*(\n|$)/.test(text)) { + return trimEndNonNbsp2(text); + } + return trimNonNbsp2(text); +} +function cleanEscapedText2(node) { + return node.value; +} +function guardThematicBreakLines(body) { + if (!body.includes("-")) + return body; + return body.split("\n").map((line2) => /^-{3,}[ \t]*$/.test(line2) ? ` ${line2}` : line2).join("\n"); +} +function escapeText2(text, captionCanOpen = false, bangOpensLiteral = false) { + const escapes = escapeMode === "minimal" ? UNCONDITIONAL_ESCAPES : CANDIDATE_ESCAPES; + let out = text.replace(UNWRITABLE_CONTROLS, "").replace(escapes, (char, offset) => { + if (char !== "^") + return `\\${char}`; + const next = text[offset + 1] ?? ""; + const opensCaption = captionCanOpen && offset === 0 && next === " "; + const opensInline = next === "[" || (text[offset - 1] ?? "") === "{" || next === "}"; + return opensCaption || opensInline ? "\\^" : "^"; + }); + if (escapeMode === "minimal" && captionCanOpen && out.startsWith("^") && out[1] === " ") { + out = "\\" + out; + } + if (escapeMode === "minimal" && bangOpensLiteral && out.endsWith("!")) { + out = out.slice(0, -1) + "\\!"; + } + if (escapeMode === "minimal") + return out; + return out.replace(LINE_INITIAL_COLON, (_m, lead, colons) => `${lead}\\${colons}`); +} +function escapePlainLine(text) { + return text.replace(/\n/g, " "); +} +function escapeImageAlt(text) { + return rawBracketRunCloses(text) ? text : text.replace(/[\\[\]]/g, "\\$&"); +} +function escapeDestinationEscapes(text) { + const openers = []; + const unbalanced = /* @__PURE__ */ new Set(); + for (let i = 0; i < text.length; i++) { + if (text[i] === "(") + openers.push(i); + else if (text[i] === ")") { + if (openers.length > 0) + openers.pop(); + else + unbalanced.add(i); + } + } + for (const i of openers) + unbalanced.add(i); + let out = ""; + for (let i = 0; i < text.length; i++) { + const ch = text[i]; + const escapable = ch === "\\" && (text[i + 1] === "(" || text[i + 1] === ")" || text[i + 1] === "\\"); + out += unbalanced.has(i) || escapable ? `\\${ch}` : ch; + } + return out; +} +function escapeDestination(text) { + const scheme = /^[\u0000-\u0020\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]*([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(text)?.[1]?.toLowerCase(); + const sanitizeBlank = scheme !== void 0 && ["javascript", "vbscript", "data", "file"].includes(scheme); + const escaped = escapeDestinationEscapes(text); + return escaped.replace(new RegExp("\\p{White_Space}", "gu"), (ch) => ch === " " ? "%20" : `%${ch.charCodeAt(0).toString(16).padStart(2, "0").toUpperCase()}`).replace(/\\?[()]/g, (m) => sanitizeBlank ? m.endsWith("(") ? "%28" : "%29" : m); +} +function escapeQuoted(text) { + return text.replace(/[\\"]/g, "\\$&"); +} +function writeFlatBracketRun(text) { + return text; +} +function escapeAbbr(text) { + return text.replace(/[\\\]]/g, "\\$&"); +} +function escapeIdentifier(text) { + return text.replace(/[^\w-]/g, ""); +} +function escapeSymbolName(text) { + return text.replace(/[^\w+-]/g, ""); +} +function escapeName(text) { + return text.replace(/[^\w.-]/g, "").replace(/^\.+|\.+$/g, ""); +} +function escapeFormat(text) { + const safe = text.replace(/[^\w-]/g, ""); + return safe || "text"; +} +function escapeFenceToken(text) { + return text.split(/[ \t\n\r]/)[0].replace(/`/g, ""); +} +function escapeAttrKey(text) { + const safe = text.replace(/^[^a-zA-Z_]+|[^\w-]/g, ""); + return safe || "x"; +} +function escapeAttrNameValue(text) { + return text.replace(/[^\w-]/g, "-"); +} +function isAttrIdentifier(text) { + return /^[A-Za-z_][\w-]*$/.test(text); +} +function escapeAutolinkHref(text) { + return text.replace(/[\\<>]/g, "\\$&"); +} +function escapeCrossrefTarget(text) { + return text.replace(/[\\>]/g, "\\$&"); +} +function escapeCriticText(text) { + return text.replace(/[\\{}]/g, "\\$&"); +} +function opensBacktickRun(node) { + if (node?.type === "code") + return node.value !== ""; + if (node?.type === "raw_inline") + return node.content !== ""; + return false; +} +function firstBoundary(node) { + if (!node) + return ""; + switch (node.type) { + case "text": + return node.value[0] ?? ""; + // The CHARACTER, not the backslash that precedes it in the output. A text + // node holding `_b_` and an escaped-text node holding `_` describe the same + // neighbour, and the writer has to brace an adjacent delimiter the same way + // for both - otherwise the first pass (text) and the second (escaped text) + // disagree and `fmt(fmt(x)) != fmt(x)`. + case "escaped_text": + return node.value; + case "soft_break": + case "hard_break": + return "\n"; + case "code": + return node.value[0] ?? ""; + case "mention": + return "@"; + case "tag": + return "#"; + default: + return ""; + } +} +function lastBoundary(node) { + if (!node) + return ""; + switch (node.type) { + case "text": + return node.value[node.value.length - 1] ?? ""; + case "escaped_text": + return node.value; + case "soft_break": + case "hard_break": + return "\n"; + case "code": + return node.value[node.value.length - 1] ?? ""; + case "mention": + return node.user[node.user.length - 1] ?? ""; + case "tag": + return node.name[node.name.length - 1] ?? ""; + default: + return ""; + } +} +var thematicBreakMarker, FOLDS_INTO_AN_OPEN_PARAGRAPH, A_BLOCK_ATTRIBUTES_LINE, MARKER_COLUMN, EMPTY_FOOTNOTE_BODY, HOISTED_DEFINITION_TYPES, RE_WRITER_BLANK, DEFAULT_SENTINELS, sentinels, UNCONDITIONAL_ESCAPES, CANDIDATE_ESCAPES, LINE_INITIAL_COLON, escapeMode, redundantIds, definitionsByLine, definitionsWrittenInPlace, footnoteDefsByLine, footnotesWrittenInPlace, documentFootnoteDefs, UNWRITABLE_CONTROLS; +var init_render_carve = __esm({ + "node_modules/@markup-carve/carve/dist/render-carve.js"() { + init_parse(); + init_render_depth(); + init_legacy_nodes(); + init_heading_ids(); + init_own_property(); + init_thematic_break_marker(); + init_source_unspellable_error(); + thematicBreakMarker = null; + FOLDS_INTO_AN_OPEN_PARAGRAPH = /* @__PURE__ */ new Set(["paragraph", "image", "figure"]); + A_BLOCK_ATTRIBUTES_LINE = /^\{.*\}$/; + MARKER_COLUMN = "\uE005"; + EMPTY_FOOTNOTE_BODY = "{empty}"; + HOISTED_DEFINITION_TYPES = /* @__PURE__ */ new Set(["link_reference_definition"]); + RE_WRITER_BLANK = /^[ \t]*$/; + DEFAULT_SENTINELS = ["\uE001", "\uE002", "\uE003", "\uE004"]; + sentinels = [ + "\uE001", + "\uE002", + "\uE003", + "\uE004" + ]; + UNCONDITIONAL_ESCAPES = /[\\`"']/g; + CANDIDATE_ESCAPES = /[\\`*_{}\[\]()#+\-.!~^/<>@%|=;"']/g; + LINE_INITIAL_COLON = /(^|\\n)(:+)/g; + escapeMode = "conservative"; + redundantIds = /* @__PURE__ */ new WeakSet(); + definitionsByLine = /* @__PURE__ */ new Map(); + definitionsWrittenInPlace = /* @__PURE__ */ new WeakSet(); + footnoteDefsByLine = /* @__PURE__ */ new Map(); + footnotesWrittenInPlace = /* @__PURE__ */ new Set(); + UNWRITABLE_CONTROLS = /[\u0000\u000d]/g; + } +}); + +// node_modules/@markup-carve/carve/dist/abbr-expansion-emitted.js +function abbreviationPairKey(abbr, expansion) { + return `${abbr}\0${expansion}`; +} +function documentHasAbbreviationDef(ast) { + const stack = [ast.children]; + for (const blocks of Object.values(ast.footnoteDefs ?? {})) { + stack.push(blocks); + } + while (stack.length > 0) { + const node = stack.pop(); + if (node === null || typeof node !== "object") + continue; + if (Array.isArray(node)) { + for (const child of node) + stack.push(child); + continue; + } + const record = node; + if (record.type === "abbreviation_def") + return true; + for (const [key2, value] of Object.entries(record)) { + if (key2 === "type" || key2 === "attrs" || key2 === "pos") + continue; + stack.push(value); + } + } + return false; +} +var init_abbr_expansion_emitted = __esm({ + "node_modules/@markup-carve/carve/dist/abbr-expansion-emitted.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/render-plain.js +function smartTypographyIsSource(value) { + return value === "source" || value === false; +} +function renderPlainText(ast, opts = {}) { + if (!documentHasAbbreviationDef(ast)) + return renderPass(ast, opts, NO_EXPANDED_DEFINITIONS).text; + const probe = renderPass(ast, opts, NO_EXPANDED_DEFINITIONS); + return renderPass(ast, opts, probe.expanded).text; +} +function renderPass(ast, opts, expandedDefinitions) { + const ctx = { + smartSource: smartTypographyIsSource(opts.smartTypography), + listDepth: 0, + blockDepth: 0, + inlineDepth: 0, + // This target expands a crossref label exactly as the other three do, so it + // needs the same bound. It shares that bound with the abbreviation, which + // expands here as of PART 11 §10f; before that clause an abbreviation + // rendered as its bare key and the crossref was the only expansion, which + // is why there was no budget until the crossref needed one + // (markup-carve/carve-js#892). + abbrBudget: budgetForDocument(ast), + definedFootnotes: new Set(Object.keys(ast.footnoteDefs ?? {})), + expandedDefinitions, + expanded: /* @__PURE__ */ new Set() + }; + const out = renderBlocks4(ast.children, ctx); + const footnotes = renderFootnoteDefs2(ast, ctx); + return { text: stripBidiControls(normalize3(`${out}${footnotes}`)), expanded: ctx.expanded }; +} +function renderBlocks4(blocks, ctx) { + if (ctx.blockDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderPlainText", MAX_RENDER_DEPTH); + ctx.blockDepth++; + try { + return blocks.map((b) => renderBlock4(b, ctx)).join(""); + } finally { + ctx.blockDepth--; + } +} +function renderBlock4(node, ctx) { + switch (node.type) { + case "heading": + return `${renderInlines4(node.children, ctx)} + +`; + case "paragraph": + return `${renderInlines4(node.children, ctx)} + +`; + case "code_block": { + const header = node.header ? `${stripControls2(node.header)} + +` : ""; + const label = node.label ? `${stripControls2(node.label)} + +` : ""; + return `${header}${label}${stripControls2(node.content)} + +`; + } + case "block_quote": + return `"${trimNonNbsp(renderBlocks4(node.children, ctx))}" + +`; + case "list": + return renderList4(node, ctx); + case "thematic_break": + return "---\n\n"; + case "table": + return renderTable4(node, ctx); + case "admonition": { + const body = renderBlocks4(node.children, ctx); + const title = node.title !== void 0 ? renderInlines4(node.title, ctx) : ""; + const labelLine = node.label ? `${stripControls2(node.label)} + +` : ""; + if (title !== "") { + return `${title} + +${labelLine}${body}`; + } + return `${labelLine}${body}`; + } + case "div": + return node.label ? `${stripControls2(node.label)} + +${renderBlocks4(node.children, ctx)}` : renderBlocks4(node.children, ctx); + case "line_block": + return renderBlocks4(node.children, ctx); + case "definition_list": + return renderDefinitionList3(node.items, ctx, true); + case "figure": + return renderFigure4(node, ctx); + case "figure_group": { + let out = ""; + if (node.caption !== void 0) { + out += `${trimNonNbsp(renderInlines4(node.caption, ctx))} + +`; + } + for (const child of node.children) { + out += child.type === "figure" ? renderPanelFigure2(child, ctx) : renderBlock4(child, ctx); + } + return out; + } + case "image": + return `${renderImageText(node)} + +`; + case "abbreviation_def": + if (ctx.expandedDefinitions.has(abbreviationPairKey(node.abbr, node.expansion))) + return ""; + return `*[${stripControls2(node.abbr)}]: ${stripControls2(node.expansion)} + +`; + case "raw_block": + case "comment": + return ""; + case "link_reference_definition": + case "citation_definition": + return ""; + default: { + const t = node; + throw new Error(`renderPlainText: unknown block ${t.type}`); + } + } +} +function renderList4(node, ctx) { + ctx.listDepth++; + let out = ""; + let counter = node.start ?? 1; + const indent2 = " ".repeat(ctx.listDepth - 1); + for (const item2 of node.items) { + out += indent2 + (node.ordered ? `${counter}. ` : "- "); + counter++; + let content = trimNonNbsp(renderBlocks4(item2.children, ctx)); + if (node.tight) { + const nestedIndent = " ".repeat(ctx.listDepth); + content = content.replace(new RegExp(`\\n\\n(?=${nestedIndent}(?:-|\\d+[.)]) )`, "g"), "\n"); + } + out += `${content} +`; + } + ctx.listDepth--; + return `${out} +`; +} +function renderDefinitionList3(items, ctx, trailingBlank) { + let out = ""; + for (const item2 of items) { + for (const term of item2.terms) + out += `${renderInlines4(term, ctx)} +`; + for (const def of item2.definitions) + out += ` ${trimNonNbsp(renderBlocks4(def, ctx))} +`; + } + return trailingBlank ? `${out} +` : out; +} +function renderTable4(node, ctx) { + const cols = node.rows.reduce((max, row) => Math.max(max, row.cells.length), 0); + let out = ""; + for (const row of node.rows) { + const cells = []; + for (let i = 0; i < cols; i++) { + cells.push(i < row.cells.length ? trimNonNbsp(renderInlines4(row.cells[i].children, ctx)) : ""); + } + while (cells.length > row.cells.length && cells[cells.length - 1] === "") + cells.pop(); + out += `${cells.join(" | ")} +`; + } + if (node.caption) + out = `${trimEndNonNbsp(out)} +${renderInlines4(node.caption, ctx)} +`; + return `${out} +`; +} +function renderFigure4(node, ctx) { + const target = node.target.type === "image" ? stripControls2(node.target.alt) : node.target.type === "table" ? trimNonNbsp(renderTable4(node.target, ctx)) : trimNonNbsp(renderBlock4(node.target, ctx)); + const sep = node.target.type === "block_quote" ? "\n\n" : "\n"; + return `${target}${sep}${renderInlines4(node.caption, ctx)} + +`; +} +function renderPanelFigure2(node, ctx) { + const target = node.target.type === "image" ? stripControls2(node.target.alt) : node.target.type === "table" ? trimNonNbsp(renderTable4(node.target, ctx)) : trimNonNbsp(renderBlock4(node.target, ctx)); + return `${trimNonNbsp(renderInlines4(node.caption, ctx))} +${target} + +`; +} +function renderFootnoteDefs2(ast, ctx) { + if (!ast.footnoteDefs) + return ""; + let out = ""; + for (const [label, blocks] of Object.entries(ast.footnoteDefs)) { + out += `[^${stripControls2(label)}]: ${trimNonNbsp(outsideLink3(() => renderBlocks4(blocks, ctx)))} +`; + } + return out; +} +function renderImageText(node) { + if (node.ref !== void 0 && !node.src) + return stripControls2(referenceSourceText(node.rawRef)); + return stripControls2(node.alt); +} +function renderInlines4(nodes, ctx) { + if (ctx.inlineDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderPlainText", MAX_RENDER_DEPTH); + ctx.inlineDepth++; + try { + return nodes.map((node) => renderInline4(node, ctx)).join(""); + } finally { + ctx.inlineDepth--; + } +} +function withinLink3(fn) { + const previous = insideLink3; + insideLink3 = true; + try { + return fn(); + } finally { + insideLink3 = previous; + } +} +function outsideLink3(fn) { + const previous = insideLink3; + insideLink3 = false; + try { + return fn(); + } finally { + insideLink3 = previous; + } +} +function renderInline4(node, ctx) { + node = normalizeLegacyInline(node); + switch (node.type) { + case "text": + return cleanEscapedText3(node); + case "escaped_text": + return node.value; + case "emphasis": + case "strong": + case "underline": + case "superscript": + case "span": { + const authoredAbbr = node.attrs?.keyValues?.abbr; + if (authoredAbbr !== void 0) { + const previous = suppressAutomaticAbbreviation3; + suppressAutomaticAbbreviation3 = true; + try { + const inner = renderInlines4(node.children, ctx); + if (authoredAbbr === "") + return inner; + if (!ctx.abbrBudget.charge(utf8ByteLength(authoredAbbr))) + return inner; + return `${inner} (${stripControls2(authoredAbbr)})`; + } finally { + suppressAutomaticAbbreviation3 = previous; + } + } + return renderInlines4(node.children, ctx); + } + case "subscript": + case "highlight": + case "insert": + case "strike": + return renderInlines4(node.children, ctx); + case "delete": + return `~${renderInlines4(node.children, ctx)}~`; + case "code": + return stripControls2(node.value); + case "link": + if (isUnresolvedReference(node)) + return stripControls2(referenceSourceText(node.rawRef)); + if (insideLink3) + return renderInlines4(node.children, ctx); + return withinLink3(() => renderInlines4(node.children, ctx)); + case "image": + return renderImageText(node); + case "math": + return stripControls2(node.content); + case "raw_inline": + return ""; + case "literal_inline": + return stripControls2(node.content); + case "symbol": + return `:${stripControls2(node.name)}:`; + case "autolink": + if (insideLink3) { + const display = node.href.startsWith("mailto:") ? node.href.slice(7) : node.text ?? node.href; + return stripControls2(display); + } + return stripControls2(node.text ?? (node.href.startsWith("mailto:") ? node.href.slice(7) : node.href)); + case "mention": + return `@${stripControls2(node.user)}`; + case "tag": + return `#${stripControls2(node.name)}`; + case "inline_extension": + return renderInlines4(node.content, ctx); + case "abbreviation": + if (suppressAutomaticAbbreviation3) + return stripControls2(node.abbr); + if (!ctx.abbrBudget.charge(utf8ByteLength(node.expansion))) + return stripControls2(node.abbr); + ctx.expanded.add(abbreviationPairKey(node.abbr, node.expansion)); + return `${stripControls2(node.abbr)} (${stripControls2(node.expansion)})`; + case "footnote_ref": + case "inline_footnote": { + if (node.inline) { + const inline = node.inline; + return `(${outsideLink3(() => renderInlines4(inline, ctx))})`; + } + const id = stripControls2(node.id ?? ""); + return ctx.definedFootnotes.has(id) ? `[${id}]` : `[^${id}]`; + } + case "soft_break": + return " "; + case "hard_break": + return "\n"; + case "substitution": + return `~${stripControls2(node.oldText)}~${stripControls2(node.newText)}`; + // A critic comment is VISIBLE content: the HTML target renders it as + // ` note `, so dropping it here made two + // targets of one engine disagree about whether the document says it. + // carve-php kept it (carve#352, corpus 33-editorial-markup). + case "critic_comment": + return stripControls2(node.text); + case "heading_ref": + if (node.href) { + const label = renderInlines4(node.resolvedText ?? [], ctx); + return ctx.abbrBudget.charge(utf8ByteLength(label)) ? label : stripControls2(node.target); + } + return ``; + case "caption_number": + return node.n === void 0 ? "#" : String(node.n); + case "citation_group": + return stripControls2(node.raw); + case "comment": + return ""; + case "smart_punctuation": + if (ctx.smartSource) + return node.value; + return node.glyph ?? SMART_PUNCTUATION_GLYPHS[node.kind] ?? node.value; + default: { + const t = node; + throw new Error(`renderPlainText: unknown inline ${t.type}`); + } + } +} +function normalize3(text) { + const body = trimEndNonNbsp(text.replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "")); + return `${body} +`.replace(/\ue000/g, " "); +} +function cleanEscapedText3(node) { + return stripControls2(node.value); +} +function stripControls2(s) { + return s.replace(/[\u000d\u007f-\u009f]/gu, ""); +} +var suppressAutomaticAbbreviation3, NO_EXPANDED_DEFINITIONS, insideLink3; +var init_render_plain = __esm({ + "node_modules/@markup-carve/carve/dist/render-plain.js"() { + init_abbr_budget(); + init_abbr_expansion_emitted(); + init_render_depth(); + init_ast(); + init_legacy_nodes(); + init_trim_non_nbsp(); + init_bidi_controls(); + init_unresolved_reference(); + suppressAutomaticAbbreviation3 = false; + NO_EXPANDED_DEFINITIONS = /* @__PURE__ */ new Set(); + insideLink3 = false; + } +}); + +// node_modules/@markup-carve/carve/dist/render-ansi.js +function renderAnsi(ast, opts = {}) { + if (!documentHasAbbreviationDef(ast)) + return renderPass2(ast, opts, NO_EXPANDED_DEFINITIONS2).text; + const probe = renderPass2(ast, opts, NO_EXPANDED_DEFINITIONS2); + return renderPass2(ast, opts, probe.expanded).text; +} +function renderPass2(ast, opts, expandedDefinitions) { + const ctx = { + smartSource: smartTypographyIsSource(opts.smartTypography), + listDepth: 0, + blockQuoteDepth: 0, + ordered: [], + blockDepth: 0, + inlineDepth: 0, + abbrBudget: budgetForDocument(ast), + definedFootnotes: new Set(Object.keys(ast.footnoteDefs ?? {})), + expandedDefinitions, + expanded: /* @__PURE__ */ new Set() + }; + const out = renderBlocks5(ast.children, ctx); + const footnotes = renderFootnoteDefs3(ast, ctx); + return { text: stripBidiControls(normalize4(`${out}${footnotes}`)), expanded: ctx.expanded }; +} +function chargeCrossrefLabel2(label, target, ctx) { + return ctx.abbrBudget.charge(utf8ByteLength(label)) ? label : stripControls3(target); +} +function style(text, codes) { + return `${codes}${text}${RESET}`; +} +function renderBlocks5(blocks, ctx) { + if (ctx.blockDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderAnsi", MAX_RENDER_DEPTH); + ctx.blockDepth++; + try { + return blocks.map((b) => renderBlock5(b, ctx)).join(""); + } finally { + ctx.blockDepth--; + } +} +function renderBlock5(node, ctx) { + switch (node.type) { + case "heading": + return renderHeading(node.level, renderInlines5(node.children, ctx)); + case "paragraph": { + let content = renderInlines5(node.children, ctx); + const prefix = blockQuotePrefix(ctx); + if (prefix) + content = prefixLines(content, prefix); + return `${content} + +`; + } + case "code_block": + return renderCodeBlock(stripControls3(node.content), node.lang ? stripControls3(node.lang) : node.lang, node.header ? stripControls3(node.header) : void 0, node.label ? stripControls3(node.label) : void 0); + case "block_quote": + ctx.blockQuoteDepth++; + { + const out = renderBlocks5(node.children, ctx); + ctx.blockQuoteDepth--; + return out; + } + case "list": + return renderList5(node, ctx); + case "thematic_break": + return `${style("\u2500".repeat(40), DIM)} + +`; + case "table": + return renderTable5(node, ctx); + case "admonition": { + const body = renderBlocks5(node.children, ctx); + const title = node.title !== void 0 ? renderInlines5(unwrapStrong2(node.title), ctx) : ""; + const prefix = blockQuotePrefix(ctx); + const boldLine = (styled) => prefix ? prefixLines(styled, prefix) : styled; + const labelLine = node.label ? `${boldLine(style(stripControls3(node.label), BOLD))} + +` : ""; + if (title !== "") { + return `${boldLine(style(title, BOLD))} + +${labelLine}${body}`; + } + return `${labelLine}${body}`; + } + case "line_block": + return renderBlocks5(node.children, ctx); + case "div": { + if (!node.label) + return renderBlocks5(node.children, ctx); + const prefix = blockQuotePrefix(ctx); + const styled = style(stripControls3(node.label), BOLD); + const labelLine = prefix ? prefixLines(styled, prefix) : styled; + return `${labelLine} + +${renderBlocks5(node.children, ctx)}`; + } + case "definition_list": + return renderDefinitionList4(node.items, ctx, true); + case "figure": + return renderFigure5(node, ctx); + case "figure_group": { + let out = ""; + if (node.caption !== void 0) + out += renderCaption(node.caption, ctx); + for (const child of node.children) { + out += child.type === "figure" ? renderPanelFigure3(child, ctx) : renderBlock5(child, ctx); + } + return out; + } + case "image": + return `${renderImage4(node)} + +`; + case "raw_block": + return `${style(`[raw:${node.format}] ${stripControls3(node.content)}`, DIM)} + +`; + case "abbreviation_def": + if (ctx.expandedDefinitions.has(abbreviationPairKey(node.abbr, node.expansion))) + return ""; + return `${style(`*[${stripControls3(node.abbr)}]: ${stripControls3(node.expansion)}`, DIM)} + +`; + case "comment": + return ""; + case "link_reference_definition": + case "citation_definition": + return ""; + default: { + const t = node; + throw new Error(`renderAnsi: unknown block ${t.type}`); + } + } +} +function renderHeading(level, content) { + const color = level === 1 ? FG_BRIGHT_MAGENTA : level === 2 ? FG_BRIGHT_CYAN : level === 3 ? FG_BRIGHT_BLUE : level === 4 ? FG_BRIGHT_GREEN : level === 5 ? FG_BRIGHT_YELLOW : FG_BRIGHT_WHITE; + let out = style(content, BOLD + color); + if (level <= 2) { + const char = level === 1 ? "\u2550" : "\u2500"; + out += ` +${style(char.repeat(width(content)), color)}`; + } + return `${out} + +`; +} +function renderCodeBlock(content, lang, header, label) { + let out = ""; + if (header) + out += `${style(header, BOLD)} + +`; + if (label) + out += `${style(label, BOLD)} + +`; + if (lang) + out += `${style(`\u250C\u2500\u2500 ${lang} `, DIM)} +`; + for (const line2 of content.replace(/\n$/, "").split("\n")) { + out += `${style(` ${line2}`, FG_BRIGHT_WHITE)} +`; + } + return `${out} +`; +} +function blockQuotePrefix(ctx) { + return ctx.blockQuoteDepth > 0 ? `${style("\u2502", FG_CYAN + DIM)} `.repeat(ctx.blockQuoteDepth) : ""; +} +function prefixLines(content, prefix) { + return content.split("\n").map((line2) => `${prefix}${line2}`).join("\n"); +} +function renderList5(node, ctx) { + ctx.listDepth++; + if (node.ordered) + ctx.ordered[ctx.listDepth] = node.start ?? 1; + const out = node.items.map((item2) => { + const indent2 = " ".repeat(ctx.listDepth - 1); + let marker; + if (node.ordered) { + const n = ctx.ordered[ctx.listDepth] ?? 1; + ctx.ordered[ctx.listDepth] = n + 1; + marker = style(`${n}.`, FG_YELLOW); + } else if (item2.checked !== void 0) { + marker = item2.checked ? style("\u2611", FG_GREEN) : style("\u2610", FG_BRIGHT_BLACK); + } else { + marker = style("\u2022", FG_CYAN); + } + return `${indent2}${marker} ${trimNonNbsp(renderBlocks5(item2.children, ctx))} +`; + }).join(""); + ctx.listDepth--; + return ctx.listDepth === 0 ? `${out} +` : out; +} +function renderDefinitionList4(items, ctx, trailingBlank) { + let out = ""; + for (const item2 of items) { + for (const term of item2.terms) + out += `${style(renderInlines5(term, ctx), BOLD + FG_YELLOW)} +`; + for (const def of item2.definitions) + out += ` ${trimNonNbsp(renderBlocks5(def, ctx))} +`; + } + return trailingBlank ? `${out} +` : out; +} +function renderTable5(node, ctx) { + const cols = node.rows.reduce((max, row) => Math.max(max, row.cells.length), 0); + const rows = node.rows.map((row) => { + const isHeader = row.cells.length > 0 && row.cells.every((c) => c.header); + return Array.from({ length: cols }, (_, i) => { + const cell = row.cells[i]; + const content = cell ? trimNonNbsp(renderInlines5(cell.children, ctx)) : ""; + return { content, plain: stripAnsi(content), isHeader }; + }); + }); + const widths = []; + for (const row of rows) { + row.forEach((cell, i) => { + widths[i] = Math.max(widths[i] ?? 0, width(cell.plain)); + }); + } + let out = ""; + let headerRendered = false; + if (rows.length) + out += tableBorder(widths, "top"); + for (const row of rows) { + out += tableRow(row, widths); + if (row[0]?.isHeader && !headerRendered) { + out += tableBorder(widths, "middle"); + headerRendered = true; + } + } + if (rows.length) + out += tableBorder(widths, "bottom"); + if (node.caption) + out += renderCaption(node.caption, ctx); + return `${out} +`; +} +function tableBorder(widths, pos) { + const left = pos === "top" ? "\u250C" : pos === "middle" ? "\u251C" : "\u2514"; + const right = pos === "top" ? "\u2510" : pos === "middle" ? "\u2524" : "\u2518"; + const cross = pos === "top" ? "\u252C" : pos === "middle" ? "\u253C" : "\u2534"; + return `${style(left + widths.map((w) => "\u2500".repeat(w + 2)).join(cross) + right, DIM)} +`; +} +function tableRow(cells, widths) { + const sep = style("\u2502", DIM); + const parts = cells.map((cell, i) => { + const padding = (widths[i] ?? 0) - width(cell.plain); + const content = cell.isHeader ? style(cell.content + " ".repeat(padding), BOLD) : cell.content + " ".repeat(padding); + return ` ${content} `; + }); + return `${sep}${parts.join(sep)}${sep} +`; +} +function renderFigure5(node, ctx) { + const target = node.target.type === "image" ? renderImage4(node.target) : node.target.type === "table" ? trimEndNonNbsp(renderTable5(node.target, ctx)) : trimEndNonNbsp(renderBlock5(node.target, ctx)); + const sep = node.target.type === "block_quote" ? "\n\n" : "\n"; + return `${target}${sep}${renderCaption(node.caption, ctx)}`; +} +function renderCaption(nodes, ctx) { + return `${style(trimNonNbsp(renderInlines5(nodes, ctx)), ITALIC + DIM)} + +`; +} +function renderPanelFigure3(node, ctx) { + const target = node.target.type === "image" ? renderImage4(node.target) : node.target.type === "table" ? trimEndNonNbsp(renderTable5(node.target, ctx)) : trimEndNonNbsp(renderBlock5(node.target, ctx)); + return `${style(trimNonNbsp(renderInlines5(node.caption, ctx)), ITALIC + DIM)} +${target} + +`; +} +function renderFootnoteDefs3(ast, ctx) { + if (!ast.footnoteDefs) + return ""; + let out = ""; + for (const [label, blocks] of Object.entries(ast.footnoteDefs)) { + out += `${style(`[^${stripControls3(label)}]`, FG_CYAN + DIM)} ${trimNonNbsp(outsideLink4(() => renderBlocks5(blocks, ctx)))} +`; + } + return out; +} +function withinLink4(fn) { + const previous = insideLink4; + insideLink4 = true; + try { + return fn(); + } finally { + insideLink4 = previous; + } +} +function outsideLink4(fn) { + const previous = insideLink4; + insideLink4 = false; + try { + return fn(); + } finally { + insideLink4 = previous; + } +} +function renderInlines5(nodes, ctx) { + if (ctx.inlineDepth >= MAX_RENDER_DEPTH) + throw new RenderDepthError("renderAnsi", MAX_RENDER_DEPTH); + ctx.inlineDepth++; + try { + return nodes.map((node) => renderInline5(node, ctx)).join(""); + } finally { + ctx.inlineDepth--; + } +} +function renderInline5(node, ctx) { + node = normalizeLegacyInline(node); + switch (node.type) { + case "text": + return cleanEscapedText4(node); + case "escaped_text": + return node.value; + case "emphasis": + return style(renderInlines5(node.children, ctx), ITALIC); + case "strong": { + const inner = node.children[0]; + if (node.boldItalic === true && node.children.length === 1 && inner?.type === "emphasis") { + return style(renderInlines5(inner.children, ctx), BOLD + ITALIC); + } + return style(renderInlines5(node.children, ctx), BOLD); + } + case "underline": + return style(renderInlines5(node.children, ctx), UNDERLINE); + case "strike": + return style(renderInlines5(node.children, ctx), STRIKE); + case "subscript": + return toSubscript(renderInlines5(node.children, ctx)); + case "superscript": + return toSuperscript(renderInlines5(node.children, ctx)); + case "highlight": + return style(renderInlines5(node.children, ctx), "\x1B[7m" + FG_YELLOW); + case "code": + return style(stripControls3(node.value), FG_BRIGHT_YELLOW); + case "link": { + if (isUnresolvedReference(node)) + return stripControls3(referenceSourceText(node.rawRef)); + if (insideLink4) + return renderInlines5(node.children, ctx); + const text = withinLink4(() => renderInlines5(node.children, ctx)); + const authored = stripControls3(node.href); + const shows = authored && !authored.startsWith("#") && authored !== stripAnsi(text); + let out = style(text, UNDERLINE + FG_BLUE); + if (shows) { + out += style(` (${blankDeniedDestination(authored)})`, DIM); + } + return out; + } + case "image": + return renderImage4(node); + case "span": { + const authoredAbbr = node.attrs?.keyValues?.abbr; + if (authoredAbbr !== void 0) { + const previous = suppressAutomaticAbbreviation4; + suppressAutomaticAbbreviation4 = true; + try { + const inner = renderInlines5(node.children, ctx); + if (authoredAbbr === "") + return inner; + if (!ctx.abbrBudget.charge(utf8ByteLength(authoredAbbr))) + return inner; + return `${inner}${style(` (${stripControls3(authoredAbbr)})`, DIM)}`; + } finally { + suppressAutomaticAbbreviation4 = previous; + } + } + return renderInlines5(node.children, ctx); + } + case "math": + return style(stripControls3(node.content), FG_BRIGHT_MAGENTA); + case "raw_inline": + return ""; + case "literal_inline": + return stripControls3(node.content); + case "symbol": + return `:${stripControls3(node.name)}:`; + case "autolink": + if (insideLink4) { + const display = node.href.startsWith("mailto:") ? node.href.slice(7) : node.text ?? node.href; + return stripControls3(display); + } + return style(stripControls3(node.text ?? (node.href.startsWith("mailto:") ? node.href.slice(7) : node.href)), UNDERLINE + FG_BLUE); + case "mention": + return `@${stripControls3(node.user)}`; + case "tag": + return `#${stripControls3(node.name)}`; + case "inline_extension": + return renderInlines5(node.content, ctx); + case "abbreviation": { + if (suppressAutomaticAbbreviation4) + return stripControls3(node.abbr); + if (!ctx.abbrBudget.charge(utf8ByteLength(node.expansion))) + return stripControls3(node.abbr); + ctx.expanded.add(abbreviationPairKey(node.abbr, node.expansion)); + return `${stripControls3(node.abbr)}${style(` (${stripControls3(node.expansion)})`, DIM)}`; + } + case "footnote_ref": + case "inline_footnote": { + if (node.inline) { + const inline = node.inline; + return `(${outsideLink4(() => renderInlines5(inline, ctx))})`; + } + const id = stripControls3(node.id ?? ""); + if (!ctx.definedFootnotes.has(id)) + return `[^${id}]`; + return style(`[${id}]`, FG_CYAN + BOLD); + } + case "soft_break": + return " "; + case "hard_break": + return "\n"; + case "insert": + return style(renderInlines5(node.children, ctx), FG_GREEN + UNDERLINE); + case "delete": + return style(renderInlines5(node.children, ctx), STRIKE + "\x1B[31m"); + case "substitution": + return style(stripControls3(node.oldText), STRIKE + "\x1B[31m") + style(stripControls3(node.newText), FG_GREEN + UNDERLINE); + // A critic comment is VISIBLE content: the HTML target renders it as + // ` note `, so dropping it here made two + // targets of one engine disagree about whether the document says it. + // carve-php kept it (carve#352, corpus 33-editorial-markup). + case "critic_comment": + return stripControls3(node.text); + case "heading_ref": + if (node.href && insideLink4) + return chargeCrossrefLabel2(renderInlines5(node.resolvedText ?? [], ctx), node.target, ctx); + if (node.href) { + return style(chargeCrossrefLabel2(withinLink4(() => renderInlines5(node.resolvedText ?? [], ctx)), node.target, ctx), UNDERLINE + FG_BLUE); + } + return ``; + case "caption_number": + return node.n === void 0 ? "#" : String(node.n); + case "citation_group": + return stripControls3(node.raw); + case "comment": + return ""; + case "smart_punctuation": + if (ctx.smartSource) + return node.value; + return node.glyph ?? SMART_PUNCTUATION_GLYPHS[node.kind] ?? node.value; + default: { + const t = node; + throw new Error(`renderAnsi: unknown inline ${t.type}`); + } + } +} +function renderImage4(node) { + if (node.ref !== void 0 && !node.src) + return stripControls3(referenceSourceText(node.rawRef)); + const alt = stripControls3(node.alt); + return `${style("[img:", FG_MAGENTA)}${alt ? ` ${alt}` : ""}${style("]", FG_MAGENTA)}`; +} +function stripAnsi(text) { + return text.replace(/\x1b\[[0-9;]*m/g, ""); +} +function isWideCodePoint(cp) { + return cp >= 4352 && cp <= 4447 || cp === 9001 || cp === 9002 || cp >= 11904 && cp <= 12350 || cp >= 12353 && cp <= 13311 || cp >= 13312 && cp <= 19903 || cp >= 19968 && cp <= 40959 || cp >= 40960 && cp <= 42191 || cp >= 44032 && cp <= 55203 || cp >= 63744 && cp <= 64255 || cp >= 65040 && cp <= 65049 || cp >= 65072 && cp <= 65135 || cp >= 65280 && cp <= 65376 || cp >= 65504 && cp <= 65510 || cp >= 127744 && cp <= 129791 || cp >= 131072 && cp <= 262141; +} +function width(text) { + let w = 0; + for (const ch of stripBidiControls(stripAnsi(text))) { + w += isWideCodePoint(ch.codePointAt(0)) ? 2 : 1; + } + return w; +} +function toSuperscript(text) { + const map = { + "0": "\u2070", + "1": "\xB9", + "2": "\xB2", + "3": "\xB3", + "4": "\u2074", + "5": "\u2075", + "6": "\u2076", + "7": "\u2077", + "8": "\u2078", + "9": "\u2079", + "+": "\u207A", + "-": "\u207B", + "=": "\u207C", + "(": "\u207D", + ")": "\u207E", + n: "\u207F", + i: "\u2071" + }; + return mapOutsideAnsi(text, map); +} +function mapOutsideAnsi(text, map) { + return text.split(/(\x1b\[[0-9;]*m)/).map((seg, i) => i % 2 === 1 ? seg : Array.from(seg).map((ch) => map[ch] ?? ch).join("")).join(""); +} +function toSubscript(text) { + const map = { + "0": "\u2080", + "1": "\u2081", + "2": "\u2082", + "3": "\u2083", + "4": "\u2084", + "5": "\u2085", + "6": "\u2086", + "7": "\u2087", + "8": "\u2088", + "9": "\u2089", + "+": "\u208A", + "-": "\u208B", + "=": "\u208C", + "(": "\u208D", + ")": "\u208E", + a: "\u2090", + e: "\u2091", + o: "\u2092", + x: "\u2093" + }; + return mapOutsideAnsi(text, map); +} +function normalize4(text) { + return `${trimNonNbsp(text.replace(/\n{3,}/g, "\n\n"))} +`.replace(/\ue000/g, " "); +} +function cleanEscapedText4(node) { + return stripControls3(node.value); +} +function stripControls3(s) { + return s.replace(new RegExp("\\p{Cc}", "gu"), (c) => c === " " || c === "\n" ? c : ""); +} +function unwrapStrong2(nodes) { + return nodes.flatMap((n) => { + const kids = n.children; + if (n.type === "strong") + return unwrapStrong2(kids ?? []); + if (Array.isArray(kids)) + return [{ ...n, children: unwrapStrong2(kids) }]; + return [n]; + }); +} +var suppressAutomaticAbbreviation4, NO_EXPANDED_DEFINITIONS2, RESET, BOLD, DIM, ITALIC, UNDERLINE, STRIKE, FG_BLUE, FG_MAGENTA, FG_CYAN, FG_YELLOW, FG_GREEN, FG_BRIGHT_BLACK, FG_BRIGHT_YELLOW, FG_BRIGHT_MAGENTA, FG_BRIGHT_CYAN, FG_BRIGHT_BLUE, FG_BRIGHT_GREEN, FG_BRIGHT_WHITE, insideLink4; +var init_render_ansi = __esm({ + "node_modules/@markup-carve/carve/dist/render-ansi.js"() { + init_render_depth(); + init_ast(); + init_abbr_budget(); + init_abbr_expansion_emitted(); + init_legacy_nodes(); + init_deny_listed_destination(); + init_render_plain(); + init_trim_non_nbsp(); + init_bidi_controls(); + init_unresolved_reference(); + suppressAutomaticAbbreviation4 = false; + NO_EXPANDED_DEFINITIONS2 = /* @__PURE__ */ new Set(); + RESET = "\x1B[0m"; + BOLD = "\x1B[1m"; + DIM = "\x1B[2m"; + ITALIC = "\x1B[3m"; + UNDERLINE = "\x1B[4m"; + STRIKE = "\x1B[9m"; + FG_BLUE = "\x1B[34m"; + FG_MAGENTA = "\x1B[35m"; + FG_CYAN = "\x1B[36m"; + FG_YELLOW = "\x1B[33m"; + FG_GREEN = "\x1B[32m"; + FG_BRIGHT_BLACK = "\x1B[90m"; + FG_BRIGHT_YELLOW = "\x1B[93m"; + FG_BRIGHT_MAGENTA = "\x1B[95m"; + FG_BRIGHT_CYAN = "\x1B[96m"; + FG_BRIGHT_BLUE = "\x1B[94m"; + FG_BRIGHT_GREEN = "\x1B[92m"; + FG_BRIGHT_WHITE = "\x1B[97m"; + insideLink4 = false; + } +}); + +// node_modules/@markup-carve/carve/dist/definition-list-wire.js +function span(nodes) { + if (nodes.length === 0) + return void 0; + const first = nodes[0]?.pos; + const last = nodes[nodes.length - 1]?.pos; + if (first === void 0 || last === void 0) + return void 0; + const pos = { startLine: first.startLine, endLine: last.endLine }; + if (first.startColumn !== void 0) + pos.startColumn = first.startColumn; + if (last.endColumn !== void 0) + pos.endColumn = last.endColumn; + if (first.startOffset !== void 0) + pos.startOffset = first.startOffset; + if (last.endOffset !== void 0) + pos.endOffset = last.endOffset; + return pos; +} +function entriesToWire(items) { + const out = []; + for (const item2 of items) { + for (const [index2, term] of (item2.terms ?? []).entries()) { + const node = { type: "definition_term", children: term }; + const pos = item2.termSpans?.[index2] ?? span(term); + if (pos !== void 0) + node.pos = pos; + out.push(node); + } + ; + (item2.definitions ?? []).forEach((definition, index2) => { + const node = { + type: "definition_description", + children: definition + }; + const recorded = item2.definitionSpans?.[index2]; + const derived = span(definition); + const pos = recorded ? { ...recorded } : derived; + if (pos && recorded && derived) { + pos.endLine = derived.endLine; + if (derived.endColumn !== void 0) + pos.endColumn = derived.endColumn; + if (derived.endOffset !== void 0) + pos.endOffset = derived.endOffset; + } + if (pos !== void 0) + node.pos = pos; + out.push(node); + }); + } + return out; +} +function readPos(value) { + if (typeof value !== "object" || value === null) + return void 0; + const pos = value; + if (typeof pos.startLine !== "number" || typeof pos.endLine !== "number") + return void 0; + return pos; +} +function entriesFromWire(nodes) { + const items = []; + let current; + const open = () => { + const item2 = { + terms: [], + definitions: [], + termSpans: [], + definitionLines: [], + definitionSpans: [] + }; + items.push(item2); + return item2; + }; + for (const node of nodes) { + if (typeof node !== "object" || node === null) + continue; + const entry = node; + if (!Array.isArray(entry.children)) + continue; + if (entry.type === "definition_term") { + if (current === void 0 || current.definitions.length > 0) + current = open(); + current.terms.push(entry.children); + current.termSpans.push(readPos(entry.pos)); + continue; + } + if (entry.type === "definition_description") { + if (current === void 0) + current = open(); + current.definitions.push(entry.children); + const pos = readPos(entry.pos); + current.definitionSpans.push(pos); + current.definitionLines.push(pos?.startLine); + } + } + return items; +} +function isRuntimeEntry(value) { + return typeof value === "object" && value !== null && Array.isArray(value.terms); +} +var init_definition_list_wire = __esm({ + "node_modules/@markup-carve/carve/dist/definition-list-wire.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/wire-fields.js +var WIRE_FIELDS, WIRE_RECORD_FIELDS, NODE_FIELDS, NODE_POSITION_KIND, WIRE_REQUIRED, WIRE_VALUE_KINDS, NODE_POSITION_TYPES, WIRE_NESTED_RECORDS; +var init_wire_fields = __esm({ + "node_modules/@markup-carve/carve/dist/wire-fields.js"() { + WIRE_FIELDS = { + "abbreviation": ["abbr", "attrs", "expansion", "pos", "type"], + "abbreviation_def": ["abbr", "attrs", "expansion", "pos", "type"], + "admonition": ["attrs", "children", "kind", "label", "pos", "title", "type"], + "autolink": ["attrs", "href", "pos", "text", "type"], + "block_quote": ["attrs", "children", "pos", "type"], + "caption_number": ["attrs", "n", "pos", "type"], + "citation_definition": ["attrs", "children", "key", "pos", "type"], + "citation_group": ["attrs", "items", "mode", "pos", "raw", "type"], + "code": ["attrs", "pos", "type", "value"], + "code_block": ["attrs", "content", "header", "label", "lang", "pos", "type"], + "comment": ["attrs", "block", "content", "delimited", "pos", "type"], + "critic_comment": ["attrs", "pos", "text", "type"], + "definition_description": ["attrs", "children", "pos", "type"], + "definition_list": ["attrs", "items", "pos", "type"], + "definition_term": ["attrs", "children", "pos", "type"], + "delete": ["attrs", "children", "pos", "type"], + "div": ["attrs", "children", "label", "pos", "type"], + "document": ["children", "srcByteLength", "type"], + "emphasis": ["attrs", "children", "pos", "type"], + "escaped_text": ["attrs", "pos", "type", "value"], + "figure": ["attrs", "caption", "pos", "shortCaption", "target", "type"], + "figure_group": ["attrs", "caption", "children", "pos", "type"], + "footnote": ["attrs", "children", "label", "pos", "type"], + "footnote_ref": ["attrs", "id", "number", "pos", "type"], + "frontmatter": ["content", "format", "pos", "type"], + "hard_break": ["attrs", "pos", "type"], + "heading": ["attrs", "children", "level", "pos", "type"], + "heading_ref": ["attrs", "href", "pos", "target", "type"], + "highlight": ["attrs", "children", "pos", "type"], + "image": ["alt", "attrs", "pos", "rawRef", "ref", "src", "title", "type"], + "inline_extension": ["attrs", "content", "name", "pos", "type"], + "inline_footnote": ["attrs", "inline", "number", "pos", "type"], + "insert": ["attrs", "children", "pos", "type"], + "line_block": ["attrs", "children", "pos", "type"], + "link": ["attrs", "children", "href", "pos", "rawRef", "ref", "title", "type"], + "link_reference_definition": ["attrs", "href", "label", "pos", "title", "type"], + "list": ["attrs", "bareMarker", "bulletChar", "delim", "items", "olType", "ordered", "pos", "start", "tight", "type"], + "list_item": ["attrs", "checked", "children", "pos", "type"], + "literal_inline": ["attrs", "content", "pos", "type"], + "math": ["attrs", "content", "display", "pos", "type"], + "mention": ["attrs", "pos", "type", "user"], + "paragraph": ["attrs", "children", "pos", "type"], + "raw_block": ["attrs", "content", "format", "pos", "type"], + "raw_inline": ["attrs", "content", "format", "pos", "type"], + "smart_punctuation": ["attrs", "glyph", "kind", "pos", "type", "value"], + "soft_break": ["attrs", "pos", "type"], + "span": ["attrs", "children", "pos", "type"], + "strike": ["attrs", "children", "pos", "type"], + "strong": ["attrs", "boldItalic", "children", "pos", "type"], + "subscript": ["attrs", "children", "pos", "type"], + "substitution": ["attrs", "newText", "oldText", "pos", "type"], + "superscript": ["attrs", "children", "pos", "type"], + "symbol": ["attrs", "name", "pos", "type"], + "table": ["attrs", "caption", "columns", "pos", "rowGroups", "rows", "shortCaption", "type"], + "table_cell": ["align", "attrs", "children", "header", "pos", "span", "type", "valign"], + "table_row": ["attrs", "cells", "pos", "type"], + "tag": ["attrs", "name", "pos", "type"], + "text": ["attrs", "pos", "type", "value"], + "thematic_break": ["attrs", "marker", "pos", "type"], + "underline": ["attrs", "children", "pos", "type"] + }; + WIRE_RECORD_FIELDS = { + "attrs": ["classes", "id", "keyValues", "order"], + "pos": ["endColumn", "endLine", "endOffset", "startColumn", "startLine", "startOffset"], + "table.columns": ["align", "valign", "width"], + "table.rowGroups": ["bodies", "footRows", "headRows"], + "table.rowGroups.bodies": ["attrs", "bodyRows", "headRows", "rowHeadColumns"] + }; + NODE_FIELDS = [ + "caption", + "cells", + "children", + "content", + "inline", + "items", + "locator", + "prefix", + "rows", + "shortCaption", + "suffix", + "target", + "title" + ]; + NODE_POSITION_KIND = { + "admonition.children": "nodes", + "admonition.title": "nodes", + "block_quote.children": "nodes", + "citation_definition.children": "nodes", + "citation_group.items": "records", + "definition_description.children": "nodes", + "definition_list.items": "nodes", + "definition_term.children": "nodes", + "delete.children": "nodes", + "div.children": "nodes", + "document.children": "nodes", + "emphasis.children": "nodes", + "figure.caption": "nodes", + "figure.shortCaption": "nodes", + "figure.target": "node", + "figure_group.caption": "nodes", + "figure_group.children": "nodes", + "footnote.children": "nodes", + "heading.children": "nodes", + "highlight.children": "nodes", + "inline_extension.content": "nodes", + "inline_footnote.inline": "nodes", + "insert.children": "nodes", + "line_block.children": "nodes", + "link.children": "nodes", + "list.items": "nodes", + "list_item.children": "nodes", + "paragraph.children": "nodes", + "span.children": "nodes", + "strike.children": "nodes", + "strong.children": "nodes", + "subscript.children": "nodes", + "superscript.children": "nodes", + "table.caption": "nodes", + "table.rows": "nodes", + "table.shortCaption": "nodes", + "table_cell.children": "nodes", + "table_row.cells": "nodes", + "underline.children": "nodes" + }; + WIRE_REQUIRED = { + "abbreviation": ["abbr", "expansion", "type"], + "abbreviation_def": ["abbr", "expansion", "type"], + "admonition": ["children", "kind", "type"], + "attrs": [], + "autolink": ["href", "type"], + "block_quote": ["children", "type"], + "caption_number": ["type"], + "citation_definition": ["children", "key", "type"], + "citation_group": ["items", "raw", "type"], + "code": ["type", "value"], + "code_block": ["content", "type"], + "comment": ["block", "content", "type"], + "critic_comment": ["text", "type"], + "definition_description": ["children", "type"], + "definition_list": ["items", "type"], + "definition_term": ["children", "type"], + "delete": ["children", "type"], + "div": ["children", "type"], + "document": ["children", "srcByteLength", "type"], + "emphasis": ["children", "type"], + "escaped_text": ["type", "value"], + "figure": ["caption", "target", "type"], + "figure_group": ["children", "type"], + "footnote": ["children", "label", "type"], + "footnote_ref": ["type"], + "frontmatter": ["content", "format", "type"], + "hard_break": ["type"], + "heading": ["children", "level", "type"], + "heading_ref": ["target", "type"], + "highlight": ["children", "type"], + "image": ["alt", "src", "type"], + "inline_extension": ["content", "name", "type"], + "inline_footnote": ["inline", "type"], + "insert": ["children", "type"], + "line_block": ["children", "type"], + "link": ["children", "href", "type"], + "link_reference_definition": ["href", "label", "type"], + "list": ["items", "ordered", "tight", "type"], + "list_item": ["children", "type"], + "literal_inline": ["content", "type"], + "math": ["content", "display", "type"], + "mention": ["type", "user"], + "paragraph": ["children", "type"], + "pos": ["endColumn", "endLine", "endOffset", "startColumn", "startLine", "startOffset"], + "raw_block": ["content", "format", "type"], + "raw_inline": ["content", "format", "type"], + "smart_punctuation": ["kind", "type", "value"], + "soft_break": ["type"], + "span": ["children", "type"], + "strike": ["children", "type"], + "strong": ["children", "type"], + "subscript": ["children", "type"], + "substitution": ["newText", "oldText", "type"], + "superscript": ["children", "type"], + "symbol": ["name", "type"], + "table": ["rows", "type"], + "table.columns": [], + "table.rowGroups": ["bodies", "footRows", "headRows"], + "table.rowGroups.bodies": ["bodyRows", "headRows"], + "table_cell": ["children", "header", "type"], + "table_row": ["cells", "type"], + "tag": ["name", "type"], + "text": ["type", "value"], + "thematic_break": ["type"], + "underline": ["children", "type"] + }; + WIRE_VALUE_KINDS = { + "abbreviation": { "abbr": "string", "attrs": "object", "expansion": "string", "pos": "object" }, + "abbreviation_def": { "abbr": "string", "attrs": "object", "expansion": "string", "pos": "object" }, + "admonition": { "attrs": "object", "children": "array", "kind": "string", "label": "string", "pos": "object", "title": "array" }, + "attrs": { "classes": "string[]", "id": "string", "keyValues": "object", "order": "string[]" }, + "autolink": { "attrs": "object", "href": "string", "pos": "object", "text": "string" }, + "block_quote": { "attrs": "object", "children": "array", "pos": "object" }, + "caption_number": { "attrs": "object", "n": "integer", "pos": "object" }, + "citation_definition": { "attrs": "object", "children": "array", "key": "string", "pos": "object" }, + "citation_group": { "attrs": "object", "items": "array", "pos": "object", "raw": "string" }, + "code": { "attrs": "object", "pos": "object", "value": "string" }, + "code_block": { "attrs": "object", "content": "string", "header": "string", "label": "string", "lang": "string", "pos": "object" }, + "comment": { "attrs": "object", "block": "boolean", "content": "string", "delimited": "boolean", "pos": "object" }, + "critic_comment": { "attrs": "object", "pos": "object", "text": "string" }, + "definition_description": { "attrs": "object", "children": "array", "pos": "object" }, + "definition_list": { "attrs": "object", "items": "array", "pos": "object" }, + "definition_term": { "attrs": "object", "children": "array", "pos": "object" }, + "delete": { "attrs": "object", "children": "array", "pos": "object" }, + "div": { "attrs": "object", "children": "array", "label": "string", "pos": "object" }, + "document": { "children": "array", "srcByteLength": "integer>=0" }, + "emphasis": { "attrs": "object", "children": "array", "pos": "object" }, + "escaped_text": { "attrs": "object", "pos": "object", "value": "string" }, + "figure": { "attrs": "object", "caption": "array", "pos": "object", "shortCaption": "array" }, + "figure_group": { "attrs": "object", "caption": "array", "children": "array", "pos": "object" }, + "footnote": { "attrs": "object", "children": "array", "label": "string", "pos": "object" }, + "footnote_ref": { "attrs": "object", "id": "string", "number": "integer", "pos": "object" }, + "frontmatter": { "content": "string", "format": "string", "pos": "object" }, + "hard_break": { "attrs": "object", "pos": "object" }, + "heading": { "attrs": "object", "children": "array", "level": "integer>=1", "pos": "object" }, + "heading_ref": { "attrs": "object", "href": "string", "pos": "object", "target": "string" }, + "highlight": { "attrs": "object", "children": "array", "pos": "object" }, + "image": { "alt": "string", "attrs": "object", "pos": "object", "rawRef": "string", "ref": "string", "src": "string", "title": "string" }, + "inline_extension": { "attrs": "object", "content": "array", "name": "string", "pos": "object" }, + "inline_footnote": { "attrs": "object", "inline": "array", "number": "integer", "pos": "object" }, + "insert": { "attrs": "object", "children": "array", "pos": "object" }, + "line_block": { "attrs": "object", "children": "array", "pos": "object" }, + "link": { "attrs": "object", "children": "array", "href": "string", "pos": "object", "rawRef": "string", "ref": "string", "title": "string" }, + "link_reference_definition": { "attrs": "object", "href": "string", "label": "string", "pos": "object", "title": "string" }, + "list": { "attrs": "object", "bulletChar": "enum:-\0*", "delim": "enum:.\0)", "items": "array", "olType": "enum:a\0A\0i\0I", "ordered": "boolean", "pos": "object", "start": "integer", "tight": "boolean" }, + "list_item": { "attrs": "object", "checked": "boolean", "children": "array", "pos": "object" }, + "literal_inline": { "attrs": "object", "content": "string", "pos": "object" }, + "math": { "attrs": "object", "content": "string", "display": "boolean", "pos": "object" }, + "mention": { "attrs": "object", "pos": "object", "user": "string" }, + "paragraph": { "attrs": "object", "children": "array", "pos": "object" }, + "pos": { "endColumn": "integer>=1", "endLine": "integer>=1", "endOffset": "integer>=0", "startColumn": "integer>=1", "startLine": "integer>=1", "startOffset": "integer>=0" }, + "raw_block": { "attrs": "object", "content": "string", "format": "string", "pos": "object" }, + "raw_inline": { "attrs": "object", "content": "string", "format": "string", "pos": "object" }, + "smart_punctuation": { "attrs": "object", "glyph": "string", "kind": "string", "pos": "object", "value": "string" }, + "soft_break": { "attrs": "object", "pos": "object" }, + "span": { "attrs": "object", "children": "array", "pos": "object" }, + "strike": { "attrs": "object", "children": "array", "pos": "object" }, + "strong": { "attrs": "object", "children": "array", "pos": "object" }, + "subscript": { "attrs": "object", "children": "array", "pos": "object" }, + "substitution": { "attrs": "object", "newText": "string", "oldText": "string", "pos": "object" }, + "superscript": { "attrs": "object", "children": "array", "pos": "object" }, + "symbol": { "attrs": "object", "name": "string", "pos": "object" }, + "table": { "attrs": "object", "caption": "array", "columns": "array", "pos": "object", "rowGroups": "object", "rows": "array", "shortCaption": "array" }, + "table.columns": { "align": "enum:left\0right\0center", "valign": "enum:top\0middle\0bottom" }, + "table.rowGroups": { "bodies": "array", "footRows": "integer>=0", "headRows": "integer>=0" }, + "table.rowGroups.bodies": { "attrs": "object", "bodyRows": "integer>=0", "headRows": "integer>=0", "rowHeadColumns": "integer>=0" }, + "table_cell": { "align": "enum:left\0right\0center", "attrs": "object", "children": "array", "header": "boolean", "pos": "object", "span": "enum:rowspan\0colspan", "valign": "enum:top\0middle\0bottom" }, + "table_row": { "attrs": "object", "cells": "array", "pos": "object" }, + "tag": { "attrs": "object", "name": "string", "pos": "object" }, + "text": { "attrs": "object", "pos": "object", "value": "string" }, + "thematic_break": { "attrs": "object", "marker": "enum:-\0*\0_", "pos": "object" }, + "underline": { "attrs": "object", "children": "array", "pos": "object" } + }; + NODE_POSITION_TYPES = { + "admonition.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "admonition.title": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "block_quote.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "citation_definition.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "definition_description.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "definition_list.items": ["definition_description", "definition_term"], + "definition_term.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "delete.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "div.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "document.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "emphasis.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "figure.caption": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "figure.shortCaption": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "figure.target": ["block_quote", "code_block", "image", "paragraph", "table"], + "figure_group.caption": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "figure_group.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "footnote.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "heading.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "highlight.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "inline_extension.content": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "inline_footnote.inline": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "insert.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "line_block.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "link.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "list.items": ["list_item"], + "list_item.children": ["abbreviation_def", "admonition", "block_quote", "citation_definition", "code_block", "comment", "definition_description", "definition_list", "definition_term", "div", "figure", "figure_group", "footnote", "frontmatter", "heading", "image", "line_block", "link_reference_definition", "list", "list_item", "paragraph", "raw_block", "table", "table_cell", "table_row", "thematic_break"], + "paragraph.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "span.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "strike.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "strong.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "subscript.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "superscript.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "table.caption": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "table.rows": ["table_row"], + "table.shortCaption": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "table_cell.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"], + "table_row.cells": ["table_cell"], + "underline.children": ["abbreviation", "autolink", "caption_number", "citation_group", "code", "comment", "critic_comment", "delete", "emphasis", "escaped_text", "footnote_ref", "hard_break", "heading_ref", "highlight", "image", "inline_extension", "inline_footnote", "insert", "link", "literal_inline", "math", "mention", "raw_inline", "smart_punctuation", "soft_break", "span", "strike", "strong", "subscript", "substitution", "superscript", "symbol", "tag", "text", "underline"] + }; + WIRE_NESTED_RECORDS = { + "abbreviation": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "abbreviation_def": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "admonition": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "autolink": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "block_quote": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "caption_number": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "citation_definition": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "citation_group": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "code": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "code_block": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "comment": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "critic_comment": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "definition_description": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "definition_list": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "definition_term": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "delete": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "div": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "emphasis": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "escaped_text": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "figure": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "figure_group": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "footnote": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "footnote_ref": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "frontmatter": { "pos": { record: "pos", array: false } }, + "hard_break": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "heading": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "heading_ref": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "highlight": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "image": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "inline_extension": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "inline_footnote": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "insert": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "line_block": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "link": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "link_reference_definition": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "list": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "list_item": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "literal_inline": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "math": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "mention": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "paragraph": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "raw_block": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "raw_inline": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "smart_punctuation": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "soft_break": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "span": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "strike": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "strong": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "subscript": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "substitution": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "superscript": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "symbol": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "table": { "attrs": { record: "attrs", array: false }, "columns": { record: "table.columns", array: true }, "pos": { record: "pos", array: false }, "rowGroups": { record: "table.rowGroups", array: false } }, + "table.rowGroups": { "bodies": { record: "table.rowGroups.bodies", array: true } }, + "table.rowGroups.bodies": { "attrs": { record: "attrs", array: false } }, + "table_cell": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "table_row": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "tag": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "text": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "thematic_break": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } }, + "underline": { "attrs": { record: "attrs", array: false }, "pos": { record: "pos", array: false } } + }; + } +}); + +// node_modules/@markup-carve/carve/dist/ast-json.js +function definitionListsToWire(node) { + if (Array.isArray(node)) { + let changed = false; + const mapped = node.map((child) => { + const next = definitionListsToWire(child); + if (next !== child) + changed = true; + return next; + }); + return changed ? mapped : node; + } + if (typeof node !== "object" || node === null) + return node; + const record = node; + let out; + if (record["type"] === "definition_list" && Array.isArray(record["items"])) { + const items = record["items"]; + if (items.every(isRuntimeEntry)) { + out = { ...record, items: entriesToWire(items) }; + } + } + for (const field of CHILD_FIELDS) { + const value = (out ?? record)[field]; + if (value === void 0) + continue; + if (field === "items" && (out ?? record)["type"] === "definition_list") { + const mapped2 = definitionListsToWire(value); + if (mapped2 !== value) + out = { ...out ?? record, [field]: mapped2 }; + continue; + } + const mapped = definitionListsToWire(value); + if (mapped !== value) + out = { ...out ?? record, [field]: mapped }; + } + const target = (out ?? record)["target"]; + if (target !== void 0) { + const mapped = definitionListsToWire(target); + if (mapped !== target) + out = { ...out ?? record, target: mapped }; + } + if ((out ?? record)["type"] === "heading_ref" && (out ?? record)["resolvedText"] !== void 0) { + const { resolvedText: _resolvedText, ...rest } = out ?? record; + out = rest; + } + if (((out ?? record)["type"] === "footnote_ref" || (out ?? record)["type"] === "inline_footnote") && (out ?? record)["refId"] !== void 0) { + const { refId: _refId, ...rest } = out ?? record; + out = rest; + } + if ((out ?? record)["type"] === "text" && (out ?? record)["escapedLeadingCaret"] !== void 0) { + const { escapedLeadingCaret: _flag, ...rest } = out ?? record; + out = rest; + } + return out ?? record; +} +function definitionListsFromWire(node) { + if (Array.isArray(node)) { + return node.map((child) => definitionListsFromWire(child)); + } + if (typeof node !== "object" || node === null) + return node; + const record = { ...node }; + if (record["type"] === "definition_list" && Array.isArray(record["items"])) { + record["items"] = record["items"].every(isRuntimeEntry) ? record["items"] : entriesFromWire(record["items"]); + return record; + } + for (const field of CHILD_FIELDS) { + if (record[field] !== void 0) + record[field] = definitionListsFromWire(record[field]); + } + if (record["target"] !== void 0) + record["target"] = definitionListsFromWire(record["target"]); + if ((record["type"] === "footnote_ref" || record["type"] === "inline_footnote") && record["refId"] !== void 0) { + delete record["refId"]; + } + return record; +} +function orderCollectedDefinitions(children) { + const slots = []; + for (let i = 0; i < children.length; i++) { + if (COLLECTED_DEFINITION_TYPES.has(children[i].type)) + slots.push(i); + } + if (slots.length < 2) + return; + const ordered = slots.map((i) => children[i]).sort((a, b) => (a.pos?.startOffset ?? 0) - (b.pos?.startOffset ?? 0)); + for (let k = 0; k < slots.length; k++) + children[slots[k]] = ordered[k]; +} +function toAstJson(doc) { + const children = []; + if (doc.frontmatter !== void 0) { + const node = { + type: "frontmatter", + format: doc.frontmatter.format, + content: doc.frontmatter.content + }; + if (doc.frontmatter.pos !== void 0) + node.pos = doc.frontmatter.pos; + children.push(node); + } + children.push(...definitionListsToWire(doc.children)); + for (const [label, body] of Object.entries(doc.footnoteDefs ?? {})) { + const node = { + type: "footnote", + label, + children: definitionListsToWire(body) + }; + const pos = ownValue(doc.footnoteDefPos, label); + if (pos !== void 0) + node.pos = pos; + children.push(node); + } + orderCollectedDefinitions(children); + const out = { type: "document", children, srcByteLength: doc.srcByteLength ?? 0 }; + return out; +} +function matchesKind(value, kind2) { + if (kind2.startsWith("enum:")) { + return typeof value === "string" && kind2.slice(5).split("\0").includes(value); + } + switch (kind2) { + case "string": + return typeof value === "string"; + case "boolean": + return typeof value === "boolean"; + case "integer": + return Number.isInteger(value); + case "integer>=0": + return Number.isInteger(value) && value >= 0; + case "integer>=1": + return Number.isInteger(value) && value >= 1; + case "object": + return value !== null && typeof value === "object" && !Array.isArray(value); + case "string[]": + return Array.isArray(value) && value.every((v) => typeof v === "string"); + case "array": + return Array.isArray(value); + case "node": + return value !== null && typeof value === "object" && !Array.isArray(value); + default: + return true; + } +} +function refuseSchemaViolations(node, path8) { + if (Array.isArray(node)) { + node.forEach((item2, index2) => refuseSchemaViolations(item2, `${path8}[${index2}]`)); + return; + } + if (node === null || typeof node !== "object") + return; + const record = node; + const type = record.type; + const required = typeof type === "string" ? ownValue(WIRE_REQUIRED, type) : void 0; + if (required !== void 0) { + for (const field of required) { + if (field in record) + continue; + throw new AstJsonSchemaError(`required property "${field}" is missing`, path8); + } + const kinds = ownValue(WIRE_VALUE_KINDS, type) ?? {}; + for (const [field, kind2] of Object.entries(kinds)) { + if (!(field in record)) + continue; + if (record[field] === void 0) + continue; + if (!matchesKind(record[field], kind2)) { + throw new AstJsonSchemaError(`"${field}" is ${describe(record[field])} where the schema gives ${kind2}`, path8); + } + } + refuseNestedRecordShapes(type, record, path8); + refusePartition(record, path8); + } + for (const [key2, value] of Object.entries(record)) { + if (NODE_FIELDS.includes(key2)) { + const admitted = typeof type === "string" ? NODE_POSITION_TYPES[`${type}.${key2}`] : void 0; + const at = path8 === "" ? key2 : `${path8}.${key2}`; + if (Array.isArray(value)) { + value.forEach((item2, index2) => refuseNodeAt(item2, admitted, `${at}[${index2}]`)); + } else if (admitted !== void 0 && NODE_POSITION_KIND[`${type}.${key2}`] === "node") { + refuseNodeAt(value, admitted, at); + } + } + refuseSchemaViolations(value, path8 === "" ? key2 : `${path8}.${key2}`); + } +} +function refuseNodeAt(value, admitted, path8) { + if (value === null || typeof value !== "object" || Array.isArray(value)) { + throw new AstJsonSchemaError(`${describe(value)} sits where a node belongs`, path8); + } + if (admitted === void 0) + return; + const type = value.type; + if (typeof type !== "string") + return; + if (!admitted.includes(type)) { + throw new AstJsonSchemaError(`a "${type}" node sits where the schema admits only ${admitted.join(", ")}`, path8); + } +} +function refuseNestedRecordShapes(owner, record, path8) { + const nested = ownValue(WIRE_NESTED_RECORDS, owner); + if (nested === void 0) + return; + for (const [field, { record: name, array }] of Object.entries(nested)) { + const value = record[field]; + const at = `${path8}.${field}`; + if (array) { + if (!Array.isArray(value)) + continue; + value.forEach((item2, index2) => refuseRecordShape(item2, name, `${at}[${index2}]`)); + continue; + } + refuseRecordShape(value, name, at); + } +} +function refusePartition(record, path8) { + if (record.type !== "table") + return; + const groups = record.rowGroups; + if (groups === void 0) + return; + const rows = Array.isArray(record.rows) ? record.rows.length : 0; + const counted = (groups.headRows ?? 0) + (groups.footRows ?? 0) + (groups.bodies ?? []).reduce((total, body) => total + (body.headRows ?? 0) + (body.bodyRows ?? 0), 0); + if (counted !== rows) + throw new AstJsonPartitionError(counted, rows, path8); +} +function refuseRecordShape(value, name, path8) { + if (value === null || typeof value !== "object" || Array.isArray(value)) { + if (value === void 0) + return; + throw new AstJsonSchemaError(`${describe(value)} sits where the schema gives a record`, path8); + } + const item2 = value; + for (const field of WIRE_REQUIRED[name] ?? []) { + if (!(field in item2)) { + throw new AstJsonSchemaError(`required property "${field}" is missing`, path8); + } + } + const kinds = WIRE_VALUE_KINDS[name] ?? {}; + for (const [field, kind2] of Object.entries(kinds)) { + if (!(field in item2) || item2[field] === void 0) + continue; + if (!matchesKind(item2[field], kind2)) { + throw new AstJsonSchemaError(`"${field}" is ${describe(item2[field])} where the schema gives ${kind2}`, path8); + } + } + refuseNestedRecordShapes(name, item2, path8); +} +function describe(value) { + if (value === null) + return "null"; + if (Array.isArray(value)) + return "an array"; + if (typeof value === "object") + return "an object"; + if (typeof value === "string") + return "a string"; + return `a ${typeof value}`; +} +function isLegacyDefinitionEntry(record) { + return record.type === void 0 && Array.isArray(record["terms"]); +} +function refuseUnknownRecordFields(owner, record, path8) { + const nested = ownValue(WIRE_NESTED_RECORDS, owner); + if (nested === void 0) + return; + for (const [field, { record: name, array }] of Object.entries(nested)) { + const value = record[field]; + const at = `${path8}.${field}`; + const items = array ? Array.isArray(value) ? value.map((item2, index2) => [item2, `${at}[${index2}]`]) : [] : [[value, at]]; + for (const [item2, itemPath] of items) { + if (item2 === null || typeof item2 !== "object" || Array.isArray(item2)) + continue; + const allowed = new Set(WIRE_RECORD_FIELDS[name]); + for (const key2 of Object.keys(item2)) { + if (!allowed.has(key2)) + throw new AstJsonUnknownFieldError(key2, itemPath, name); + } + refuseUnknownRecordFields(name, item2, itemPath); + } + } +} +function refuseUnknownFields(node, path8) { + if (Array.isArray(node)) { + node.forEach((item2, index2) => refuseUnknownFields(item2, `${path8}[${index2}]`)); + return; + } + if (node === null || typeof node !== "object") + return; + const record = node; + const type = record.type; + const known = typeof type === "string" ? ownValue(WIRE_FIELDS, type) : void 0; + if (known === void 0 && isLegacyDefinitionEntry(record)) { + for (const key2 of Object.keys(record)) { + if (!LEGACY_DEFINITION_ENTRY_FIELDS.has(key2)) { + throw new AstJsonUnknownFieldError(key2, path8, "definition_list.items"); + } + } + } + if (known !== void 0) { + for (const key2 of Object.keys(record)) { + if (!known.includes(key2)) + throw new AstJsonUnknownFieldError(key2, path8, type); + } + refuseUnknownRecordFields(type, record, path8); + } + for (const [key2, value] of Object.entries(record)) { + refuseUnknownFields(value, path8 === "" ? key2 : `${path8}.${key2}`); + } +} +function refuseUnknownNodeTypes(node, path8, typeRequired, legacyKeys) { + if (Array.isArray(node)) { + node.forEach((item2, index2) => refuseUnknownNodeTypes(item2, `${path8}[${index2}]`, typeRequired, legacyKeys)); + return; + } + if (node === null || typeof node !== "object") + return; + const record = node; + const type = record.type; + if (typeof type !== "string") { + const legacyShaped = legacyKeys === void 0 || legacyKeys.some((key2) => key2 in record); + if (type !== void 0 || typeRequired || !legacyShaped) { + throw new AstJsonNodeTypeError(type, path8); + } + } else if (ownValue(WIRE_FIELDS, type) === void 0) { + throw new AstJsonUnknownNodeTypeError(type, path8); + } + const fields = typeof type === "string" ? NODE_FIELDS : [...NODE_FIELDS, ...LEGACY_RECORD_FIELDS]; + for (const field of fields) { + const value = record[field]; + if (value === void 0) + continue; + const position = typeof type === "string" ? `${type}.${field}` : void 0; + const legacy = position === void 0 ? void 0 : LEGACY_TYPELESS_POSITIONS.get(position); + const kind2 = position === void 0 ? "nodes" : legacy !== void 0 ? "records" : NODE_POSITION_KIND[position]; + refuseUnknownNodeTypes( + value, + path8 === "" ? field : `${path8}.${field}`, + // `nodes` is about the ELEMENTS: a non-array where the array belongs is + // the unruled wrong-type class, and `children: {}` still degrades to an + // empty document rather than being decided here. + kind2 === "node" ? true : kind2 === "nodes" ? Array.isArray(value) : false, + legacy + ); + } +} +function astJsonDepth(root, limit, walkLimit) { + let deepest = 0; + let deepestWalk = 0; + const stack = [ + { node: root, depth: 0, walk: 0 } + ]; + while (stack.length > 0) { + const { node, depth, walk: walk2 } = stack.pop(); + if (depth > deepest) + deepest = depth; + if (walk2 > deepestWalk) + deepestWalk = walk2; + if (deepest > limit || deepestWalk > walkLimit) + return { nodes: deepest, walk: deepestWalk }; + if (Array.isArray(node)) { + for (const child of node) + stack.push({ node: child, depth, walk: walk2 + 1 }); + continue; + } + if (typeof node !== "object" || node === null) + continue; + const record = node; + for (const field of DEPTH_WALK_FIELDS) { + if (record[field] !== void 0) + stack.push({ node: record[field], depth: depth + 1, walk: walk2 + 1 }); + } + } + return { nodes: deepest, walk: deepestWalk }; +} +function fromAstJson(json, payloadByteLength) { + if (typeof json === "string") { + throw new TypeError("fromAstJson takes a parsed AST object, not a JSON string; call JSON.parse first"); + } + if (json?.type !== "document") + throw new AstJsonRootError(json?.type); + for (const field of ["children", "srcByteLength"]) { + if (!(field in json)) + throw new AstJsonRootFieldError(field); + } + const { nodes, walk: walk2 } = astJsonDepth(json, MAX_AST_JSON_DEPTH, MAX_AST_JSON_WALK); + if (nodes > MAX_AST_JSON_DEPTH) + throw new AstJsonDepthError(nodes); + if (walk2 > MAX_AST_JSON_WALK) + throw new AstJsonDepthError(walk2); + refuseUnknownNodeTypes(json, "", true); + refuseUnknownFields(json, ""); + refuseSchemaViolations(json, ""); + const children = []; + const footnoteDefs = {}; + const footnoteDefPos = {}; + let frontmatter; + for (const child of Array.isArray(json.children) ? json.children : []) { + if (child?.type === "frontmatter" && frontmatter === void 0) { + const node = child; + if (typeof node.format === "string" && typeof node.content === "string") { + frontmatter = { format: node.format, content: node.content }; + if (node.pos !== void 0) + frontmatter.pos = node.pos; + continue; + } + } + if (child?.type === "footnote") { + const node = child; + const label = typeof node.label === "string" ? node.label : node.id; + if (typeof label === "string" && Array.isArray(node.children)) { + if (ownValue(footnoteDefs, label) === void 0) { + setOwn(footnoteDefs, label, definitionListsFromWire(node.children)); + if (node.pos !== void 0) + setOwn(footnoteDefPos, label, node.pos); + } + continue; + } + continue; + } + children.push(definitionListsFromWire(child)); + } + const doc = { type: "document", children }; + if (frontmatter !== void 0) + doc.frontmatter = frontmatter; + if (Object.keys(footnoteDefs).length > 0) + doc.footnoteDefs = footnoteDefs; + if (Object.keys(footnoteDefPos).length > 0) + doc.footnoteDefPos = footnoteDefPos; + if (json.srcByteLength !== void 0) + doc.srcByteLength = json.srcByteLength; + clearUnbackedFootnoteNumbers(doc, footnoteDefs); + renumberCaptionsIfPublished(doc); + recordIngestPayloadLength(doc, payloadByteLength ?? measurePayload(json)); + return doc; +} +function measurePayload(json) { + try { + return utf8ByteLength(JSON.stringify(json)); + } catch { + return 0; + } +} +function renumberCaptionsIfPublished(doc) { + const bodies = doc.footnoteDefs ? Object.values(doc.footnoteDefs) : []; + if (!hasPublishedCaptionNumber(doc.children) && !bodies.some(hasPublishedCaptionNumber)) + return; + const counters = /* @__PURE__ */ new Map(); + numberCaptionsIn(doc.children, counters); + for (const body of bodies) + numberCaptionsIn(body, counters); +} +function hasPublishedCaptionNumber(blocks) { + const stack = [blocks]; + while (stack.length > 0) { + const cur = stack.pop(); + if (Array.isArray(cur)) { + for (const item2 of cur) + stack.push(item2); + continue; + } + if (cur === null || typeof cur !== "object") + continue; + const node = cur; + if (node.type === "caption_number" && node.n !== void 0) + return true; + for (const value of Object.values(cur)) { + if (value !== null && typeof value === "object") + stack.push(value); + } + } + return false; +} +function clearUnbackedFootnoteNumbers(doc, defs) { + const stack = [doc.children, Object.values(defs)]; + while (stack.length > 0) { + const cur = stack.pop(); + if (Array.isArray(cur)) { + for (const item2 of cur) + stack.push(item2); + continue; + } + if (cur === null || typeof cur !== "object") + continue; + const node = cur; + if (node.type === "footnote_ref" && node.number !== void 0) { + if (node.id === void 0 || ownValue(defs, node.id) === void 0) + delete node.number; + } + for (const value of Object.values(cur)) { + if (value !== null && typeof value === "object") + stack.push(value); + } + } +} +var CHILD_FIELDS, COLLECTED_DEFINITION_TYPES, AstJsonDepthError, AstJsonRootError, AstJsonRootFieldError, AstJsonUnknownNodeTypeError, AstJsonNodeTypeError, AstJsonUnknownFieldError, AstJsonSchemaError, AstJsonPartitionError, LEGACY_DEFINITION_ENTRY_FIELDS, LEGACY_TYPELESS_POSITIONS, LEGACY_RECORD_FIELDS, MAX_AST_JSON_DEPTH, MAX_AST_JSON_WALK, DEPTH_WALK_FIELDS; +var init_ast_json = __esm({ + "node_modules/@markup-carve/carve/dist/ast-json.js"() { + init_parse(); + init_heading_ids(); + init_definition_list_wire(); + init_wire_fields(); + init_own_property(); + init_abbr_budget(); + CHILD_FIELDS = ["children", "items", "rows", "cells", "inline", "content", "caption", "shortCaption", "title"]; + COLLECTED_DEFINITION_TYPES = /* @__PURE__ */ new Set([ + "link_reference_definition", + "footnote" + ]); + AstJsonDepthError = class extends Error { + depth; + constructor(depth) { + super(`AST nests ${depth} levels, deeper than the reader's cap of ${MAX_AST_JSON_DEPTH}`); + this.depth = depth; + this.name = "AstJsonDepthError"; + } + }; + AstJsonRootError = class extends Error { + found; + constructor(found) { + super(`AST root type ${JSON.stringify(found)} is not "document"; the root is fixed by PART 12 \xA77`); + this.found = found; + this.name = "AstJsonRootError"; + } + }; + AstJsonRootFieldError = class extends Error { + field; + constructor(field) { + super(`AST root is missing ${JSON.stringify(field)}; PART 12 \xA77 fixes the root at "type", "children" and "srcByteLength", and \xA712 refuses a root without one`); + this.field = field; + this.name = "AstJsonRootFieldError"; + } + }; + AstJsonUnknownNodeTypeError = class extends Error { + nodeType; + path; + constructor(nodeType, path8) { + super(`AST node at ${path8 === "" ? "the root" : path8} has type ${JSON.stringify(nodeType)}, which the schema does not name (PART 12 \xA712)`); + this.nodeType = nodeType; + this.path = path8; + this.name = "AstJsonUnknownNodeTypeError"; + } + }; + AstJsonNodeTypeError = class extends Error { + found; + path; + constructor(found, path8) { + const described = found === void 0 ? 'no "type"' : `a "type" of ${JSON.stringify(found) ?? typeof found}`; + super(`AST node at ${path8 === "" ? "the root" : path8} has ${described}; every node carries a string "type" the schema names (PART 12 \xA712)`); + this.found = found; + this.path = path8; + this.name = "AstJsonNodeTypeError"; + } + }; + AstJsonUnknownFieldError = class extends Error { + property; + path; + nodeType; + constructor(property, path8, nodeType) { + super(`AST node ${nodeType} at ${path8} carries ${JSON.stringify(property)}, which the schema does not name (PART 12 \xA711)`); + this.property = property; + this.path = path8; + this.nodeType = nodeType; + this.name = "AstJsonUnknownFieldError"; + } + }; + AstJsonSchemaError = class extends Error { + detail; + path; + constructor(detail, path8) { + super(`AST payload does not match the schema at ${path8 === "" ? "$" : path8}: ${detail}`); + this.detail = detail; + this.path = path8; + this.name = "AstJsonSchemaError"; + } + }; + AstJsonPartitionError = class extends Error { + counted; + rows; + path; + constructor(counted, rows, path8) { + super(`AST payload has a table.rowGroups that does not partition its rows at ${path8 === "" ? "$" : path8}: the head, bodies and foot account for ${counted} row${counted === 1 ? "" : "s"} of ${rows}`); + this.counted = counted; + this.rows = rows; + this.path = path8; + this.name = "AstJsonPartitionError"; + } + }; + LEGACY_DEFINITION_ENTRY_FIELDS = /* @__PURE__ */ new Set([ + "terms", + "definitions", + "definitionLines", + "definitionSpans" + ]); + LEGACY_TYPELESS_POSITIONS = /* @__PURE__ */ new Map([ + ["definition_list.items", ["terms", "definitions"]] + ]); + LEGACY_RECORD_FIELDS = ["terms", "definitions"]; + MAX_AST_JSON_DEPTH = MAX_NESTING_DEPTH * 3 + 32; + MAX_AST_JSON_WALK = MAX_AST_JSON_DEPTH * 2 + 32; + DEPTH_WALK_FIELDS = [.../* @__PURE__ */ new Set([...CHILD_FIELDS, "target"])]; + } +}); + +// node_modules/@markup-carve/carve/dist/coalesce-text-runs.js +function coalesceTextRuns(doc) { + visit(doc); + for (const blocks of Object.values(doc.footnoteDefs ?? {})) { + for (const block of blocks) + visit(block); + } + return doc; +} +function visit(node) { + if (!node || typeof node !== "object") + return; + for (const field of CHILD_FIELDS2) { + const value = node[field]; + if (!Array.isArray(value)) + continue; + for (const child of value) + visit(child); + const merged = mergeRun(value); + if (merged !== null) + node[field] = merged; + } +} +function mergeRun(nodes) { + let adjacent = false; + for (let i = 1; i < nodes.length; i++) { + if (nodes[i - 1]?.["type"] === "text" && nodes[i]?.["type"] === "text") { + adjacent = true; + break; + } + } + if (!adjacent) + return null; + const out = []; + let run = null; + let parts = []; + let pos; + const flush = () => { + if (run === null) + return; + if (parts.length > 1) { + run["value"] = parts.join(""); + run["pos"] = pos; + } + out.push(run); + run = null; + parts = []; + pos = void 0; + }; + for (const node of nodes) { + if (node?.["type"] === "text") { + if (run === null) { + run = node; + parts = [String(node["value"] ?? "")]; + pos = node["pos"]; + continue; + } + parts.push(String(node["value"] ?? "")); + pos = joinPos(pos, node["pos"]); + continue; + } + flush(); + out.push(node); + } + flush(); + return out; +} +function joinPos(left, right) { + if (!left || !right || typeof left !== "object" || typeof right !== "object") + return void 0; + const a = left; + const b = right; + if (a["endOffset"] !== b["startOffset"]) + return void 0; + return { + ...a, + endLine: b["endLine"], + endColumn: b["endColumn"], + endOffset: b["endOffset"] + }; +} +var CHILD_FIELDS2; +var init_coalesce_text_runs = __esm({ + "node_modules/@markup-carve/carve/dist/coalesce-text-runs.js"() { + CHILD_FIELDS2 = ["children", "items", "rows", "cells", "inline", "content", "caption", "title"]; + } +}); + +// node_modules/@markup-carve/carve/dist/source-layout.js +function toSourceLayout(source, ast) { + const points = [...source]; + const byteAt = (offset) => new TextEncoder().encode(points.slice(0, offset).join("")).length; + const nodes = []; + const escape = (key2) => key2.replace(/~/g, "~0").replace(/\//g, "~1"); + const walk2 = (value, path8) => { + if (!value || typeof value !== "object") + return; + const positioned = value; + const start = positioned.pos?.startOffset; + const end = positioned.pos?.endOffset; + if (Number.isInteger(start) && Number.isInteger(end)) { + nodes.push({ path: path8, startByte: byteAt(start), endByte: byteAt(end) }); + } + if (Array.isArray(value)) + value.forEach((child, index2) => walk2(child, `${path8}/${index2}`)); + else + Object.entries(value).forEach(([key2, child]) => { + if (key2 !== "pos") + walk2(child, `${path8}/${escape(key2)}`); + }); + }; + walk2(ast, ""); + nodes.sort((a, b) => a.path.localeCompare(b.path)); + const endings = source.match(/\r\n|\r|\n/g) ?? []; + const kinds = new Set(endings.map((x) => x === "\r\n" ? "crlf" : x === "\r" ? "cr" : "lf")); + const lineEndings = kinds.size === 0 ? "none" : kinds.size > 1 ? "mixed" : [...kinds][0]; + return { version: 1, encoding: "utf-8", source, lineEndings, bom: source.startsWith("\uFEFF"), nodes }; +} +var init_source_layout = __esm({ + "node_modules/@markup-carve/carve/dist/source-layout.js"() { + } +}); + +// node_modules/parse5/dist/common/unicode.js +function isSurrogate(cp) { + return cp >= 55296 && cp <= 57343; +} +function isSurrogatePair(cp) { + return cp >= 56320 && cp <= 57343; +} +function getSurrogatePairCodePoint(cp1, cp2) { + return (cp1 - 55296) * 1024 + 9216 + cp2; +} +function isControlCodePoint(cp) { + return cp !== 32 && cp !== 10 && cp !== 13 && cp !== 9 && cp !== 12 && cp >= 1 && cp <= 31 || cp >= 127 && cp <= 159; +} +function isUndefinedCodePoint(cp) { + return cp >= 64976 && cp <= 65007 || UNDEFINED_CODE_POINTS.has(cp); +} +var UNDEFINED_CODE_POINTS, REPLACEMENT_CHARACTER, CODE_POINTS, SEQUENCES; +var init_unicode = __esm({ + "node_modules/parse5/dist/common/unicode.js"() { + UNDEFINED_CODE_POINTS = /* @__PURE__ */ new Set([ + 65534, + 65535, + 131070, + 131071, + 196606, + 196607, + 262142, + 262143, + 327678, + 327679, + 393214, + 393215, + 458750, + 458751, + 524286, + 524287, + 589822, + 589823, + 655358, + 655359, + 720894, + 720895, + 786430, + 786431, + 851966, + 851967, + 917502, + 917503, + 983038, + 983039, + 1048574, + 1048575, + 1114110, + 1114111 + ]); + REPLACEMENT_CHARACTER = "\uFFFD"; + (function(CODE_POINTS2) { + CODE_POINTS2[CODE_POINTS2["EOF"] = -1] = "EOF"; + CODE_POINTS2[CODE_POINTS2["NULL"] = 0] = "NULL"; + CODE_POINTS2[CODE_POINTS2["TABULATION"] = 9] = "TABULATION"; + CODE_POINTS2[CODE_POINTS2["CARRIAGE_RETURN"] = 13] = "CARRIAGE_RETURN"; + CODE_POINTS2[CODE_POINTS2["LINE_FEED"] = 10] = "LINE_FEED"; + CODE_POINTS2[CODE_POINTS2["FORM_FEED"] = 12] = "FORM_FEED"; + CODE_POINTS2[CODE_POINTS2["SPACE"] = 32] = "SPACE"; + CODE_POINTS2[CODE_POINTS2["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK"; + CODE_POINTS2[CODE_POINTS2["QUOTATION_MARK"] = 34] = "QUOTATION_MARK"; + CODE_POINTS2[CODE_POINTS2["AMPERSAND"] = 38] = "AMPERSAND"; + CODE_POINTS2[CODE_POINTS2["APOSTROPHE"] = 39] = "APOSTROPHE"; + CODE_POINTS2[CODE_POINTS2["HYPHEN_MINUS"] = 45] = "HYPHEN_MINUS"; + CODE_POINTS2[CODE_POINTS2["SOLIDUS"] = 47] = "SOLIDUS"; + CODE_POINTS2[CODE_POINTS2["DIGIT_0"] = 48] = "DIGIT_0"; + CODE_POINTS2[CODE_POINTS2["DIGIT_9"] = 57] = "DIGIT_9"; + CODE_POINTS2[CODE_POINTS2["SEMICOLON"] = 59] = "SEMICOLON"; + CODE_POINTS2[CODE_POINTS2["LESS_THAN_SIGN"] = 60] = "LESS_THAN_SIGN"; + CODE_POINTS2[CODE_POINTS2["EQUALS_SIGN"] = 61] = "EQUALS_SIGN"; + CODE_POINTS2[CODE_POINTS2["GREATER_THAN_SIGN"] = 62] = "GREATER_THAN_SIGN"; + CODE_POINTS2[CODE_POINTS2["QUESTION_MARK"] = 63] = "QUESTION_MARK"; + CODE_POINTS2[CODE_POINTS2["LATIN_CAPITAL_A"] = 65] = "LATIN_CAPITAL_A"; + CODE_POINTS2[CODE_POINTS2["LATIN_CAPITAL_Z"] = 90] = "LATIN_CAPITAL_Z"; + CODE_POINTS2[CODE_POINTS2["RIGHT_SQUARE_BRACKET"] = 93] = "RIGHT_SQUARE_BRACKET"; + CODE_POINTS2[CODE_POINTS2["GRAVE_ACCENT"] = 96] = "GRAVE_ACCENT"; + CODE_POINTS2[CODE_POINTS2["LATIN_SMALL_A"] = 97] = "LATIN_SMALL_A"; + CODE_POINTS2[CODE_POINTS2["LATIN_SMALL_Z"] = 122] = "LATIN_SMALL_Z"; + })(CODE_POINTS || (CODE_POINTS = {})); + SEQUENCES = { + DASH_DASH: "--", + CDATA_START: "[CDATA[", + DOCTYPE: "doctype", + SCRIPT: "script", + PUBLIC: "public", + SYSTEM: "system" + }; + } +}); + +// node_modules/parse5/dist/common/error-codes.js +var ERR; +var init_error_codes = __esm({ + "node_modules/parse5/dist/common/error-codes.js"() { + (function(ERR2) { + ERR2["controlCharacterInInputStream"] = "control-character-in-input-stream"; + ERR2["noncharacterInInputStream"] = "noncharacter-in-input-stream"; + ERR2["surrogateInInputStream"] = "surrogate-in-input-stream"; + ERR2["nonVoidHtmlElementStartTagWithTrailingSolidus"] = "non-void-html-element-start-tag-with-trailing-solidus"; + ERR2["endTagWithAttributes"] = "end-tag-with-attributes"; + ERR2["endTagWithTrailingSolidus"] = "end-tag-with-trailing-solidus"; + ERR2["unexpectedSolidusInTag"] = "unexpected-solidus-in-tag"; + ERR2["unexpectedNullCharacter"] = "unexpected-null-character"; + ERR2["unexpectedQuestionMarkInsteadOfTagName"] = "unexpected-question-mark-instead-of-tag-name"; + ERR2["invalidFirstCharacterOfTagName"] = "invalid-first-character-of-tag-name"; + ERR2["unexpectedEqualsSignBeforeAttributeName"] = "unexpected-equals-sign-before-attribute-name"; + ERR2["missingEndTagName"] = "missing-end-tag-name"; + ERR2["unexpectedCharacterInAttributeName"] = "unexpected-character-in-attribute-name"; + ERR2["unknownNamedCharacterReference"] = "unknown-named-character-reference"; + ERR2["missingSemicolonAfterCharacterReference"] = "missing-semicolon-after-character-reference"; + ERR2["unexpectedCharacterAfterDoctypeSystemIdentifier"] = "unexpected-character-after-doctype-system-identifier"; + ERR2["unexpectedCharacterInUnquotedAttributeValue"] = "unexpected-character-in-unquoted-attribute-value"; + ERR2["eofBeforeTagName"] = "eof-before-tag-name"; + ERR2["eofInTag"] = "eof-in-tag"; + ERR2["missingAttributeValue"] = "missing-attribute-value"; + ERR2["missingWhitespaceBetweenAttributes"] = "missing-whitespace-between-attributes"; + ERR2["missingWhitespaceAfterDoctypePublicKeyword"] = "missing-whitespace-after-doctype-public-keyword"; + ERR2["missingWhitespaceBetweenDoctypePublicAndSystemIdentifiers"] = "missing-whitespace-between-doctype-public-and-system-identifiers"; + ERR2["missingWhitespaceAfterDoctypeSystemKeyword"] = "missing-whitespace-after-doctype-system-keyword"; + ERR2["missingQuoteBeforeDoctypePublicIdentifier"] = "missing-quote-before-doctype-public-identifier"; + ERR2["missingQuoteBeforeDoctypeSystemIdentifier"] = "missing-quote-before-doctype-system-identifier"; + ERR2["missingDoctypePublicIdentifier"] = "missing-doctype-public-identifier"; + ERR2["missingDoctypeSystemIdentifier"] = "missing-doctype-system-identifier"; + ERR2["abruptDoctypePublicIdentifier"] = "abrupt-doctype-public-identifier"; + ERR2["abruptDoctypeSystemIdentifier"] = "abrupt-doctype-system-identifier"; + ERR2["cdataInHtmlContent"] = "cdata-in-html-content"; + ERR2["incorrectlyOpenedComment"] = "incorrectly-opened-comment"; + ERR2["eofInScriptHtmlCommentLikeText"] = "eof-in-script-html-comment-like-text"; + ERR2["eofInDoctype"] = "eof-in-doctype"; + ERR2["nestedComment"] = "nested-comment"; + ERR2["abruptClosingOfEmptyComment"] = "abrupt-closing-of-empty-comment"; + ERR2["eofInComment"] = "eof-in-comment"; + ERR2["incorrectlyClosedComment"] = "incorrectly-closed-comment"; + ERR2["eofInCdata"] = "eof-in-cdata"; + ERR2["absenceOfDigitsInNumericCharacterReference"] = "absence-of-digits-in-numeric-character-reference"; + ERR2["nullCharacterReference"] = "null-character-reference"; + ERR2["surrogateCharacterReference"] = "surrogate-character-reference"; + ERR2["characterReferenceOutsideUnicodeRange"] = "character-reference-outside-unicode-range"; + ERR2["controlCharacterReference"] = "control-character-reference"; + ERR2["noncharacterCharacterReference"] = "noncharacter-character-reference"; + ERR2["missingWhitespaceBeforeDoctypeName"] = "missing-whitespace-before-doctype-name"; + ERR2["missingDoctypeName"] = "missing-doctype-name"; + ERR2["invalidCharacterSequenceAfterDoctypeName"] = "invalid-character-sequence-after-doctype-name"; + ERR2["duplicateAttribute"] = "duplicate-attribute"; + ERR2["nonConformingDoctype"] = "non-conforming-doctype"; + ERR2["missingDoctype"] = "missing-doctype"; + ERR2["misplacedDoctype"] = "misplaced-doctype"; + ERR2["endTagWithoutMatchingOpenElement"] = "end-tag-without-matching-open-element"; + ERR2["closingOfElementWithOpenChildElements"] = "closing-of-element-with-open-child-elements"; + ERR2["disallowedContentInNoscriptInHead"] = "disallowed-content-in-noscript-in-head"; + ERR2["openElementsLeftAfterEof"] = "open-elements-left-after-eof"; + ERR2["abandonedHeadElementChild"] = "abandoned-head-element-child"; + ERR2["misplacedStartTagForHeadElement"] = "misplaced-start-tag-for-head-element"; + ERR2["nestedNoscriptInHead"] = "nested-noscript-in-head"; + ERR2["eofInElementThatCanContainOnlyText"] = "eof-in-element-that-can-contain-only-text"; + })(ERR || (ERR = {})); + } +}); + +// node_modules/parse5/dist/tokenizer/preprocessor.js +var DEFAULT_BUFFER_WATERLINE, Preprocessor; +var init_preprocessor = __esm({ + "node_modules/parse5/dist/tokenizer/preprocessor.js"() { + init_unicode(); + init_error_codes(); + DEFAULT_BUFFER_WATERLINE = 1 << 16; + Preprocessor = class { + constructor(handler) { + this.handler = handler; + this.html = ""; + this.pos = -1; + this.lastGapPos = -2; + this.gapStack = []; + this.skipNextNewLine = false; + this.lastChunkWritten = false; + this.endOfChunkHit = false; + this.bufferWaterline = DEFAULT_BUFFER_WATERLINE; + this.isEol = false; + this.lineStartPos = 0; + this.droppedBufferSize = 0; + this.line = 1; + this.lastErrOffset = -1; + } + /** The column on the current line. If we just saw a gap (eg. a surrogate pair), return the index before. */ + get col() { + return this.pos - this.lineStartPos + Number(this.lastGapPos !== this.pos); + } + get offset() { + return this.droppedBufferSize + this.pos; + } + getError(code, cpOffset) { + const { line: line2, col, offset } = this; + const startCol = col + cpOffset; + const startOffset = offset + cpOffset; + return { + code, + startLine: line2, + endLine: line2, + startCol, + endCol: startCol, + startOffset, + endOffset: startOffset + }; + } + _err(code) { + if (this.handler.onParseError && this.lastErrOffset !== this.offset) { + this.lastErrOffset = this.offset; + this.handler.onParseError(this.getError(code, 0)); + } + } + _addGap() { + this.gapStack.push(this.lastGapPos); + this.lastGapPos = this.pos; + } + _processSurrogate(cp) { + if (this.pos !== this.html.length - 1) { + const nextCp = this.html.charCodeAt(this.pos + 1); + if (isSurrogatePair(nextCp)) { + this.pos++; + this._addGap(); + return getSurrogatePairCodePoint(cp, nextCp); + } + } else if (!this.lastChunkWritten) { + this.endOfChunkHit = true; + return CODE_POINTS.EOF; + } + this._err(ERR.surrogateInInputStream); + return cp; + } + willDropParsedChunk() { + return this.pos > this.bufferWaterline; + } + dropParsedChunk() { + if (this.willDropParsedChunk()) { + this.html = this.html.substring(this.pos); + this.lineStartPos -= this.pos; + this.droppedBufferSize += this.pos; + this.pos = 0; + this.lastGapPos = -2; + this.gapStack.length = 0; + } + } + write(chunk, isLastChunk) { + if (this.html.length > 0) { + this.html += chunk; + } else { + this.html = chunk; + } + this.endOfChunkHit = false; + this.lastChunkWritten = isLastChunk; + } + insertHtmlAtCurrentPos(chunk) { + this.html = this.html.substring(0, this.pos + 1) + chunk + this.html.substring(this.pos + 1); + this.endOfChunkHit = false; + } + startsWith(pattern, caseSensitive) { + if (this.pos + pattern.length > this.html.length) { + this.endOfChunkHit = !this.lastChunkWritten; + return false; + } + if (caseSensitive) { + return this.html.startsWith(pattern, this.pos); + } + for (let i = 0; i < pattern.length; i++) { + const cp = this.html.charCodeAt(this.pos + i) | 32; + if (cp !== pattern.charCodeAt(i)) { + return false; + } + } + return true; + } + peek(offset) { + const pos = this.pos + offset; + if (pos >= this.html.length) { + this.endOfChunkHit = !this.lastChunkWritten; + return CODE_POINTS.EOF; + } + const code = this.html.charCodeAt(pos); + return code === CODE_POINTS.CARRIAGE_RETURN ? CODE_POINTS.LINE_FEED : code; + } + advance() { + this.pos++; + if (this.isEol) { + this.isEol = false; + this.line++; + this.lineStartPos = this.pos; + } + if (this.pos >= this.html.length) { + this.endOfChunkHit = !this.lastChunkWritten; + return CODE_POINTS.EOF; + } + let cp = this.html.charCodeAt(this.pos); + if (cp === CODE_POINTS.CARRIAGE_RETURN) { + this.isEol = true; + this.skipNextNewLine = true; + return CODE_POINTS.LINE_FEED; + } + if (cp === CODE_POINTS.LINE_FEED) { + this.isEol = true; + if (this.skipNextNewLine) { + this.line--; + this.skipNextNewLine = false; + this._addGap(); + return this.advance(); + } + } + this.skipNextNewLine = false; + if (isSurrogate(cp)) { + cp = this._processSurrogate(cp); + } + const isCommonValidRange = this.handler.onParseError === null || cp > 31 && cp < 127 || cp === CODE_POINTS.LINE_FEED || cp === CODE_POINTS.CARRIAGE_RETURN || cp > 159 && cp < 64976; + if (!isCommonValidRange) { + this._checkForProblematicCharacters(cp); + } + return cp; + } + _checkForProblematicCharacters(cp) { + if (isControlCodePoint(cp)) { + this._err(ERR.controlCharacterInInputStream); + } else if (isUndefinedCodePoint(cp)) { + this._err(ERR.noncharacterInInputStream); + } + } + retreat(count) { + this.pos -= count; + while (this.pos < this.lastGapPos) { + this.lastGapPos = this.gapStack.pop(); + this.pos--; + } + this.isEol = false; + } + }; + } +}); + +// node_modules/parse5/dist/common/token.js +function getTokenAttr(token, attrName) { + for (let i = token.attrs.length - 1; i >= 0; i--) { + if (token.attrs[i].name === attrName) { + return token.attrs[i].value; + } + } + return null; +} +var TokenType; +var init_token = __esm({ + "node_modules/parse5/dist/common/token.js"() { + (function(TokenType2) { + TokenType2[TokenType2["CHARACTER"] = 0] = "CHARACTER"; + TokenType2[TokenType2["NULL_CHARACTER"] = 1] = "NULL_CHARACTER"; + TokenType2[TokenType2["WHITESPACE_CHARACTER"] = 2] = "WHITESPACE_CHARACTER"; + TokenType2[TokenType2["START_TAG"] = 3] = "START_TAG"; + TokenType2[TokenType2["END_TAG"] = 4] = "END_TAG"; + TokenType2[TokenType2["COMMENT"] = 5] = "COMMENT"; + TokenType2[TokenType2["DOCTYPE"] = 6] = "DOCTYPE"; + TokenType2[TokenType2["EOF"] = 7] = "EOF"; + TokenType2[TokenType2["HIBERNATION"] = 8] = "HIBERNATION"; + })(TokenType || (TokenType = {})); + } +}); + +// node_modules/entities/dist/esm/generated/decode-data-html.js +var htmlDecodeTree; +var init_decode_data_html = __esm({ + "node_modules/entities/dist/esm/generated/decode-data-html.js"() { + htmlDecodeTree = /* @__PURE__ */ new Uint16Array( + // prettier-ignore + /* @__PURE__ */ '\u1D41<\xD5\u0131\u028A\u049D\u057B\u05D0\u0675\u06DE\u07A2\u07D6\u080F\u0A4A\u0A91\u0DA1\u0E6D\u0F09\u0F26\u10CA\u1228\u12E1\u1415\u149D\u14C3\u14DF\u1525\0\0\0\0\0\0\u156B\u16CD\u198D\u1C12\u1DDD\u1F7E\u2060\u21B0\u228D\u23C0\u23FB\u2442\u2824\u2912\u2D08\u2E48\u2FCE\u3016\u32BA\u3639\u37AC\u38FE\u3A28\u3A71\u3AE0\u3B2E\u0800EMabcfglmnoprstu\\bfms\x7F\x84\x8B\x90\x95\x98\xA6\xB3\xB9\xC8\xCFlig\u803B\xC6\u40C6P\u803B&\u4026cute\u803B\xC1\u40C1reve;\u4102\u0100iyx}rc\u803B\xC2\u40C2;\u4410r;\uC000\u{1D504}rave\u803B\xC0\u40C0pha;\u4391acr;\u4100d;\u6A53\u0100gp\x9D\xA1on;\u4104f;\uC000\u{1D538}plyFunction;\u6061ing\u803B\xC5\u40C5\u0100cs\xBE\xC3r;\uC000\u{1D49C}ign;\u6254ilde\u803B\xC3\u40C3ml\u803B\xC4\u40C4\u0400aceforsu\xE5\xFB\xFE\u0117\u011C\u0122\u0127\u012A\u0100cr\xEA\xF2kslash;\u6216\u0176\xF6\xF8;\u6AE7ed;\u6306y;\u4411\u0180crt\u0105\u010B\u0114ause;\u6235noullis;\u612Ca;\u4392r;\uC000\u{1D505}pf;\uC000\u{1D539}eve;\u42D8c\xF2\u0113mpeq;\u624E\u0700HOacdefhilorsu\u014D\u0151\u0156\u0180\u019E\u01A2\u01B5\u01B7\u01BA\u01DC\u0215\u0273\u0278\u027Ecy;\u4427PY\u803B\xA9\u40A9\u0180cpy\u015D\u0162\u017Aute;\u4106\u0100;i\u0167\u0168\u62D2talDifferentialD;\u6145leys;\u612D\u0200aeio\u0189\u018E\u0194\u0198ron;\u410Cdil\u803B\xC7\u40C7rc;\u4108nint;\u6230ot;\u410A\u0100dn\u01A7\u01ADilla;\u40B8terDot;\u40B7\xF2\u017Fi;\u43A7rcle\u0200DMPT\u01C7\u01CB\u01D1\u01D6ot;\u6299inus;\u6296lus;\u6295imes;\u6297o\u0100cs\u01E2\u01F8kwiseContourIntegral;\u6232eCurly\u0100DQ\u0203\u020FoubleQuote;\u601Duote;\u6019\u0200lnpu\u021E\u0228\u0247\u0255on\u0100;e\u0225\u0226\u6237;\u6A74\u0180git\u022F\u0236\u023Aruent;\u6261nt;\u622FourIntegral;\u622E\u0100fr\u024C\u024E;\u6102oduct;\u6210nterClockwiseContourIntegral;\u6233oss;\u6A2Fcr;\uC000\u{1D49E}p\u0100;C\u0284\u0285\u62D3ap;\u624D\u0580DJSZacefios\u02A0\u02AC\u02B0\u02B4\u02B8\u02CB\u02D7\u02E1\u02E6\u0333\u048D\u0100;o\u0179\u02A5trahd;\u6911cy;\u4402cy;\u4405cy;\u440F\u0180grs\u02BF\u02C4\u02C7ger;\u6021r;\u61A1hv;\u6AE4\u0100ay\u02D0\u02D5ron;\u410E;\u4414l\u0100;t\u02DD\u02DE\u6207a;\u4394r;\uC000\u{1D507}\u0100af\u02EB\u0327\u0100cm\u02F0\u0322ritical\u0200ADGT\u0300\u0306\u0316\u031Ccute;\u40B4o\u0174\u030B\u030D;\u42D9bleAcute;\u42DDrave;\u4060ilde;\u42DCond;\u62C4ferentialD;\u6146\u0470\u033D\0\0\0\u0342\u0354\0\u0405f;\uC000\u{1D53B}\u0180;DE\u0348\u0349\u034D\u40A8ot;\u60DCqual;\u6250ble\u0300CDLRUV\u0363\u0372\u0382\u03CF\u03E2\u03F8ontourIntegra\xEC\u0239o\u0274\u0379\0\0\u037B\xBB\u0349nArrow;\u61D3\u0100eo\u0387\u03A4ft\u0180ART\u0390\u0396\u03A1rrow;\u61D0ightArrow;\u61D4e\xE5\u02CAng\u0100LR\u03AB\u03C4eft\u0100AR\u03B3\u03B9rrow;\u67F8ightArrow;\u67FAightArrow;\u67F9ight\u0100AT\u03D8\u03DErrow;\u61D2ee;\u62A8p\u0241\u03E9\0\0\u03EFrrow;\u61D1ownArrow;\u61D5erticalBar;\u6225n\u0300ABLRTa\u0412\u042A\u0430\u045E\u047F\u037Crrow\u0180;BU\u041D\u041E\u0422\u6193ar;\u6913pArrow;\u61F5reve;\u4311eft\u02D2\u043A\0\u0446\0\u0450ightVector;\u6950eeVector;\u695Eector\u0100;B\u0459\u045A\u61BDar;\u6956ight\u01D4\u0467\0\u0471eeVector;\u695Fector\u0100;B\u047A\u047B\u61C1ar;\u6957ee\u0100;A\u0486\u0487\u62A4rrow;\u61A7\u0100ct\u0492\u0497r;\uC000\u{1D49F}rok;\u4110\u0800NTacdfglmopqstux\u04BD\u04C0\u04C4\u04CB\u04DE\u04E2\u04E7\u04EE\u04F5\u0521\u052F\u0536\u0552\u055D\u0560\u0565G;\u414AH\u803B\xD0\u40D0cute\u803B\xC9\u40C9\u0180aiy\u04D2\u04D7\u04DCron;\u411Arc\u803B\xCA\u40CA;\u442Dot;\u4116r;\uC000\u{1D508}rave\u803B\xC8\u40C8ement;\u6208\u0100ap\u04FA\u04FEcr;\u4112ty\u0253\u0506\0\0\u0512mallSquare;\u65FBerySmallSquare;\u65AB\u0100gp\u0526\u052Aon;\u4118f;\uC000\u{1D53C}silon;\u4395u\u0100ai\u053C\u0549l\u0100;T\u0542\u0543\u6A75ilde;\u6242librium;\u61CC\u0100ci\u0557\u055Ar;\u6130m;\u6A73a;\u4397ml\u803B\xCB\u40CB\u0100ip\u056A\u056Fsts;\u6203onentialE;\u6147\u0280cfios\u0585\u0588\u058D\u05B2\u05CCy;\u4424r;\uC000\u{1D509}lled\u0253\u0597\0\0\u05A3mallSquare;\u65FCerySmallSquare;\u65AA\u0370\u05BA\0\u05BF\0\0\u05C4f;\uC000\u{1D53D}All;\u6200riertrf;\u6131c\xF2\u05CB\u0600JTabcdfgorst\u05E8\u05EC\u05EF\u05FA\u0600\u0612\u0616\u061B\u061D\u0623\u066C\u0672cy;\u4403\u803B>\u403Emma\u0100;d\u05F7\u05F8\u4393;\u43DCreve;\u411E\u0180eiy\u0607\u060C\u0610dil;\u4122rc;\u411C;\u4413ot;\u4120r;\uC000\u{1D50A};\u62D9pf;\uC000\u{1D53E}eater\u0300EFGLST\u0635\u0644\u064E\u0656\u065B\u0666qual\u0100;L\u063E\u063F\u6265ess;\u62DBullEqual;\u6267reater;\u6AA2ess;\u6277lantEqual;\u6A7Eilde;\u6273cr;\uC000\u{1D4A2};\u626B\u0400Aacfiosu\u0685\u068B\u0696\u069B\u069E\u06AA\u06BE\u06CARDcy;\u442A\u0100ct\u0690\u0694ek;\u42C7;\u405Eirc;\u4124r;\u610ClbertSpace;\u610B\u01F0\u06AF\0\u06B2f;\u610DizontalLine;\u6500\u0100ct\u06C3\u06C5\xF2\u06A9rok;\u4126mp\u0144\u06D0\u06D8ownHum\xF0\u012Fqual;\u624F\u0700EJOacdfgmnostu\u06FA\u06FE\u0703\u0707\u070E\u071A\u071E\u0721\u0728\u0744\u0778\u078B\u078F\u0795cy;\u4415lig;\u4132cy;\u4401cute\u803B\xCD\u40CD\u0100iy\u0713\u0718rc\u803B\xCE\u40CE;\u4418ot;\u4130r;\u6111rave\u803B\xCC\u40CC\u0180;ap\u0720\u072F\u073F\u0100cg\u0734\u0737r;\u412AinaryI;\u6148lie\xF3\u03DD\u01F4\u0749\0\u0762\u0100;e\u074D\u074E\u622C\u0100gr\u0753\u0758ral;\u622Bsection;\u62C2isible\u0100CT\u076C\u0772omma;\u6063imes;\u6062\u0180gpt\u077F\u0783\u0788on;\u412Ef;\uC000\u{1D540}a;\u4399cr;\u6110ilde;\u4128\u01EB\u079A\0\u079Ecy;\u4406l\u803B\xCF\u40CF\u0280cfosu\u07AC\u07B7\u07BC\u07C2\u07D0\u0100iy\u07B1\u07B5rc;\u4134;\u4419r;\uC000\u{1D50D}pf;\uC000\u{1D541}\u01E3\u07C7\0\u07CCr;\uC000\u{1D4A5}rcy;\u4408kcy;\u4404\u0380HJacfos\u07E4\u07E8\u07EC\u07F1\u07FD\u0802\u0808cy;\u4425cy;\u440Cppa;\u439A\u0100ey\u07F6\u07FBdil;\u4136;\u441Ar;\uC000\u{1D50E}pf;\uC000\u{1D542}cr;\uC000\u{1D4A6}\u0580JTaceflmost\u0825\u0829\u082C\u0850\u0863\u09B3\u09B8\u09C7\u09CD\u0A37\u0A47cy;\u4409\u803B<\u403C\u0280cmnpr\u0837\u083C\u0841\u0844\u084Dute;\u4139bda;\u439Bg;\u67EAlacetrf;\u6112r;\u619E\u0180aey\u0857\u085C\u0861ron;\u413Ddil;\u413B;\u441B\u0100fs\u0868\u0970t\u0500ACDFRTUVar\u087E\u08A9\u08B1\u08E0\u08E6\u08FC\u092F\u095B\u0390\u096A\u0100nr\u0883\u088FgleBracket;\u67E8row\u0180;BR\u0899\u089A\u089E\u6190ar;\u61E4ightArrow;\u61C6eiling;\u6308o\u01F5\u08B7\0\u08C3bleBracket;\u67E6n\u01D4\u08C8\0\u08D2eeVector;\u6961ector\u0100;B\u08DB\u08DC\u61C3ar;\u6959loor;\u630Aight\u0100AV\u08EF\u08F5rrow;\u6194ector;\u694E\u0100er\u0901\u0917e\u0180;AV\u0909\u090A\u0910\u62A3rrow;\u61A4ector;\u695Aiangle\u0180;BE\u0924\u0925\u0929\u62B2ar;\u69CFqual;\u62B4p\u0180DTV\u0937\u0942\u094CownVector;\u6951eeVector;\u6960ector\u0100;B\u0956\u0957\u61BFar;\u6958ector\u0100;B\u0965\u0966\u61BCar;\u6952ight\xE1\u039Cs\u0300EFGLST\u097E\u098B\u0995\u099D\u09A2\u09ADqualGreater;\u62DAullEqual;\u6266reater;\u6276ess;\u6AA1lantEqual;\u6A7Dilde;\u6272r;\uC000\u{1D50F}\u0100;e\u09BD\u09BE\u62D8ftarrow;\u61DAidot;\u413F\u0180npw\u09D4\u0A16\u0A1Bg\u0200LRlr\u09DE\u09F7\u0A02\u0A10eft\u0100AR\u09E6\u09ECrrow;\u67F5ightArrow;\u67F7ightArrow;\u67F6eft\u0100ar\u03B3\u0A0Aight\xE1\u03BFight\xE1\u03CAf;\uC000\u{1D543}er\u0100LR\u0A22\u0A2CeftArrow;\u6199ightArrow;\u6198\u0180cht\u0A3E\u0A40\u0A42\xF2\u084C;\u61B0rok;\u4141;\u626A\u0400acefiosu\u0A5A\u0A5D\u0A60\u0A77\u0A7C\u0A85\u0A8B\u0A8Ep;\u6905y;\u441C\u0100dl\u0A65\u0A6FiumSpace;\u605Flintrf;\u6133r;\uC000\u{1D510}nusPlus;\u6213pf;\uC000\u{1D544}c\xF2\u0A76;\u439C\u0480Jacefostu\u0AA3\u0AA7\u0AAD\u0AC0\u0B14\u0B19\u0D91\u0D97\u0D9Ecy;\u440Acute;\u4143\u0180aey\u0AB4\u0AB9\u0ABEron;\u4147dil;\u4145;\u441D\u0180gsw\u0AC7\u0AF0\u0B0Eative\u0180MTV\u0AD3\u0ADF\u0AE8ediumSpace;\u600Bhi\u0100cn\u0AE6\u0AD8\xEB\u0AD9eryThi\xEE\u0AD9ted\u0100GL\u0AF8\u0B06reaterGreate\xF2\u0673essLes\xF3\u0A48Line;\u400Ar;\uC000\u{1D511}\u0200Bnpt\u0B22\u0B28\u0B37\u0B3Areak;\u6060BreakingSpace;\u40A0f;\u6115\u0680;CDEGHLNPRSTV\u0B55\u0B56\u0B6A\u0B7C\u0BA1\u0BEB\u0C04\u0C5E\u0C84\u0CA6\u0CD8\u0D61\u0D85\u6AEC\u0100ou\u0B5B\u0B64ngruent;\u6262pCap;\u626DoubleVerticalBar;\u6226\u0180lqx\u0B83\u0B8A\u0B9Bement;\u6209ual\u0100;T\u0B92\u0B93\u6260ilde;\uC000\u2242\u0338ists;\u6204reater\u0380;EFGLST\u0BB6\u0BB7\u0BBD\u0BC9\u0BD3\u0BD8\u0BE5\u626Fqual;\u6271ullEqual;\uC000\u2267\u0338reater;\uC000\u226B\u0338ess;\u6279lantEqual;\uC000\u2A7E\u0338ilde;\u6275ump\u0144\u0BF2\u0BFDownHump;\uC000\u224E\u0338qual;\uC000\u224F\u0338e\u0100fs\u0C0A\u0C27tTriangle\u0180;BE\u0C1A\u0C1B\u0C21\u62EAar;\uC000\u29CF\u0338qual;\u62ECs\u0300;EGLST\u0C35\u0C36\u0C3C\u0C44\u0C4B\u0C58\u626Equal;\u6270reater;\u6278ess;\uC000\u226A\u0338lantEqual;\uC000\u2A7D\u0338ilde;\u6274ested\u0100GL\u0C68\u0C79reaterGreater;\uC000\u2AA2\u0338essLess;\uC000\u2AA1\u0338recedes\u0180;ES\u0C92\u0C93\u0C9B\u6280qual;\uC000\u2AAF\u0338lantEqual;\u62E0\u0100ei\u0CAB\u0CB9verseElement;\u620CghtTriangle\u0180;BE\u0CCB\u0CCC\u0CD2\u62EBar;\uC000\u29D0\u0338qual;\u62ED\u0100qu\u0CDD\u0D0CuareSu\u0100bp\u0CE8\u0CF9set\u0100;E\u0CF0\u0CF3\uC000\u228F\u0338qual;\u62E2erset\u0100;E\u0D03\u0D06\uC000\u2290\u0338qual;\u62E3\u0180bcp\u0D13\u0D24\u0D4Eset\u0100;E\u0D1B\u0D1E\uC000\u2282\u20D2qual;\u6288ceeds\u0200;EST\u0D32\u0D33\u0D3B\u0D46\u6281qual;\uC000\u2AB0\u0338lantEqual;\u62E1ilde;\uC000\u227F\u0338erset\u0100;E\u0D58\u0D5B\uC000\u2283\u20D2qual;\u6289ilde\u0200;EFT\u0D6E\u0D6F\u0D75\u0D7F\u6241qual;\u6244ullEqual;\u6247ilde;\u6249erticalBar;\u6224cr;\uC000\u{1D4A9}ilde\u803B\xD1\u40D1;\u439D\u0700Eacdfgmoprstuv\u0DBD\u0DC2\u0DC9\u0DD5\u0DDB\u0DE0\u0DE7\u0DFC\u0E02\u0E20\u0E22\u0E32\u0E3F\u0E44lig;\u4152cute\u803B\xD3\u40D3\u0100iy\u0DCE\u0DD3rc\u803B\xD4\u40D4;\u441Eblac;\u4150r;\uC000\u{1D512}rave\u803B\xD2\u40D2\u0180aei\u0DEE\u0DF2\u0DF6cr;\u414Cga;\u43A9cron;\u439Fpf;\uC000\u{1D546}enCurly\u0100DQ\u0E0E\u0E1AoubleQuote;\u601Cuote;\u6018;\u6A54\u0100cl\u0E27\u0E2Cr;\uC000\u{1D4AA}ash\u803B\xD8\u40D8i\u016C\u0E37\u0E3Cde\u803B\xD5\u40D5es;\u6A37ml\u803B\xD6\u40D6er\u0100BP\u0E4B\u0E60\u0100ar\u0E50\u0E53r;\u603Eac\u0100ek\u0E5A\u0E5C;\u63DEet;\u63B4arenthesis;\u63DC\u0480acfhilors\u0E7F\u0E87\u0E8A\u0E8F\u0E92\u0E94\u0E9D\u0EB0\u0EFCrtialD;\u6202y;\u441Fr;\uC000\u{1D513}i;\u43A6;\u43A0usMinus;\u40B1\u0100ip\u0EA2\u0EADncareplan\xE5\u069Df;\u6119\u0200;eio\u0EB9\u0EBA\u0EE0\u0EE4\u6ABBcedes\u0200;EST\u0EC8\u0EC9\u0ECF\u0EDA\u627Aqual;\u6AAFlantEqual;\u627Cilde;\u627Eme;\u6033\u0100dp\u0EE9\u0EEEuct;\u620Fortion\u0100;a\u0225\u0EF9l;\u621D\u0100ci\u0F01\u0F06r;\uC000\u{1D4AB};\u43A8\u0200Ufos\u0F11\u0F16\u0F1B\u0F1FOT\u803B"\u4022r;\uC000\u{1D514}pf;\u611Acr;\uC000\u{1D4AC}\u0600BEacefhiorsu\u0F3E\u0F43\u0F47\u0F60\u0F73\u0FA7\u0FAA\u0FAD\u1096\u10A9\u10B4\u10BEarr;\u6910G\u803B\xAE\u40AE\u0180cnr\u0F4E\u0F53\u0F56ute;\u4154g;\u67EBr\u0100;t\u0F5C\u0F5D\u61A0l;\u6916\u0180aey\u0F67\u0F6C\u0F71ron;\u4158dil;\u4156;\u4420\u0100;v\u0F78\u0F79\u611Cerse\u0100EU\u0F82\u0F99\u0100lq\u0F87\u0F8Eement;\u620Builibrium;\u61CBpEquilibrium;\u696Fr\xBB\u0F79o;\u43A1ght\u0400ACDFTUVa\u0FC1\u0FEB\u0FF3\u1022\u1028\u105B\u1087\u03D8\u0100nr\u0FC6\u0FD2gleBracket;\u67E9row\u0180;BL\u0FDC\u0FDD\u0FE1\u6192ar;\u61E5eftArrow;\u61C4eiling;\u6309o\u01F5\u0FF9\0\u1005bleBracket;\u67E7n\u01D4\u100A\0\u1014eeVector;\u695Dector\u0100;B\u101D\u101E\u61C2ar;\u6955loor;\u630B\u0100er\u102D\u1043e\u0180;AV\u1035\u1036\u103C\u62A2rrow;\u61A6ector;\u695Biangle\u0180;BE\u1050\u1051\u1055\u62B3ar;\u69D0qual;\u62B5p\u0180DTV\u1063\u106E\u1078ownVector;\u694FeeVector;\u695Cector\u0100;B\u1082\u1083\u61BEar;\u6954ector\u0100;B\u1091\u1092\u61C0ar;\u6953\u0100pu\u109B\u109Ef;\u611DndImplies;\u6970ightarrow;\u61DB\u0100ch\u10B9\u10BCr;\u611B;\u61B1leDelayed;\u69F4\u0680HOacfhimoqstu\u10E4\u10F1\u10F7\u10FD\u1119\u111E\u1151\u1156\u1161\u1167\u11B5\u11BB\u11BF\u0100Cc\u10E9\u10EEHcy;\u4429y;\u4428FTcy;\u442Ccute;\u415A\u0280;aeiy\u1108\u1109\u110E\u1113\u1117\u6ABCron;\u4160dil;\u415Erc;\u415C;\u4421r;\uC000\u{1D516}ort\u0200DLRU\u112A\u1134\u113E\u1149ownArrow\xBB\u041EeftArrow\xBB\u089AightArrow\xBB\u0FDDpArrow;\u6191gma;\u43A3allCircle;\u6218pf;\uC000\u{1D54A}\u0272\u116D\0\0\u1170t;\u621Aare\u0200;ISU\u117B\u117C\u1189\u11AF\u65A1ntersection;\u6293u\u0100bp\u118F\u119Eset\u0100;E\u1197\u1198\u628Fqual;\u6291erset\u0100;E\u11A8\u11A9\u6290qual;\u6292nion;\u6294cr;\uC000\u{1D4AE}ar;\u62C6\u0200bcmp\u11C8\u11DB\u1209\u120B\u0100;s\u11CD\u11CE\u62D0et\u0100;E\u11CD\u11D5qual;\u6286\u0100ch\u11E0\u1205eeds\u0200;EST\u11ED\u11EE\u11F4\u11FF\u627Bqual;\u6AB0lantEqual;\u627Dilde;\u627FTh\xE1\u0F8C;\u6211\u0180;es\u1212\u1213\u1223\u62D1rset\u0100;E\u121C\u121D\u6283qual;\u6287et\xBB\u1213\u0580HRSacfhiors\u123E\u1244\u1249\u1255\u125E\u1271\u1276\u129F\u12C2\u12C8\u12D1ORN\u803B\xDE\u40DEADE;\u6122\u0100Hc\u124E\u1252cy;\u440By;\u4426\u0100bu\u125A\u125C;\u4009;\u43A4\u0180aey\u1265\u126A\u126Fron;\u4164dil;\u4162;\u4422r;\uC000\u{1D517}\u0100ei\u127B\u1289\u01F2\u1280\0\u1287efore;\u6234a;\u4398\u0100cn\u128E\u1298kSpace;\uC000\u205F\u200ASpace;\u6009lde\u0200;EFT\u12AB\u12AC\u12B2\u12BC\u623Cqual;\u6243ullEqual;\u6245ilde;\u6248pf;\uC000\u{1D54B}ipleDot;\u60DB\u0100ct\u12D6\u12DBr;\uC000\u{1D4AF}rok;\u4166\u0AE1\u12F7\u130E\u131A\u1326\0\u132C\u1331\0\0\0\0\0\u1338\u133D\u1377\u1385\0\u13FF\u1404\u140A\u1410\u0100cr\u12FB\u1301ute\u803B\xDA\u40DAr\u0100;o\u1307\u1308\u619Fcir;\u6949r\u01E3\u1313\0\u1316y;\u440Eve;\u416C\u0100iy\u131E\u1323rc\u803B\xDB\u40DB;\u4423blac;\u4170r;\uC000\u{1D518}rave\u803B\xD9\u40D9acr;\u416A\u0100di\u1341\u1369er\u0100BP\u1348\u135D\u0100ar\u134D\u1350r;\u405Fac\u0100ek\u1357\u1359;\u63DFet;\u63B5arenthesis;\u63DDon\u0100;P\u1370\u1371\u62C3lus;\u628E\u0100gp\u137B\u137Fon;\u4172f;\uC000\u{1D54C}\u0400ADETadps\u1395\u13AE\u13B8\u13C4\u03E8\u13D2\u13D7\u13F3rrow\u0180;BD\u1150\u13A0\u13A4ar;\u6912ownArrow;\u61C5ownArrow;\u6195quilibrium;\u696Eee\u0100;A\u13CB\u13CC\u62A5rrow;\u61A5own\xE1\u03F3er\u0100LR\u13DE\u13E8eftArrow;\u6196ightArrow;\u6197i\u0100;l\u13F9\u13FA\u43D2on;\u43A5ing;\u416Ecr;\uC000\u{1D4B0}ilde;\u4168ml\u803B\xDC\u40DC\u0480Dbcdefosv\u1427\u142C\u1430\u1433\u143E\u1485\u148A\u1490\u1496ash;\u62ABar;\u6AEBy;\u4412ash\u0100;l\u143B\u143C\u62A9;\u6AE6\u0100er\u1443\u1445;\u62C1\u0180bty\u144C\u1450\u147Aar;\u6016\u0100;i\u144F\u1455cal\u0200BLST\u1461\u1465\u146A\u1474ar;\u6223ine;\u407Ceparator;\u6758ilde;\u6240ThinSpace;\u600Ar;\uC000\u{1D519}pf;\uC000\u{1D54D}cr;\uC000\u{1D4B1}dash;\u62AA\u0280cefos\u14A7\u14AC\u14B1\u14B6\u14BCirc;\u4174dge;\u62C0r;\uC000\u{1D51A}pf;\uC000\u{1D54E}cr;\uC000\u{1D4B2}\u0200fios\u14CB\u14D0\u14D2\u14D8r;\uC000\u{1D51B};\u439Epf;\uC000\u{1D54F}cr;\uC000\u{1D4B3}\u0480AIUacfosu\u14F1\u14F5\u14F9\u14FD\u1504\u150F\u1514\u151A\u1520cy;\u442Fcy;\u4407cy;\u442Ecute\u803B\xDD\u40DD\u0100iy\u1509\u150Drc;\u4176;\u442Br;\uC000\u{1D51C}pf;\uC000\u{1D550}cr;\uC000\u{1D4B4}ml;\u4178\u0400Hacdefos\u1535\u1539\u153F\u154B\u154F\u155D\u1560\u1564cy;\u4416cute;\u4179\u0100ay\u1544\u1549ron;\u417D;\u4417ot;\u417B\u01F2\u1554\0\u155BoWidt\xE8\u0AD9a;\u4396r;\u6128pf;\u6124cr;\uC000\u{1D4B5}\u0BE1\u1583\u158A\u1590\0\u15B0\u15B6\u15BF\0\0\0\0\u15C6\u15DB\u15EB\u165F\u166D\0\u1695\u169B\u16B2\u16B9\0\u16BEcute\u803B\xE1\u40E1reve;\u4103\u0300;Ediuy\u159C\u159D\u15A1\u15A3\u15A8\u15AD\u623E;\uC000\u223E\u0333;\u623Frc\u803B\xE2\u40E2te\u80BB\xB4\u0306;\u4430lig\u803B\xE6\u40E6\u0100;r\xB2\u15BA;\uC000\u{1D51E}rave\u803B\xE0\u40E0\u0100ep\u15CA\u15D6\u0100fp\u15CF\u15D4sym;\u6135\xE8\u15D3ha;\u43B1\u0100ap\u15DFc\u0100cl\u15E4\u15E7r;\u4101g;\u6A3F\u0264\u15F0\0\0\u160A\u0280;adsv\u15FA\u15FB\u15FF\u1601\u1607\u6227nd;\u6A55;\u6A5Clope;\u6A58;\u6A5A\u0380;elmrsz\u1618\u1619\u161B\u161E\u163F\u164F\u1659\u6220;\u69A4e\xBB\u1619sd\u0100;a\u1625\u1626\u6221\u0461\u1630\u1632\u1634\u1636\u1638\u163A\u163C\u163E;\u69A8;\u69A9;\u69AA;\u69AB;\u69AC;\u69AD;\u69AE;\u69AFt\u0100;v\u1645\u1646\u621Fb\u0100;d\u164C\u164D\u62BE;\u699D\u0100pt\u1654\u1657h;\u6222\xBB\xB9arr;\u637C\u0100gp\u1663\u1667on;\u4105f;\uC000\u{1D552}\u0380;Eaeiop\u12C1\u167B\u167D\u1682\u1684\u1687\u168A;\u6A70cir;\u6A6F;\u624Ad;\u624Bs;\u4027rox\u0100;e\u12C1\u1692\xF1\u1683ing\u803B\xE5\u40E5\u0180cty\u16A1\u16A6\u16A8r;\uC000\u{1D4B6};\u402Amp\u0100;e\u12C1\u16AF\xF1\u0288ilde\u803B\xE3\u40E3ml\u803B\xE4\u40E4\u0100ci\u16C2\u16C8onin\xF4\u0272nt;\u6A11\u0800Nabcdefiklnoprsu\u16ED\u16F1\u1730\u173C\u1743\u1748\u1778\u177D\u17E0\u17E6\u1839\u1850\u170D\u193D\u1948\u1970ot;\u6AED\u0100cr\u16F6\u171Ek\u0200ceps\u1700\u1705\u170D\u1713ong;\u624Cpsilon;\u43F6rime;\u6035im\u0100;e\u171A\u171B\u623Dq;\u62CD\u0176\u1722\u1726ee;\u62BDed\u0100;g\u172C\u172D\u6305e\xBB\u172Drk\u0100;t\u135C\u1737brk;\u63B6\u0100oy\u1701\u1741;\u4431quo;\u601E\u0280cmprt\u1753\u175B\u1761\u1764\u1768aus\u0100;e\u010A\u0109ptyv;\u69B0s\xE9\u170Cno\xF5\u0113\u0180ahw\u176F\u1771\u1773;\u43B2;\u6136een;\u626Cr;\uC000\u{1D51F}g\u0380costuvw\u178D\u179D\u17B3\u17C1\u17D5\u17DB\u17DE\u0180aiu\u1794\u1796\u179A\xF0\u0760rc;\u65EFp\xBB\u1371\u0180dpt\u17A4\u17A8\u17ADot;\u6A00lus;\u6A01imes;\u6A02\u0271\u17B9\0\0\u17BEcup;\u6A06ar;\u6605riangle\u0100du\u17CD\u17D2own;\u65BDp;\u65B3plus;\u6A04e\xE5\u1444\xE5\u14ADarow;\u690D\u0180ako\u17ED\u1826\u1835\u0100cn\u17F2\u1823k\u0180lst\u17FA\u05AB\u1802ozenge;\u69EBriangle\u0200;dlr\u1812\u1813\u1818\u181D\u65B4own;\u65BEeft;\u65C2ight;\u65B8k;\u6423\u01B1\u182B\0\u1833\u01B2\u182F\0\u1831;\u6592;\u65914;\u6593ck;\u6588\u0100eo\u183E\u184D\u0100;q\u1843\u1846\uC000=\u20E5uiv;\uC000\u2261\u20E5t;\u6310\u0200ptwx\u1859\u185E\u1867\u186Cf;\uC000\u{1D553}\u0100;t\u13CB\u1863om\xBB\u13CCtie;\u62C8\u0600DHUVbdhmptuv\u1885\u1896\u18AA\u18BB\u18D7\u18DB\u18EC\u18FF\u1905\u190A\u1910\u1921\u0200LRlr\u188E\u1890\u1892\u1894;\u6557;\u6554;\u6556;\u6553\u0280;DUdu\u18A1\u18A2\u18A4\u18A6\u18A8\u6550;\u6566;\u6569;\u6564;\u6567\u0200LRlr\u18B3\u18B5\u18B7\u18B9;\u655D;\u655A;\u655C;\u6559\u0380;HLRhlr\u18CA\u18CB\u18CD\u18CF\u18D1\u18D3\u18D5\u6551;\u656C;\u6563;\u6560;\u656B;\u6562;\u655Fox;\u69C9\u0200LRlr\u18E4\u18E6\u18E8\u18EA;\u6555;\u6552;\u6510;\u650C\u0280;DUdu\u06BD\u18F7\u18F9\u18FB\u18FD;\u6565;\u6568;\u652C;\u6534inus;\u629Flus;\u629Eimes;\u62A0\u0200LRlr\u1919\u191B\u191D\u191F;\u655B;\u6558;\u6518;\u6514\u0380;HLRhlr\u1930\u1931\u1933\u1935\u1937\u1939\u193B\u6502;\u656A;\u6561;\u655E;\u653C;\u6524;\u651C\u0100ev\u0123\u1942bar\u803B\xA6\u40A6\u0200ceio\u1951\u1956\u195A\u1960r;\uC000\u{1D4B7}mi;\u604Fm\u0100;e\u171A\u171Cl\u0180;bh\u1968\u1969\u196B\u405C;\u69C5sub;\u67C8\u016C\u1974\u197El\u0100;e\u1979\u197A\u6022t\xBB\u197Ap\u0180;Ee\u012F\u1985\u1987;\u6AAE\u0100;q\u06DC\u06DB\u0CE1\u19A7\0\u19E8\u1A11\u1A15\u1A32\0\u1A37\u1A50\0\0\u1AB4\0\0\u1AC1\0\0\u1B21\u1B2E\u1B4D\u1B52\0\u1BFD\0\u1C0C\u0180cpr\u19AD\u19B2\u19DDute;\u4107\u0300;abcds\u19BF\u19C0\u19C4\u19CA\u19D5\u19D9\u6229nd;\u6A44rcup;\u6A49\u0100au\u19CF\u19D2p;\u6A4Bp;\u6A47ot;\u6A40;\uC000\u2229\uFE00\u0100eo\u19E2\u19E5t;\u6041\xEE\u0693\u0200aeiu\u19F0\u19FB\u1A01\u1A05\u01F0\u19F5\0\u19F8s;\u6A4Don;\u410Ddil\u803B\xE7\u40E7rc;\u4109ps\u0100;s\u1A0C\u1A0D\u6A4Cm;\u6A50ot;\u410B\u0180dmn\u1A1B\u1A20\u1A26il\u80BB\xB8\u01ADptyv;\u69B2t\u8100\xA2;e\u1A2D\u1A2E\u40A2r\xE4\u01B2r;\uC000\u{1D520}\u0180cei\u1A3D\u1A40\u1A4Dy;\u4447ck\u0100;m\u1A47\u1A48\u6713ark\xBB\u1A48;\u43C7r\u0380;Ecefms\u1A5F\u1A60\u1A62\u1A6B\u1AA4\u1AAA\u1AAE\u65CB;\u69C3\u0180;el\u1A69\u1A6A\u1A6D\u42C6q;\u6257e\u0261\u1A74\0\0\u1A88rrow\u0100lr\u1A7C\u1A81eft;\u61BAight;\u61BB\u0280RSacd\u1A92\u1A94\u1A96\u1A9A\u1A9F\xBB\u0F47;\u64C8st;\u629Birc;\u629Aash;\u629Dnint;\u6A10id;\u6AEFcir;\u69C2ubs\u0100;u\u1ABB\u1ABC\u6663it\xBB\u1ABC\u02EC\u1AC7\u1AD4\u1AFA\0\u1B0Aon\u0100;e\u1ACD\u1ACE\u403A\u0100;q\xC7\xC6\u026D\u1AD9\0\0\u1AE2a\u0100;t\u1ADE\u1ADF\u402C;\u4040\u0180;fl\u1AE8\u1AE9\u1AEB\u6201\xEE\u1160e\u0100mx\u1AF1\u1AF6ent\xBB\u1AE9e\xF3\u024D\u01E7\u1AFE\0\u1B07\u0100;d\u12BB\u1B02ot;\u6A6Dn\xF4\u0246\u0180fry\u1B10\u1B14\u1B17;\uC000\u{1D554}o\xE4\u0254\u8100\xA9;s\u0155\u1B1Dr;\u6117\u0100ao\u1B25\u1B29rr;\u61B5ss;\u6717\u0100cu\u1B32\u1B37r;\uC000\u{1D4B8}\u0100bp\u1B3C\u1B44\u0100;e\u1B41\u1B42\u6ACF;\u6AD1\u0100;e\u1B49\u1B4A\u6AD0;\u6AD2dot;\u62EF\u0380delprvw\u1B60\u1B6C\u1B77\u1B82\u1BAC\u1BD4\u1BF9arr\u0100lr\u1B68\u1B6A;\u6938;\u6935\u0270\u1B72\0\0\u1B75r;\u62DEc;\u62DFarr\u0100;p\u1B7F\u1B80\u61B6;\u693D\u0300;bcdos\u1B8F\u1B90\u1B96\u1BA1\u1BA5\u1BA8\u622Arcap;\u6A48\u0100au\u1B9B\u1B9Ep;\u6A46p;\u6A4Aot;\u628Dr;\u6A45;\uC000\u222A\uFE00\u0200alrv\u1BB5\u1BBF\u1BDE\u1BE3rr\u0100;m\u1BBC\u1BBD\u61B7;\u693Cy\u0180evw\u1BC7\u1BD4\u1BD8q\u0270\u1BCE\0\0\u1BD2re\xE3\u1B73u\xE3\u1B75ee;\u62CEedge;\u62CFen\u803B\xA4\u40A4earrow\u0100lr\u1BEE\u1BF3eft\xBB\u1B80ight\xBB\u1BBDe\xE4\u1BDD\u0100ci\u1C01\u1C07onin\xF4\u01F7nt;\u6231lcty;\u632D\u0980AHabcdefhijlorstuwz\u1C38\u1C3B\u1C3F\u1C5D\u1C69\u1C75\u1C8A\u1C9E\u1CAC\u1CB7\u1CFB\u1CFF\u1D0D\u1D7B\u1D91\u1DAB\u1DBB\u1DC6\u1DCDr\xF2\u0381ar;\u6965\u0200glrs\u1C48\u1C4D\u1C52\u1C54ger;\u6020eth;\u6138\xF2\u1133h\u0100;v\u1C5A\u1C5B\u6010\xBB\u090A\u016B\u1C61\u1C67arow;\u690Fa\xE3\u0315\u0100ay\u1C6E\u1C73ron;\u410F;\u4434\u0180;ao\u0332\u1C7C\u1C84\u0100gr\u02BF\u1C81r;\u61CAtseq;\u6A77\u0180glm\u1C91\u1C94\u1C98\u803B\xB0\u40B0ta;\u43B4ptyv;\u69B1\u0100ir\u1CA3\u1CA8sht;\u697F;\uC000\u{1D521}ar\u0100lr\u1CB3\u1CB5\xBB\u08DC\xBB\u101E\u0280aegsv\u1CC2\u0378\u1CD6\u1CDC\u1CE0m\u0180;os\u0326\u1CCA\u1CD4nd\u0100;s\u0326\u1CD1uit;\u6666amma;\u43DDin;\u62F2\u0180;io\u1CE7\u1CE8\u1CF8\u40F7de\u8100\xF7;o\u1CE7\u1CF0ntimes;\u62C7n\xF8\u1CF7cy;\u4452c\u026F\u1D06\0\0\u1D0Arn;\u631Eop;\u630D\u0280lptuw\u1D18\u1D1D\u1D22\u1D49\u1D55lar;\u4024f;\uC000\u{1D555}\u0280;emps\u030B\u1D2D\u1D37\u1D3D\u1D42q\u0100;d\u0352\u1D33ot;\u6251inus;\u6238lus;\u6214quare;\u62A1blebarwedg\xE5\xFAn\u0180adh\u112E\u1D5D\u1D67ownarrow\xF3\u1C83arpoon\u0100lr\u1D72\u1D76ef\xF4\u1CB4igh\xF4\u1CB6\u0162\u1D7F\u1D85karo\xF7\u0F42\u026F\u1D8A\0\0\u1D8Ern;\u631Fop;\u630C\u0180cot\u1D98\u1DA3\u1DA6\u0100ry\u1D9D\u1DA1;\uC000\u{1D4B9};\u4455l;\u69F6rok;\u4111\u0100dr\u1DB0\u1DB4ot;\u62F1i\u0100;f\u1DBA\u1816\u65BF\u0100ah\u1DC0\u1DC3r\xF2\u0429a\xF2\u0FA6angle;\u69A6\u0100ci\u1DD2\u1DD5y;\u445Fgrarr;\u67FF\u0900Dacdefglmnopqrstux\u1E01\u1E09\u1E19\u1E38\u0578\u1E3C\u1E49\u1E61\u1E7E\u1EA5\u1EAF\u1EBD\u1EE1\u1F2A\u1F37\u1F44\u1F4E\u1F5A\u0100Do\u1E06\u1D34o\xF4\u1C89\u0100cs\u1E0E\u1E14ute\u803B\xE9\u40E9ter;\u6A6E\u0200aioy\u1E22\u1E27\u1E31\u1E36ron;\u411Br\u0100;c\u1E2D\u1E2E\u6256\u803B\xEA\u40EAlon;\u6255;\u444Dot;\u4117\u0100Dr\u1E41\u1E45ot;\u6252;\uC000\u{1D522}\u0180;rs\u1E50\u1E51\u1E57\u6A9Aave\u803B\xE8\u40E8\u0100;d\u1E5C\u1E5D\u6A96ot;\u6A98\u0200;ils\u1E6A\u1E6B\u1E72\u1E74\u6A99nters;\u63E7;\u6113\u0100;d\u1E79\u1E7A\u6A95ot;\u6A97\u0180aps\u1E85\u1E89\u1E97cr;\u4113ty\u0180;sv\u1E92\u1E93\u1E95\u6205et\xBB\u1E93p\u01001;\u1E9D\u1EA4\u0133\u1EA1\u1EA3;\u6004;\u6005\u6003\u0100gs\u1EAA\u1EAC;\u414Bp;\u6002\u0100gp\u1EB4\u1EB8on;\u4119f;\uC000\u{1D556}\u0180als\u1EC4\u1ECE\u1ED2r\u0100;s\u1ECA\u1ECB\u62D5l;\u69E3us;\u6A71i\u0180;lv\u1EDA\u1EDB\u1EDF\u43B5on\xBB\u1EDB;\u43F5\u0200csuv\u1EEA\u1EF3\u1F0B\u1F23\u0100io\u1EEF\u1E31rc\xBB\u1E2E\u0269\u1EF9\0\0\u1EFB\xED\u0548ant\u0100gl\u1F02\u1F06tr\xBB\u1E5Dess\xBB\u1E7A\u0180aei\u1F12\u1F16\u1F1Als;\u403Dst;\u625Fv\u0100;D\u0235\u1F20D;\u6A78parsl;\u69E5\u0100Da\u1F2F\u1F33ot;\u6253rr;\u6971\u0180cdi\u1F3E\u1F41\u1EF8r;\u612Fo\xF4\u0352\u0100ah\u1F49\u1F4B;\u43B7\u803B\xF0\u40F0\u0100mr\u1F53\u1F57l\u803B\xEB\u40EBo;\u60AC\u0180cip\u1F61\u1F64\u1F67l;\u4021s\xF4\u056E\u0100eo\u1F6C\u1F74ctatio\xEE\u0559nential\xE5\u0579\u09E1\u1F92\0\u1F9E\0\u1FA1\u1FA7\0\0\u1FC6\u1FCC\0\u1FD3\0\u1FE6\u1FEA\u2000\0\u2008\u205Allingdotse\xF1\u1E44y;\u4444male;\u6640\u0180ilr\u1FAD\u1FB3\u1FC1lig;\u8000\uFB03\u0269\u1FB9\0\0\u1FBDg;\u8000\uFB00ig;\u8000\uFB04;\uC000\u{1D523}lig;\u8000\uFB01lig;\uC000fj\u0180alt\u1FD9\u1FDC\u1FE1t;\u666Dig;\u8000\uFB02ns;\u65B1of;\u4192\u01F0\u1FEE\0\u1FF3f;\uC000\u{1D557}\u0100ak\u05BF\u1FF7\u0100;v\u1FFC\u1FFD\u62D4;\u6AD9artint;\u6A0D\u0100ao\u200C\u2055\u0100cs\u2011\u2052\u03B1\u201A\u2030\u2038\u2045\u2048\0\u2050\u03B2\u2022\u2025\u2027\u202A\u202C\0\u202E\u803B\xBD\u40BD;\u6153\u803B\xBC\u40BC;\u6155;\u6159;\u615B\u01B3\u2034\0\u2036;\u6154;\u6156\u02B4\u203E\u2041\0\0\u2043\u803B\xBE\u40BE;\u6157;\u615C5;\u6158\u01B6\u204C\0\u204E;\u615A;\u615D8;\u615El;\u6044wn;\u6322cr;\uC000\u{1D4BB}\u0880Eabcdefgijlnorstv\u2082\u2089\u209F\u20A5\u20B0\u20B4\u20F0\u20F5\u20FA\u20FF\u2103\u2112\u2138\u0317\u213E\u2152\u219E\u0100;l\u064D\u2087;\u6A8C\u0180cmp\u2090\u2095\u209Dute;\u41F5ma\u0100;d\u209C\u1CDA\u43B3;\u6A86reve;\u411F\u0100iy\u20AA\u20AErc;\u411D;\u4433ot;\u4121\u0200;lqs\u063E\u0642\u20BD\u20C9\u0180;qs\u063E\u064C\u20C4lan\xF4\u0665\u0200;cdl\u0665\u20D2\u20D5\u20E5c;\u6AA9ot\u0100;o\u20DC\u20DD\u6A80\u0100;l\u20E2\u20E3\u6A82;\u6A84\u0100;e\u20EA\u20ED\uC000\u22DB\uFE00s;\u6A94r;\uC000\u{1D524}\u0100;g\u0673\u061Bmel;\u6137cy;\u4453\u0200;Eaj\u065A\u210C\u210E\u2110;\u6A92;\u6AA5;\u6AA4\u0200Eaes\u211B\u211D\u2129\u2134;\u6269p\u0100;p\u2123\u2124\u6A8Arox\xBB\u2124\u0100;q\u212E\u212F\u6A88\u0100;q\u212E\u211Bim;\u62E7pf;\uC000\u{1D558}\u0100ci\u2143\u2146r;\u610Am\u0180;el\u066B\u214E\u2150;\u6A8E;\u6A90\u8300>;cdlqr\u05EE\u2160\u216A\u216E\u2173\u2179\u0100ci\u2165\u2167;\u6AA7r;\u6A7Aot;\u62D7Par;\u6995uest;\u6A7C\u0280adels\u2184\u216A\u2190\u0656\u219B\u01F0\u2189\0\u218Epro\xF8\u209Er;\u6978q\u0100lq\u063F\u2196les\xF3\u2088i\xED\u066B\u0100en\u21A3\u21ADrtneqq;\uC000\u2269\uFE00\xC5\u21AA\u0500Aabcefkosy\u21C4\u21C7\u21F1\u21F5\u21FA\u2218\u221D\u222F\u2268\u227Dr\xF2\u03A0\u0200ilmr\u21D0\u21D4\u21D7\u21DBrs\xF0\u1484f\xBB\u2024il\xF4\u06A9\u0100dr\u21E0\u21E4cy;\u444A\u0180;cw\u08F4\u21EB\u21EFir;\u6948;\u61ADar;\u610Firc;\u4125\u0180alr\u2201\u220E\u2213rts\u0100;u\u2209\u220A\u6665it\xBB\u220Alip;\u6026con;\u62B9r;\uC000\u{1D525}s\u0100ew\u2223\u2229arow;\u6925arow;\u6926\u0280amopr\u223A\u223E\u2243\u225E\u2263rr;\u61FFtht;\u623Bk\u0100lr\u2249\u2253eftarrow;\u61A9ightarrow;\u61AAf;\uC000\u{1D559}bar;\u6015\u0180clt\u226F\u2274\u2278r;\uC000\u{1D4BD}as\xE8\u21F4rok;\u4127\u0100bp\u2282\u2287ull;\u6043hen\xBB\u1C5B\u0AE1\u22A3\0\u22AA\0\u22B8\u22C5\u22CE\0\u22D5\u22F3\0\0\u22F8\u2322\u2367\u2362\u237F\0\u2386\u23AA\u23B4cute\u803B\xED\u40ED\u0180;iy\u0771\u22B0\u22B5rc\u803B\xEE\u40EE;\u4438\u0100cx\u22BC\u22BFy;\u4435cl\u803B\xA1\u40A1\u0100fr\u039F\u22C9;\uC000\u{1D526}rave\u803B\xEC\u40EC\u0200;ino\u073E\u22DD\u22E9\u22EE\u0100in\u22E2\u22E6nt;\u6A0Ct;\u622Dfin;\u69DCta;\u6129lig;\u4133\u0180aop\u22FE\u231A\u231D\u0180cgt\u2305\u2308\u2317r;\u412B\u0180elp\u071F\u230F\u2313in\xE5\u078Ear\xF4\u0720h;\u4131f;\u62B7ed;\u41B5\u0280;cfot\u04F4\u232C\u2331\u233D\u2341are;\u6105in\u0100;t\u2338\u2339\u621Eie;\u69DDdo\xF4\u2319\u0280;celp\u0757\u234C\u2350\u235B\u2361al;\u62BA\u0100gr\u2355\u2359er\xF3\u1563\xE3\u234Darhk;\u6A17rod;\u6A3C\u0200cgpt\u236F\u2372\u2376\u237By;\u4451on;\u412Ff;\uC000\u{1D55A}a;\u43B9uest\u803B\xBF\u40BF\u0100ci\u238A\u238Fr;\uC000\u{1D4BE}n\u0280;Edsv\u04F4\u239B\u239D\u23A1\u04F3;\u62F9ot;\u62F5\u0100;v\u23A6\u23A7\u62F4;\u62F3\u0100;i\u0777\u23AElde;\u4129\u01EB\u23B8\0\u23BCcy;\u4456l\u803B\xEF\u40EF\u0300cfmosu\u23CC\u23D7\u23DC\u23E1\u23E7\u23F5\u0100iy\u23D1\u23D5rc;\u4135;\u4439r;\uC000\u{1D527}ath;\u4237pf;\uC000\u{1D55B}\u01E3\u23EC\0\u23F1r;\uC000\u{1D4BF}rcy;\u4458kcy;\u4454\u0400acfghjos\u240B\u2416\u2422\u2427\u242D\u2431\u2435\u243Bppa\u0100;v\u2413\u2414\u43BA;\u43F0\u0100ey\u241B\u2420dil;\u4137;\u443Ar;\uC000\u{1D528}reen;\u4138cy;\u4445cy;\u445Cpf;\uC000\u{1D55C}cr;\uC000\u{1D4C0}\u0B80ABEHabcdefghjlmnoprstuv\u2470\u2481\u2486\u248D\u2491\u250E\u253D\u255A\u2580\u264E\u265E\u2665\u2679\u267D\u269A\u26B2\u26D8\u275D\u2768\u278B\u27C0\u2801\u2812\u0180art\u2477\u247A\u247Cr\xF2\u09C6\xF2\u0395ail;\u691Barr;\u690E\u0100;g\u0994\u248B;\u6A8Bar;\u6962\u0963\u24A5\0\u24AA\0\u24B1\0\0\0\0\0\u24B5\u24BA\0\u24C6\u24C8\u24CD\0\u24F9ute;\u413Amptyv;\u69B4ra\xEE\u084Cbda;\u43BBg\u0180;dl\u088E\u24C1\u24C3;\u6991\xE5\u088E;\u6A85uo\u803B\xAB\u40ABr\u0400;bfhlpst\u0899\u24DE\u24E6\u24E9\u24EB\u24EE\u24F1\u24F5\u0100;f\u089D\u24E3s;\u691Fs;\u691D\xEB\u2252p;\u61ABl;\u6939im;\u6973l;\u61A2\u0180;ae\u24FF\u2500\u2504\u6AABil;\u6919\u0100;s\u2509\u250A\u6AAD;\uC000\u2AAD\uFE00\u0180abr\u2515\u2519\u251Drr;\u690Crk;\u6772\u0100ak\u2522\u252Cc\u0100ek\u2528\u252A;\u407B;\u405B\u0100es\u2531\u2533;\u698Bl\u0100du\u2539\u253B;\u698F;\u698D\u0200aeuy\u2546\u254B\u2556\u2558ron;\u413E\u0100di\u2550\u2554il;\u413C\xEC\u08B0\xE2\u2529;\u443B\u0200cqrs\u2563\u2566\u256D\u257Da;\u6936uo\u0100;r\u0E19\u1746\u0100du\u2572\u2577har;\u6967shar;\u694Bh;\u61B2\u0280;fgqs\u258B\u258C\u0989\u25F3\u25FF\u6264t\u0280ahlrt\u2598\u25A4\u25B7\u25C2\u25E8rrow\u0100;t\u0899\u25A1a\xE9\u24F6arpoon\u0100du\u25AF\u25B4own\xBB\u045Ap\xBB\u0966eftarrows;\u61C7ight\u0180ahs\u25CD\u25D6\u25DErrow\u0100;s\u08F4\u08A7arpoon\xF3\u0F98quigarro\xF7\u21F0hreetimes;\u62CB\u0180;qs\u258B\u0993\u25FAlan\xF4\u09AC\u0280;cdgs\u09AC\u260A\u260D\u261D\u2628c;\u6AA8ot\u0100;o\u2614\u2615\u6A7F\u0100;r\u261A\u261B\u6A81;\u6A83\u0100;e\u2622\u2625\uC000\u22DA\uFE00s;\u6A93\u0280adegs\u2633\u2639\u263D\u2649\u264Bppro\xF8\u24C6ot;\u62D6q\u0100gq\u2643\u2645\xF4\u0989gt\xF2\u248C\xF4\u099Bi\xED\u09B2\u0180ilr\u2655\u08E1\u265Asht;\u697C;\uC000\u{1D529}\u0100;E\u099C\u2663;\u6A91\u0161\u2669\u2676r\u0100du\u25B2\u266E\u0100;l\u0965\u2673;\u696Alk;\u6584cy;\u4459\u0280;acht\u0A48\u2688\u268B\u2691\u2696r\xF2\u25C1orne\xF2\u1D08ard;\u696Bri;\u65FA\u0100io\u269F\u26A4dot;\u4140ust\u0100;a\u26AC\u26AD\u63B0che\xBB\u26AD\u0200Eaes\u26BB\u26BD\u26C9\u26D4;\u6268p\u0100;p\u26C3\u26C4\u6A89rox\xBB\u26C4\u0100;q\u26CE\u26CF\u6A87\u0100;q\u26CE\u26BBim;\u62E6\u0400abnoptwz\u26E9\u26F4\u26F7\u271A\u272F\u2741\u2747\u2750\u0100nr\u26EE\u26F1g;\u67ECr;\u61FDr\xEB\u08C1g\u0180lmr\u26FF\u270D\u2714eft\u0100ar\u09E6\u2707ight\xE1\u09F2apsto;\u67FCight\xE1\u09FDparrow\u0100lr\u2725\u2729ef\xF4\u24EDight;\u61AC\u0180afl\u2736\u2739\u273Dr;\u6985;\uC000\u{1D55D}us;\u6A2Dimes;\u6A34\u0161\u274B\u274Fst;\u6217\xE1\u134E\u0180;ef\u2757\u2758\u1800\u65CAnge\xBB\u2758ar\u0100;l\u2764\u2765\u4028t;\u6993\u0280achmt\u2773\u2776\u277C\u2785\u2787r\xF2\u08A8orne\xF2\u1D8Car\u0100;d\u0F98\u2783;\u696D;\u600Eri;\u62BF\u0300achiqt\u2798\u279D\u0A40\u27A2\u27AE\u27BBquo;\u6039r;\uC000\u{1D4C1}m\u0180;eg\u09B2\u27AA\u27AC;\u6A8D;\u6A8F\u0100bu\u252A\u27B3o\u0100;r\u0E1F\u27B9;\u601Arok;\u4142\u8400<;cdhilqr\u082B\u27D2\u2639\u27DC\u27E0\u27E5\u27EA\u27F0\u0100ci\u27D7\u27D9;\u6AA6r;\u6A79re\xE5\u25F2mes;\u62C9arr;\u6976uest;\u6A7B\u0100Pi\u27F5\u27F9ar;\u6996\u0180;ef\u2800\u092D\u181B\u65C3r\u0100du\u2807\u280Dshar;\u694Ahar;\u6966\u0100en\u2817\u2821rtneqq;\uC000\u2268\uFE00\xC5\u281E\u0700Dacdefhilnopsu\u2840\u2845\u2882\u288E\u2893\u28A0\u28A5\u28A8\u28DA\u28E2\u28E4\u0A83\u28F3\u2902Dot;\u623A\u0200clpr\u284E\u2852\u2863\u287Dr\u803B\xAF\u40AF\u0100et\u2857\u2859;\u6642\u0100;e\u285E\u285F\u6720se\xBB\u285F\u0100;s\u103B\u2868to\u0200;dlu\u103B\u2873\u2877\u287Bow\xEE\u048Cef\xF4\u090F\xF0\u13D1ker;\u65AE\u0100oy\u2887\u288Cmma;\u6A29;\u443Cash;\u6014asuredangle\xBB\u1626r;\uC000\u{1D52A}o;\u6127\u0180cdn\u28AF\u28B4\u28C9ro\u803B\xB5\u40B5\u0200;acd\u1464\u28BD\u28C0\u28C4s\xF4\u16A7ir;\u6AF0ot\u80BB\xB7\u01B5us\u0180;bd\u28D2\u1903\u28D3\u6212\u0100;u\u1D3C\u28D8;\u6A2A\u0163\u28DE\u28E1p;\u6ADB\xF2\u2212\xF0\u0A81\u0100dp\u28E9\u28EEels;\u62A7f;\uC000\u{1D55E}\u0100ct\u28F8\u28FDr;\uC000\u{1D4C2}pos\xBB\u159D\u0180;lm\u2909\u290A\u290D\u43BCtimap;\u62B8\u0C00GLRVabcdefghijlmoprstuvw\u2942\u2953\u297E\u2989\u2998\u29DA\u29E9\u2A15\u2A1A\u2A58\u2A5D\u2A83\u2A95\u2AA4\u2AA8\u2B04\u2B07\u2B44\u2B7F\u2BAE\u2C34\u2C67\u2C7C\u2CE9\u0100gt\u2947\u294B;\uC000\u22D9\u0338\u0100;v\u2950\u0BCF\uC000\u226B\u20D2\u0180elt\u295A\u2972\u2976ft\u0100ar\u2961\u2967rrow;\u61CDightarrow;\u61CE;\uC000\u22D8\u0338\u0100;v\u297B\u0C47\uC000\u226A\u20D2ightarrow;\u61CF\u0100Dd\u298E\u2993ash;\u62AFash;\u62AE\u0280bcnpt\u29A3\u29A7\u29AC\u29B1\u29CCla\xBB\u02DEute;\u4144g;\uC000\u2220\u20D2\u0280;Eiop\u0D84\u29BC\u29C0\u29C5\u29C8;\uC000\u2A70\u0338d;\uC000\u224B\u0338s;\u4149ro\xF8\u0D84ur\u0100;a\u29D3\u29D4\u666El\u0100;s\u29D3\u0B38\u01F3\u29DF\0\u29E3p\u80BB\xA0\u0B37mp\u0100;e\u0BF9\u0C00\u0280aeouy\u29F4\u29FE\u2A03\u2A10\u2A13\u01F0\u29F9\0\u29FB;\u6A43on;\u4148dil;\u4146ng\u0100;d\u0D7E\u2A0Aot;\uC000\u2A6D\u0338p;\u6A42;\u443Dash;\u6013\u0380;Aadqsx\u0B92\u2A29\u2A2D\u2A3B\u2A41\u2A45\u2A50rr;\u61D7r\u0100hr\u2A33\u2A36k;\u6924\u0100;o\u13F2\u13F0ot;\uC000\u2250\u0338ui\xF6\u0B63\u0100ei\u2A4A\u2A4Ear;\u6928\xED\u0B98ist\u0100;s\u0BA0\u0B9Fr;\uC000\u{1D52B}\u0200Eest\u0BC5\u2A66\u2A79\u2A7C\u0180;qs\u0BBC\u2A6D\u0BE1\u0180;qs\u0BBC\u0BC5\u2A74lan\xF4\u0BE2i\xED\u0BEA\u0100;r\u0BB6\u2A81\xBB\u0BB7\u0180Aap\u2A8A\u2A8D\u2A91r\xF2\u2971rr;\u61AEar;\u6AF2\u0180;sv\u0F8D\u2A9C\u0F8C\u0100;d\u2AA1\u2AA2\u62FC;\u62FAcy;\u445A\u0380AEadest\u2AB7\u2ABA\u2ABE\u2AC2\u2AC5\u2AF6\u2AF9r\xF2\u2966;\uC000\u2266\u0338rr;\u619Ar;\u6025\u0200;fqs\u0C3B\u2ACE\u2AE3\u2AEFt\u0100ar\u2AD4\u2AD9rro\xF7\u2AC1ightarro\xF7\u2A90\u0180;qs\u0C3B\u2ABA\u2AEAlan\xF4\u0C55\u0100;s\u0C55\u2AF4\xBB\u0C36i\xED\u0C5D\u0100;r\u0C35\u2AFEi\u0100;e\u0C1A\u0C25i\xE4\u0D90\u0100pt\u2B0C\u2B11f;\uC000\u{1D55F}\u8180\xAC;in\u2B19\u2B1A\u2B36\u40ACn\u0200;Edv\u0B89\u2B24\u2B28\u2B2E;\uC000\u22F9\u0338ot;\uC000\u22F5\u0338\u01E1\u0B89\u2B33\u2B35;\u62F7;\u62F6i\u0100;v\u0CB8\u2B3C\u01E1\u0CB8\u2B41\u2B43;\u62FE;\u62FD\u0180aor\u2B4B\u2B63\u2B69r\u0200;ast\u0B7B\u2B55\u2B5A\u2B5Flle\xEC\u0B7Bl;\uC000\u2AFD\u20E5;\uC000\u2202\u0338lint;\u6A14\u0180;ce\u0C92\u2B70\u2B73u\xE5\u0CA5\u0100;c\u0C98\u2B78\u0100;e\u0C92\u2B7D\xF1\u0C98\u0200Aait\u2B88\u2B8B\u2B9D\u2BA7r\xF2\u2988rr\u0180;cw\u2B94\u2B95\u2B99\u619B;\uC000\u2933\u0338;\uC000\u219D\u0338ghtarrow\xBB\u2B95ri\u0100;e\u0CCB\u0CD6\u0380chimpqu\u2BBD\u2BCD\u2BD9\u2B04\u0B78\u2BE4\u2BEF\u0200;cer\u0D32\u2BC6\u0D37\u2BC9u\xE5\u0D45;\uC000\u{1D4C3}ort\u026D\u2B05\0\0\u2BD6ar\xE1\u2B56m\u0100;e\u0D6E\u2BDF\u0100;q\u0D74\u0D73su\u0100bp\u2BEB\u2BED\xE5\u0CF8\xE5\u0D0B\u0180bcp\u2BF6\u2C11\u2C19\u0200;Ees\u2BFF\u2C00\u0D22\u2C04\u6284;\uC000\u2AC5\u0338et\u0100;e\u0D1B\u2C0Bq\u0100;q\u0D23\u2C00c\u0100;e\u0D32\u2C17\xF1\u0D38\u0200;Ees\u2C22\u2C23\u0D5F\u2C27\u6285;\uC000\u2AC6\u0338et\u0100;e\u0D58\u2C2Eq\u0100;q\u0D60\u2C23\u0200gilr\u2C3D\u2C3F\u2C45\u2C47\xEC\u0BD7lde\u803B\xF1\u40F1\xE7\u0C43iangle\u0100lr\u2C52\u2C5Ceft\u0100;e\u0C1A\u2C5A\xF1\u0C26ight\u0100;e\u0CCB\u2C65\xF1\u0CD7\u0100;m\u2C6C\u2C6D\u43BD\u0180;es\u2C74\u2C75\u2C79\u4023ro;\u6116p;\u6007\u0480DHadgilrs\u2C8F\u2C94\u2C99\u2C9E\u2CA3\u2CB0\u2CB6\u2CD3\u2CE3ash;\u62ADarr;\u6904p;\uC000\u224D\u20D2ash;\u62AC\u0100et\u2CA8\u2CAC;\uC000\u2265\u20D2;\uC000>\u20D2nfin;\u69DE\u0180Aet\u2CBD\u2CC1\u2CC5rr;\u6902;\uC000\u2264\u20D2\u0100;r\u2CCA\u2CCD\uC000<\u20D2ie;\uC000\u22B4\u20D2\u0100At\u2CD8\u2CDCrr;\u6903rie;\uC000\u22B5\u20D2im;\uC000\u223C\u20D2\u0180Aan\u2CF0\u2CF4\u2D02rr;\u61D6r\u0100hr\u2CFA\u2CFDk;\u6923\u0100;o\u13E7\u13E5ear;\u6927\u1253\u1A95\0\0\0\0\0\0\0\0\0\0\0\0\0\u2D2D\0\u2D38\u2D48\u2D60\u2D65\u2D72\u2D84\u1B07\0\0\u2D8D\u2DAB\0\u2DC8\u2DCE\0\u2DDC\u2E19\u2E2B\u2E3E\u2E43\u0100cs\u2D31\u1A97ute\u803B\xF3\u40F3\u0100iy\u2D3C\u2D45r\u0100;c\u1A9E\u2D42\u803B\xF4\u40F4;\u443E\u0280abios\u1AA0\u2D52\u2D57\u01C8\u2D5Alac;\u4151v;\u6A38old;\u69BClig;\u4153\u0100cr\u2D69\u2D6Dir;\u69BF;\uC000\u{1D52C}\u036F\u2D79\0\0\u2D7C\0\u2D82n;\u42DBave\u803B\xF2\u40F2;\u69C1\u0100bm\u2D88\u0DF4ar;\u69B5\u0200acit\u2D95\u2D98\u2DA5\u2DA8r\xF2\u1A80\u0100ir\u2D9D\u2DA0r;\u69BEoss;\u69BBn\xE5\u0E52;\u69C0\u0180aei\u2DB1\u2DB5\u2DB9cr;\u414Dga;\u43C9\u0180cdn\u2DC0\u2DC5\u01CDron;\u43BF;\u69B6pf;\uC000\u{1D560}\u0180ael\u2DD4\u2DD7\u01D2r;\u69B7rp;\u69B9\u0380;adiosv\u2DEA\u2DEB\u2DEE\u2E08\u2E0D\u2E10\u2E16\u6228r\xF2\u1A86\u0200;efm\u2DF7\u2DF8\u2E02\u2E05\u6A5Dr\u0100;o\u2DFE\u2DFF\u6134f\xBB\u2DFF\u803B\xAA\u40AA\u803B\xBA\u40BAgof;\u62B6r;\u6A56lope;\u6A57;\u6A5B\u0180clo\u2E1F\u2E21\u2E27\xF2\u2E01ash\u803B\xF8\u40F8l;\u6298i\u016C\u2E2F\u2E34de\u803B\xF5\u40F5es\u0100;a\u01DB\u2E3As;\u6A36ml\u803B\xF6\u40F6bar;\u633D\u0AE1\u2E5E\0\u2E7D\0\u2E80\u2E9D\0\u2EA2\u2EB9\0\0\u2ECB\u0E9C\0\u2F13\0\0\u2F2B\u2FBC\0\u2FC8r\u0200;ast\u0403\u2E67\u2E72\u0E85\u8100\xB6;l\u2E6D\u2E6E\u40B6le\xEC\u0403\u0269\u2E78\0\0\u2E7Bm;\u6AF3;\u6AFDy;\u443Fr\u0280cimpt\u2E8B\u2E8F\u2E93\u1865\u2E97nt;\u4025od;\u402Eil;\u6030enk;\u6031r;\uC000\u{1D52D}\u0180imo\u2EA8\u2EB0\u2EB4\u0100;v\u2EAD\u2EAE\u43C6;\u43D5ma\xF4\u0A76ne;\u660E\u0180;tv\u2EBF\u2EC0\u2EC8\u43C0chfork\xBB\u1FFD;\u43D6\u0100au\u2ECF\u2EDFn\u0100ck\u2ED5\u2EDDk\u0100;h\u21F4\u2EDB;\u610E\xF6\u21F4s\u0480;abcdemst\u2EF3\u2EF4\u1908\u2EF9\u2EFD\u2F04\u2F06\u2F0A\u2F0E\u402Bcir;\u6A23ir;\u6A22\u0100ou\u1D40\u2F02;\u6A25;\u6A72n\u80BB\xB1\u0E9Dim;\u6A26wo;\u6A27\u0180ipu\u2F19\u2F20\u2F25ntint;\u6A15f;\uC000\u{1D561}nd\u803B\xA3\u40A3\u0500;Eaceinosu\u0EC8\u2F3F\u2F41\u2F44\u2F47\u2F81\u2F89\u2F92\u2F7E\u2FB6;\u6AB3p;\u6AB7u\xE5\u0ED9\u0100;c\u0ECE\u2F4C\u0300;acens\u0EC8\u2F59\u2F5F\u2F66\u2F68\u2F7Eppro\xF8\u2F43urlye\xF1\u0ED9\xF1\u0ECE\u0180aes\u2F6F\u2F76\u2F7Approx;\u6AB9qq;\u6AB5im;\u62E8i\xED\u0EDFme\u0100;s\u2F88\u0EAE\u6032\u0180Eas\u2F78\u2F90\u2F7A\xF0\u2F75\u0180dfp\u0EEC\u2F99\u2FAF\u0180als\u2FA0\u2FA5\u2FAAlar;\u632Eine;\u6312urf;\u6313\u0100;t\u0EFB\u2FB4\xEF\u0EFBrel;\u62B0\u0100ci\u2FC0\u2FC5r;\uC000\u{1D4C5};\u43C8ncsp;\u6008\u0300fiopsu\u2FDA\u22E2\u2FDF\u2FE5\u2FEB\u2FF1r;\uC000\u{1D52E}pf;\uC000\u{1D562}rime;\u6057cr;\uC000\u{1D4C6}\u0180aeo\u2FF8\u3009\u3013t\u0100ei\u2FFE\u3005rnion\xF3\u06B0nt;\u6A16st\u0100;e\u3010\u3011\u403F\xF1\u1F19\xF4\u0F14\u0A80ABHabcdefhilmnoprstux\u3040\u3051\u3055\u3059\u30E0\u310E\u312B\u3147\u3162\u3172\u318E\u3206\u3215\u3224\u3229\u3258\u326E\u3272\u3290\u32B0\u32B7\u0180art\u3047\u304A\u304Cr\xF2\u10B3\xF2\u03DDail;\u691Car\xF2\u1C65ar;\u6964\u0380cdenqrt\u3068\u3075\u3078\u307F\u308F\u3094\u30CC\u0100eu\u306D\u3071;\uC000\u223D\u0331te;\u4155i\xE3\u116Emptyv;\u69B3g\u0200;del\u0FD1\u3089\u308B\u308D;\u6992;\u69A5\xE5\u0FD1uo\u803B\xBB\u40BBr\u0580;abcfhlpstw\u0FDC\u30AC\u30AF\u30B7\u30B9\u30BC\u30BE\u30C0\u30C3\u30C7\u30CAp;\u6975\u0100;f\u0FE0\u30B4s;\u6920;\u6933s;\u691E\xEB\u225D\xF0\u272El;\u6945im;\u6974l;\u61A3;\u619D\u0100ai\u30D1\u30D5il;\u691Ao\u0100;n\u30DB\u30DC\u6236al\xF3\u0F1E\u0180abr\u30E7\u30EA\u30EEr\xF2\u17E5rk;\u6773\u0100ak\u30F3\u30FDc\u0100ek\u30F9\u30FB;\u407D;\u405D\u0100es\u3102\u3104;\u698Cl\u0100du\u310A\u310C;\u698E;\u6990\u0200aeuy\u3117\u311C\u3127\u3129ron;\u4159\u0100di\u3121\u3125il;\u4157\xEC\u0FF2\xE2\u30FA;\u4440\u0200clqs\u3134\u3137\u313D\u3144a;\u6937dhar;\u6969uo\u0100;r\u020E\u020Dh;\u61B3\u0180acg\u314E\u315F\u0F44l\u0200;ips\u0F78\u3158\u315B\u109Cn\xE5\u10BBar\xF4\u0FA9t;\u65AD\u0180ilr\u3169\u1023\u316Esht;\u697D;\uC000\u{1D52F}\u0100ao\u3177\u3186r\u0100du\u317D\u317F\xBB\u047B\u0100;l\u1091\u3184;\u696C\u0100;v\u318B\u318C\u43C1;\u43F1\u0180gns\u3195\u31F9\u31FCht\u0300ahlrst\u31A4\u31B0\u31C2\u31D8\u31E4\u31EErrow\u0100;t\u0FDC\u31ADa\xE9\u30C8arpoon\u0100du\u31BB\u31BFow\xEE\u317Ep\xBB\u1092eft\u0100ah\u31CA\u31D0rrow\xF3\u0FEAarpoon\xF3\u0551ightarrows;\u61C9quigarro\xF7\u30CBhreetimes;\u62CCg;\u42DAingdotse\xF1\u1F32\u0180ahm\u320D\u3210\u3213r\xF2\u0FEAa\xF2\u0551;\u600Foust\u0100;a\u321E\u321F\u63B1che\xBB\u321Fmid;\u6AEE\u0200abpt\u3232\u323D\u3240\u3252\u0100nr\u3237\u323Ag;\u67EDr;\u61FEr\xEB\u1003\u0180afl\u3247\u324A\u324Er;\u6986;\uC000\u{1D563}us;\u6A2Eimes;\u6A35\u0100ap\u325D\u3267r\u0100;g\u3263\u3264\u4029t;\u6994olint;\u6A12ar\xF2\u31E3\u0200achq\u327B\u3280\u10BC\u3285quo;\u603Ar;\uC000\u{1D4C7}\u0100bu\u30FB\u328Ao\u0100;r\u0214\u0213\u0180hir\u3297\u329B\u32A0re\xE5\u31F8mes;\u62CAi\u0200;efl\u32AA\u1059\u1821\u32AB\u65B9tri;\u69CEluhar;\u6968;\u611E\u0D61\u32D5\u32DB\u32DF\u332C\u3338\u3371\0\u337A\u33A4\0\0\u33EC\u33F0\0\u3428\u3448\u345A\u34AD\u34B1\u34CA\u34F1\0\u3616\0\0\u3633cute;\u415Bqu\xEF\u27BA\u0500;Eaceinpsy\u11ED\u32F3\u32F5\u32FF\u3302\u330B\u330F\u331F\u3326\u3329;\u6AB4\u01F0\u32FA\0\u32FC;\u6AB8on;\u4161u\xE5\u11FE\u0100;d\u11F3\u3307il;\u415Frc;\u415D\u0180Eas\u3316\u3318\u331B;\u6AB6p;\u6ABAim;\u62E9olint;\u6A13i\xED\u1204;\u4441ot\u0180;be\u3334\u1D47\u3335\u62C5;\u6A66\u0380Aacmstx\u3346\u334A\u3357\u335B\u335E\u3363\u336Drr;\u61D8r\u0100hr\u3350\u3352\xEB\u2228\u0100;o\u0A36\u0A34t\u803B\xA7\u40A7i;\u403Bwar;\u6929m\u0100in\u3369\xF0nu\xF3\xF1t;\u6736r\u0100;o\u3376\u2055\uC000\u{1D530}\u0200acoy\u3382\u3386\u3391\u33A0rp;\u666F\u0100hy\u338B\u338Fcy;\u4449;\u4448rt\u026D\u3399\0\0\u339Ci\xE4\u1464ara\xEC\u2E6F\u803B\xAD\u40AD\u0100gm\u33A8\u33B4ma\u0180;fv\u33B1\u33B2\u33B2\u43C3;\u43C2\u0400;deglnpr\u12AB\u33C5\u33C9\u33CE\u33D6\u33DE\u33E1\u33E6ot;\u6A6A\u0100;q\u12B1\u12B0\u0100;E\u33D3\u33D4\u6A9E;\u6AA0\u0100;E\u33DB\u33DC\u6A9D;\u6A9Fe;\u6246lus;\u6A24arr;\u6972ar\xF2\u113D\u0200aeit\u33F8\u3408\u340F\u3417\u0100ls\u33FD\u3404lsetm\xE9\u336Ahp;\u6A33parsl;\u69E4\u0100dl\u1463\u3414e;\u6323\u0100;e\u341C\u341D\u6AAA\u0100;s\u3422\u3423\u6AAC;\uC000\u2AAC\uFE00\u0180flp\u342E\u3433\u3442tcy;\u444C\u0100;b\u3438\u3439\u402F\u0100;a\u343E\u343F\u69C4r;\u633Ff;\uC000\u{1D564}a\u0100dr\u344D\u0402es\u0100;u\u3454\u3455\u6660it\xBB\u3455\u0180csu\u3460\u3479\u349F\u0100au\u3465\u346Fp\u0100;s\u1188\u346B;\uC000\u2293\uFE00p\u0100;s\u11B4\u3475;\uC000\u2294\uFE00u\u0100bp\u347F\u348F\u0180;es\u1197\u119C\u3486et\u0100;e\u1197\u348D\xF1\u119D\u0180;es\u11A8\u11AD\u3496et\u0100;e\u11A8\u349D\xF1\u11AE\u0180;af\u117B\u34A6\u05B0r\u0165\u34AB\u05B1\xBB\u117Car\xF2\u1148\u0200cemt\u34B9\u34BE\u34C2\u34C5r;\uC000\u{1D4C8}tm\xEE\xF1i\xEC\u3415ar\xE6\u11BE\u0100ar\u34CE\u34D5r\u0100;f\u34D4\u17BF\u6606\u0100an\u34DA\u34EDight\u0100ep\u34E3\u34EApsilo\xEE\u1EE0h\xE9\u2EAFs\xBB\u2852\u0280bcmnp\u34FB\u355E\u1209\u358B\u358E\u0480;Edemnprs\u350E\u350F\u3511\u3515\u351E\u3523\u352C\u3531\u3536\u6282;\u6AC5ot;\u6ABD\u0100;d\u11DA\u351Aot;\u6AC3ult;\u6AC1\u0100Ee\u3528\u352A;\u6ACB;\u628Alus;\u6ABFarr;\u6979\u0180eiu\u353D\u3552\u3555t\u0180;en\u350E\u3545\u354Bq\u0100;q\u11DA\u350Feq\u0100;q\u352B\u3528m;\u6AC7\u0100bp\u355A\u355C;\u6AD5;\u6AD3c\u0300;acens\u11ED\u356C\u3572\u3579\u357B\u3326ppro\xF8\u32FAurlye\xF1\u11FE\xF1\u11F3\u0180aes\u3582\u3588\u331Bppro\xF8\u331Aq\xF1\u3317g;\u666A\u0680123;Edehlmnps\u35A9\u35AC\u35AF\u121C\u35B2\u35B4\u35C0\u35C9\u35D5\u35DA\u35DF\u35E8\u35ED\u803B\xB9\u40B9\u803B\xB2\u40B2\u803B\xB3\u40B3;\u6AC6\u0100os\u35B9\u35BCt;\u6ABEub;\u6AD8\u0100;d\u1222\u35C5ot;\u6AC4s\u0100ou\u35CF\u35D2l;\u67C9b;\u6AD7arr;\u697Bult;\u6AC2\u0100Ee\u35E4\u35E6;\u6ACC;\u628Blus;\u6AC0\u0180eiu\u35F4\u3609\u360Ct\u0180;en\u121C\u35FC\u3602q\u0100;q\u1222\u35B2eq\u0100;q\u35E7\u35E4m;\u6AC8\u0100bp\u3611\u3613;\u6AD4;\u6AD6\u0180Aan\u361C\u3620\u362Drr;\u61D9r\u0100hr\u3626\u3628\xEB\u222E\u0100;o\u0A2B\u0A29war;\u692Alig\u803B\xDF\u40DF\u0BE1\u3651\u365D\u3660\u12CE\u3673\u3679\0\u367E\u36C2\0\0\0\0\0\u36DB\u3703\0\u3709\u376C\0\0\0\u3787\u0272\u3656\0\0\u365Bget;\u6316;\u43C4r\xEB\u0E5F\u0180aey\u3666\u366B\u3670ron;\u4165dil;\u4163;\u4442lrec;\u6315r;\uC000\u{1D531}\u0200eiko\u3686\u369D\u36B5\u36BC\u01F2\u368B\0\u3691e\u01004f\u1284\u1281a\u0180;sv\u3698\u3699\u369B\u43B8ym;\u43D1\u0100cn\u36A2\u36B2k\u0100as\u36A8\u36AEppro\xF8\u12C1im\xBB\u12ACs\xF0\u129E\u0100as\u36BA\u36AE\xF0\u12C1rn\u803B\xFE\u40FE\u01EC\u031F\u36C6\u22E7es\u8180\xD7;bd\u36CF\u36D0\u36D8\u40D7\u0100;a\u190F\u36D5r;\u6A31;\u6A30\u0180eps\u36E1\u36E3\u3700\xE1\u2A4D\u0200;bcf\u0486\u36EC\u36F0\u36F4ot;\u6336ir;\u6AF1\u0100;o\u36F9\u36FC\uC000\u{1D565}rk;\u6ADA\xE1\u3362rime;\u6034\u0180aip\u370F\u3712\u3764d\xE5\u1248\u0380adempst\u3721\u374D\u3740\u3751\u3757\u375C\u375Fngle\u0280;dlqr\u3730\u3731\u3736\u3740\u3742\u65B5own\xBB\u1DBBeft\u0100;e\u2800\u373E\xF1\u092E;\u625Cight\u0100;e\u32AA\u374B\xF1\u105Aot;\u65ECinus;\u6A3Alus;\u6A39b;\u69CDime;\u6A3Bezium;\u63E2\u0180cht\u3772\u377D\u3781\u0100ry\u3777\u377B;\uC000\u{1D4C9};\u4446cy;\u445Brok;\u4167\u0100io\u378B\u378Ex\xF4\u1777head\u0100lr\u3797\u37A0eftarro\xF7\u084Fightarrow\xBB\u0F5D\u0900AHabcdfghlmoprstuw\u37D0\u37D3\u37D7\u37E4\u37F0\u37FC\u380E\u381C\u3823\u3834\u3851\u385D\u386B\u38A9\u38CC\u38D2\u38EA\u38F6r\xF2\u03EDar;\u6963\u0100cr\u37DC\u37E2ute\u803B\xFA\u40FA\xF2\u1150r\u01E3\u37EA\0\u37EDy;\u445Eve;\u416D\u0100iy\u37F5\u37FArc\u803B\xFB\u40FB;\u4443\u0180abh\u3803\u3806\u380Br\xF2\u13ADlac;\u4171a\xF2\u13C3\u0100ir\u3813\u3818sht;\u697E;\uC000\u{1D532}rave\u803B\xF9\u40F9\u0161\u3827\u3831r\u0100lr\u382C\u382E\xBB\u0957\xBB\u1083lk;\u6580\u0100ct\u3839\u384D\u026F\u383F\0\0\u384Arn\u0100;e\u3845\u3846\u631Cr\xBB\u3846op;\u630Fri;\u65F8\u0100al\u3856\u385Acr;\u416B\u80BB\xA8\u0349\u0100gp\u3862\u3866on;\u4173f;\uC000\u{1D566}\u0300adhlsu\u114B\u3878\u387D\u1372\u3891\u38A0own\xE1\u13B3arpoon\u0100lr\u3888\u388Cef\xF4\u382Digh\xF4\u382Fi\u0180;hl\u3899\u389A\u389C\u43C5\xBB\u13FAon\xBB\u389Aparrows;\u61C8\u0180cit\u38B0\u38C4\u38C8\u026F\u38B6\0\0\u38C1rn\u0100;e\u38BC\u38BD\u631Dr\xBB\u38BDop;\u630Eng;\u416Fri;\u65F9cr;\uC000\u{1D4CA}\u0180dir\u38D9\u38DD\u38E2ot;\u62F0lde;\u4169i\u0100;f\u3730\u38E8\xBB\u1813\u0100am\u38EF\u38F2r\xF2\u38A8l\u803B\xFC\u40FCangle;\u69A7\u0780ABDacdeflnoprsz\u391C\u391F\u3929\u392D\u39B5\u39B8\u39BD\u39DF\u39E4\u39E8\u39F3\u39F9\u39FD\u3A01\u3A20r\xF2\u03F7ar\u0100;v\u3926\u3927\u6AE8;\u6AE9as\xE8\u03E1\u0100nr\u3932\u3937grt;\u699C\u0380eknprst\u34E3\u3946\u394B\u3952\u395D\u3964\u3996app\xE1\u2415othin\xE7\u1E96\u0180hir\u34EB\u2EC8\u3959op\xF4\u2FB5\u0100;h\u13B7\u3962\xEF\u318D\u0100iu\u3969\u396Dgm\xE1\u33B3\u0100bp\u3972\u3984setneq\u0100;q\u397D\u3980\uC000\u228A\uFE00;\uC000\u2ACB\uFE00setneq\u0100;q\u398F\u3992\uC000\u228B\uFE00;\uC000\u2ACC\uFE00\u0100hr\u399B\u399Fet\xE1\u369Ciangle\u0100lr\u39AA\u39AFeft\xBB\u0925ight\xBB\u1051y;\u4432ash\xBB\u1036\u0180elr\u39C4\u39D2\u39D7\u0180;be\u2DEA\u39CB\u39CFar;\u62BBq;\u625Alip;\u62EE\u0100bt\u39DC\u1468a\xF2\u1469r;\uC000\u{1D533}tr\xE9\u39AEsu\u0100bp\u39EF\u39F1\xBB\u0D1C\xBB\u0D59pf;\uC000\u{1D567}ro\xF0\u0EFBtr\xE9\u39B4\u0100cu\u3A06\u3A0Br;\uC000\u{1D4CB}\u0100bp\u3A10\u3A18n\u0100Ee\u3980\u3A16\xBB\u397En\u0100Ee\u3992\u3A1E\xBB\u3990igzag;\u699A\u0380cefoprs\u3A36\u3A3B\u3A56\u3A5B\u3A54\u3A61\u3A6Airc;\u4175\u0100di\u3A40\u3A51\u0100bg\u3A45\u3A49ar;\u6A5Fe\u0100;q\u15FA\u3A4F;\u6259erp;\u6118r;\uC000\u{1D534}pf;\uC000\u{1D568}\u0100;e\u1479\u3A66at\xE8\u1479cr;\uC000\u{1D4CC}\u0AE3\u178E\u3A87\0\u3A8B\0\u3A90\u3A9B\0\0\u3A9D\u3AA8\u3AAB\u3AAF\0\0\u3AC3\u3ACE\0\u3AD8\u17DC\u17DFtr\xE9\u17D1r;\uC000\u{1D535}\u0100Aa\u3A94\u3A97r\xF2\u03C3r\xF2\u09F6;\u43BE\u0100Aa\u3AA1\u3AA4r\xF2\u03B8r\xF2\u09EBa\xF0\u2713is;\u62FB\u0180dpt\u17A4\u3AB5\u3ABE\u0100fl\u3ABA\u17A9;\uC000\u{1D569}im\xE5\u17B2\u0100Aa\u3AC7\u3ACAr\xF2\u03CEr\xF2\u0A01\u0100cq\u3AD2\u17B8r;\uC000\u{1D4CD}\u0100pt\u17D6\u3ADCr\xE9\u17D4\u0400acefiosu\u3AF0\u3AFD\u3B08\u3B0C\u3B11\u3B15\u3B1B\u3B21c\u0100uy\u3AF6\u3AFBte\u803B\xFD\u40FD;\u444F\u0100iy\u3B02\u3B06rc;\u4177;\u444Bn\u803B\xA5\u40A5r;\uC000\u{1D536}cy;\u4457pf;\uC000\u{1D56A}cr;\uC000\u{1D4CE}\u0100cm\u3B26\u3B29y;\u444El\u803B\xFF\u40FF\u0500acdefhiosw\u3B42\u3B48\u3B54\u3B58\u3B64\u3B69\u3B6D\u3B74\u3B7A\u3B80cute;\u417A\u0100ay\u3B4D\u3B52ron;\u417E;\u4437ot;\u417C\u0100et\u3B5D\u3B61tr\xE6\u155Fa;\u43B6r;\uC000\u{1D537}cy;\u4436grarr;\u61DDpf;\uC000\u{1D56B}cr;\uC000\u{1D4CF}\u0100jn\u3B85\u3B87;\u600Dj;\u600C'.split("").map((c) => c.charCodeAt(0)) + ); + } +}); + +// node_modules/entities/dist/esm/generated/decode-data-xml.js +var init_decode_data_xml = __esm({ + "node_modules/entities/dist/esm/generated/decode-data-xml.js"() { + } +}); + +// node_modules/entities/dist/esm/decode-codepoint.js +function replaceCodePoint(codePoint) { + var _a2; + if (codePoint >= 55296 && codePoint <= 57343 || codePoint > 1114111) { + return 65533; + } + return (_a2 = decodeMap.get(codePoint)) !== null && _a2 !== void 0 ? _a2 : codePoint; +} +var _a, decodeMap, fromCodePoint; +var init_decode_codepoint = __esm({ + "node_modules/entities/dist/esm/decode-codepoint.js"() { + decodeMap = /* @__PURE__ */ new Map([ + [0, 65533], + // C1 Unicode control character reference replacements + [128, 8364], + [130, 8218], + [131, 402], + [132, 8222], + [133, 8230], + [134, 8224], + [135, 8225], + [136, 710], + [137, 8240], + [138, 352], + [139, 8249], + [140, 338], + [142, 381], + [145, 8216], + [146, 8217], + [147, 8220], + [148, 8221], + [149, 8226], + [150, 8211], + [151, 8212], + [152, 732], + [153, 8482], + [154, 353], + [155, 8250], + [156, 339], + [158, 382], + [159, 376] + ]); + fromCodePoint = // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, n/no-unsupported-features/es-builtins + (_a = String.fromCodePoint) !== null && _a !== void 0 ? _a : function(codePoint) { + let output = ""; + if (codePoint > 65535) { + codePoint -= 65536; + output += String.fromCharCode(codePoint >>> 10 & 1023 | 55296); + codePoint = 56320 | codePoint & 1023; + } + output += String.fromCharCode(codePoint); + return output; + }; + } +}); + +// node_modules/entities/dist/esm/decode.js +function isNumber(code) { + return code >= CharCodes.ZERO && code <= CharCodes.NINE; +} +function isHexadecimalCharacter(code) { + return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_F || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_F; +} +function isAsciiAlphaNumeric(code) { + return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_Z || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_Z || isNumber(code); +} +function isEntityInAttributeInvalidEnd(code) { + return code === CharCodes.EQUALS || isAsciiAlphaNumeric(code); +} +function determineBranch(decodeTree, current, nodeIndex, char) { + const branchCount = (current & BinTrieFlags.BRANCH_LENGTH) >> 7; + const jumpOffset = current & BinTrieFlags.JUMP_TABLE; + if (branchCount === 0) { + return jumpOffset !== 0 && char === jumpOffset ? nodeIndex : -1; + } + if (jumpOffset) { + const value = char - jumpOffset; + return value < 0 || value >= branchCount ? -1 : decodeTree[nodeIndex + value] - 1; + } + let lo = nodeIndex; + let hi = lo + branchCount - 1; + while (lo <= hi) { + const mid = lo + hi >>> 1; + const midValue = decodeTree[mid]; + if (midValue < char) { + lo = mid + 1; + } else if (midValue > char) { + hi = mid - 1; + } else { + return decodeTree[mid + branchCount]; + } + } + return -1; +} +var CharCodes, TO_LOWER_BIT, BinTrieFlags, EntityDecoderState, DecodingMode, EntityDecoder; +var init_decode = __esm({ + "node_modules/entities/dist/esm/decode.js"() { + init_decode_data_html(); + init_decode_data_xml(); + init_decode_codepoint(); + init_decode_data_html(); + init_decode_data_xml(); + init_decode_codepoint(); + (function(CharCodes2) { + CharCodes2[CharCodes2["NUM"] = 35] = "NUM"; + CharCodes2[CharCodes2["SEMI"] = 59] = "SEMI"; + CharCodes2[CharCodes2["EQUALS"] = 61] = "EQUALS"; + CharCodes2[CharCodes2["ZERO"] = 48] = "ZERO"; + CharCodes2[CharCodes2["NINE"] = 57] = "NINE"; + CharCodes2[CharCodes2["LOWER_A"] = 97] = "LOWER_A"; + CharCodes2[CharCodes2["LOWER_F"] = 102] = "LOWER_F"; + CharCodes2[CharCodes2["LOWER_X"] = 120] = "LOWER_X"; + CharCodes2[CharCodes2["LOWER_Z"] = 122] = "LOWER_Z"; + CharCodes2[CharCodes2["UPPER_A"] = 65] = "UPPER_A"; + CharCodes2[CharCodes2["UPPER_F"] = 70] = "UPPER_F"; + CharCodes2[CharCodes2["UPPER_Z"] = 90] = "UPPER_Z"; + })(CharCodes || (CharCodes = {})); + TO_LOWER_BIT = 32; + (function(BinTrieFlags2) { + BinTrieFlags2[BinTrieFlags2["VALUE_LENGTH"] = 49152] = "VALUE_LENGTH"; + BinTrieFlags2[BinTrieFlags2["BRANCH_LENGTH"] = 16256] = "BRANCH_LENGTH"; + BinTrieFlags2[BinTrieFlags2["JUMP_TABLE"] = 127] = "JUMP_TABLE"; + })(BinTrieFlags || (BinTrieFlags = {})); + (function(EntityDecoderState2) { + EntityDecoderState2[EntityDecoderState2["EntityStart"] = 0] = "EntityStart"; + EntityDecoderState2[EntityDecoderState2["NumericStart"] = 1] = "NumericStart"; + EntityDecoderState2[EntityDecoderState2["NumericDecimal"] = 2] = "NumericDecimal"; + EntityDecoderState2[EntityDecoderState2["NumericHex"] = 3] = "NumericHex"; + EntityDecoderState2[EntityDecoderState2["NamedEntity"] = 4] = "NamedEntity"; + })(EntityDecoderState || (EntityDecoderState = {})); + (function(DecodingMode2) { + DecodingMode2[DecodingMode2["Legacy"] = 0] = "Legacy"; + DecodingMode2[DecodingMode2["Strict"] = 1] = "Strict"; + DecodingMode2[DecodingMode2["Attribute"] = 2] = "Attribute"; + })(DecodingMode || (DecodingMode = {})); + EntityDecoder = class { + constructor(decodeTree, emitCodePoint, errors) { + this.decodeTree = decodeTree; + this.emitCodePoint = emitCodePoint; + this.errors = errors; + this.state = EntityDecoderState.EntityStart; + this.consumed = 1; + this.result = 0; + this.treeIndex = 0; + this.excess = 1; + this.decodeMode = DecodingMode.Strict; + } + /** Resets the instance to make it reusable. */ + startEntity(decodeMode) { + this.decodeMode = decodeMode; + this.state = EntityDecoderState.EntityStart; + this.result = 0; + this.treeIndex = 0; + this.excess = 1; + this.consumed = 1; + } + /** + * Write an entity to the decoder. This can be called multiple times with partial entities. + * If the entity is incomplete, the decoder will return -1. + * + * Mirrors the implementation of `getDecoder`, but with the ability to stop decoding if the + * entity is incomplete, and resume when the next string is written. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The offset at which the entity begins. Should be 0 if this is not the first call. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + write(input, offset) { + switch (this.state) { + case EntityDecoderState.EntityStart: { + if (input.charCodeAt(offset) === CharCodes.NUM) { + this.state = EntityDecoderState.NumericStart; + this.consumed += 1; + return this.stateNumericStart(input, offset + 1); + } + this.state = EntityDecoderState.NamedEntity; + return this.stateNamedEntity(input, offset); + } + case EntityDecoderState.NumericStart: { + return this.stateNumericStart(input, offset); + } + case EntityDecoderState.NumericDecimal: { + return this.stateNumericDecimal(input, offset); + } + case EntityDecoderState.NumericHex: { + return this.stateNumericHex(input, offset); + } + case EntityDecoderState.NamedEntity: { + return this.stateNamedEntity(input, offset); + } + } + } + /** + * Switches between the numeric decimal and hexadecimal states. + * + * Equivalent to the `Numeric character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericStart(input, offset) { + if (offset >= input.length) { + return -1; + } + if ((input.charCodeAt(offset) | TO_LOWER_BIT) === CharCodes.LOWER_X) { + this.state = EntityDecoderState.NumericHex; + this.consumed += 1; + return this.stateNumericHex(input, offset + 1); + } + this.state = EntityDecoderState.NumericDecimal; + return this.stateNumericDecimal(input, offset); + } + addToNumericResult(input, start, end, base) { + if (start !== end) { + const digitCount = end - start; + this.result = this.result * Math.pow(base, digitCount) + Number.parseInt(input.substr(start, digitCount), base); + this.consumed += digitCount; + } + } + /** + * Parses a hexadecimal numeric entity. + * + * Equivalent to the `Hexademical character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericHex(input, offset) { + const startIndex = offset; + while (offset < input.length) { + const char = input.charCodeAt(offset); + if (isNumber(char) || isHexadecimalCharacter(char)) { + offset += 1; + } else { + this.addToNumericResult(input, startIndex, offset, 16); + return this.emitNumericEntity(char, 3); + } + } + this.addToNumericResult(input, startIndex, offset, 16); + return -1; + } + /** + * Parses a decimal numeric entity. + * + * Equivalent to the `Decimal character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericDecimal(input, offset) { + const startIndex = offset; + while (offset < input.length) { + const char = input.charCodeAt(offset); + if (isNumber(char)) { + offset += 1; + } else { + this.addToNumericResult(input, startIndex, offset, 10); + return this.emitNumericEntity(char, 2); + } + } + this.addToNumericResult(input, startIndex, offset, 10); + return -1; + } + /** + * Validate and emit a numeric entity. + * + * Implements the logic from the `Hexademical character reference start + * state` and `Numeric character reference end state` in the HTML spec. + * + * @param lastCp The last code point of the entity. Used to see if the + * entity was terminated with a semicolon. + * @param expectedLength The minimum number of characters that should be + * consumed. Used to validate that at least one digit + * was consumed. + * @returns The number of characters that were consumed. + */ + emitNumericEntity(lastCp, expectedLength) { + var _a2; + if (this.consumed <= expectedLength) { + (_a2 = this.errors) === null || _a2 === void 0 ? void 0 : _a2.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + if (lastCp === CharCodes.SEMI) { + this.consumed += 1; + } else if (this.decodeMode === DecodingMode.Strict) { + return 0; + } + this.emitCodePoint(replaceCodePoint(this.result), this.consumed); + if (this.errors) { + if (lastCp !== CharCodes.SEMI) { + this.errors.missingSemicolonAfterCharacterReference(); + } + this.errors.validateNumericCharacterReference(this.result); + } + return this.consumed; + } + /** + * Parses a named entity. + * + * Equivalent to the `Named character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNamedEntity(input, offset) { + const { decodeTree } = this; + let current = decodeTree[this.treeIndex]; + let valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + for (; offset < input.length; offset++, this.excess++) { + const char = input.charCodeAt(offset); + this.treeIndex = determineBranch(decodeTree, current, this.treeIndex + Math.max(1, valueLength), char); + if (this.treeIndex < 0) { + return this.result === 0 || // If we are parsing an attribute + this.decodeMode === DecodingMode.Attribute && // We shouldn't have consumed any characters after the entity, + (valueLength === 0 || // And there should be no invalid characters. + isEntityInAttributeInvalidEnd(char)) ? 0 : this.emitNotTerminatedNamedEntity(); + } + current = decodeTree[this.treeIndex]; + valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + if (valueLength !== 0) { + if (char === CharCodes.SEMI) { + return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess); + } + if (this.decodeMode !== DecodingMode.Strict) { + this.result = this.treeIndex; + this.consumed += this.excess; + this.excess = 0; + } + } + } + return -1; + } + /** + * Emit a named entity that was not terminated with a semicolon. + * + * @returns The number of characters consumed. + */ + emitNotTerminatedNamedEntity() { + var _a2; + const { result, decodeTree } = this; + const valueLength = (decodeTree[result] & BinTrieFlags.VALUE_LENGTH) >> 14; + this.emitNamedEntityData(result, valueLength, this.consumed); + (_a2 = this.errors) === null || _a2 === void 0 ? void 0 : _a2.missingSemicolonAfterCharacterReference(); + return this.consumed; + } + /** + * Emit a named entity. + * + * @param result The index of the entity in the decode tree. + * @param valueLength The number of bytes in the entity. + * @param consumed The number of characters consumed. + * + * @returns The number of characters consumed. + */ + emitNamedEntityData(result, valueLength, consumed) { + const { decodeTree } = this; + this.emitCodePoint(valueLength === 1 ? decodeTree[result] & ~BinTrieFlags.VALUE_LENGTH : decodeTree[result + 1], consumed); + if (valueLength === 3) { + this.emitCodePoint(decodeTree[result + 2], consumed); + } + return consumed; + } + /** + * Signal to the parser that the end of the input was reached. + * + * Remaining data will be emitted and relevant errors will be produced. + * + * @returns The number of characters consumed. + */ + end() { + var _a2; + switch (this.state) { + case EntityDecoderState.NamedEntity: { + return this.result !== 0 && (this.decodeMode !== DecodingMode.Attribute || this.result === this.treeIndex) ? this.emitNotTerminatedNamedEntity() : 0; + } + // Otherwise, emit a numeric entity if we have one. + case EntityDecoderState.NumericDecimal: { + return this.emitNumericEntity(0, 2); + } + case EntityDecoderState.NumericHex: { + return this.emitNumericEntity(0, 3); + } + case EntityDecoderState.NumericStart: { + (_a2 = this.errors) === null || _a2 === void 0 ? void 0 : _a2.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + case EntityDecoderState.EntityStart: { + return 0; + } + } + } + }; + } +}); + +// node_modules/parse5/dist/common/html.js +function getTagID(tagName) { + var _a2; + return (_a2 = TAG_NAME_TO_ID.get(tagName)) !== null && _a2 !== void 0 ? _a2 : TAG_ID.UNKNOWN; +} +function hasUnescapedText(tn, scriptingEnabled) { + return UNESCAPED_TEXT.has(tn) || scriptingEnabled && tn === TAG_NAMES.NOSCRIPT; +} +var NS, ATTRS, DOCUMENT_MODE, TAG_NAMES, TAG_ID, TAG_NAME_TO_ID, $, SPECIAL_ELEMENTS, NUMBERED_HEADERS, UNESCAPED_TEXT; +var init_html = __esm({ + "node_modules/parse5/dist/common/html.js"() { + (function(NS2) { + NS2["HTML"] = "http://www.w3.org/1999/xhtml"; + NS2["MATHML"] = "http://www.w3.org/1998/Math/MathML"; + NS2["SVG"] = "http://www.w3.org/2000/svg"; + NS2["XLINK"] = "http://www.w3.org/1999/xlink"; + NS2["XML"] = "http://www.w3.org/XML/1998/namespace"; + NS2["XMLNS"] = "http://www.w3.org/2000/xmlns/"; + })(NS || (NS = {})); + (function(ATTRS2) { + ATTRS2["TYPE"] = "type"; + ATTRS2["ACTION"] = "action"; + ATTRS2["ENCODING"] = "encoding"; + ATTRS2["PROMPT"] = "prompt"; + ATTRS2["NAME"] = "name"; + ATTRS2["COLOR"] = "color"; + ATTRS2["FACE"] = "face"; + ATTRS2["SIZE"] = "size"; + })(ATTRS || (ATTRS = {})); + (function(DOCUMENT_MODE2) { + DOCUMENT_MODE2["NO_QUIRKS"] = "no-quirks"; + DOCUMENT_MODE2["QUIRKS"] = "quirks"; + DOCUMENT_MODE2["LIMITED_QUIRKS"] = "limited-quirks"; + })(DOCUMENT_MODE || (DOCUMENT_MODE = {})); + (function(TAG_NAMES2) { + TAG_NAMES2["A"] = "a"; + TAG_NAMES2["ADDRESS"] = "address"; + TAG_NAMES2["ANNOTATION_XML"] = "annotation-xml"; + TAG_NAMES2["APPLET"] = "applet"; + TAG_NAMES2["AREA"] = "area"; + TAG_NAMES2["ARTICLE"] = "article"; + TAG_NAMES2["ASIDE"] = "aside"; + TAG_NAMES2["B"] = "b"; + TAG_NAMES2["BASE"] = "base"; + TAG_NAMES2["BASEFONT"] = "basefont"; + TAG_NAMES2["BGSOUND"] = "bgsound"; + TAG_NAMES2["BIG"] = "big"; + TAG_NAMES2["BLOCKQUOTE"] = "blockquote"; + TAG_NAMES2["BODY"] = "body"; + TAG_NAMES2["BR"] = "br"; + TAG_NAMES2["BUTTON"] = "button"; + TAG_NAMES2["CAPTION"] = "caption"; + TAG_NAMES2["CENTER"] = "center"; + TAG_NAMES2["CODE"] = "code"; + TAG_NAMES2["COL"] = "col"; + TAG_NAMES2["COLGROUP"] = "colgroup"; + TAG_NAMES2["DD"] = "dd"; + TAG_NAMES2["DESC"] = "desc"; + TAG_NAMES2["DETAILS"] = "details"; + TAG_NAMES2["DIALOG"] = "dialog"; + TAG_NAMES2["DIR"] = "dir"; + TAG_NAMES2["DIV"] = "div"; + TAG_NAMES2["DL"] = "dl"; + TAG_NAMES2["DT"] = "dt"; + TAG_NAMES2["EM"] = "em"; + TAG_NAMES2["EMBED"] = "embed"; + TAG_NAMES2["FIELDSET"] = "fieldset"; + TAG_NAMES2["FIGCAPTION"] = "figcaption"; + TAG_NAMES2["FIGURE"] = "figure"; + TAG_NAMES2["FONT"] = "font"; + TAG_NAMES2["FOOTER"] = "footer"; + TAG_NAMES2["FOREIGN_OBJECT"] = "foreignObject"; + TAG_NAMES2["FORM"] = "form"; + TAG_NAMES2["FRAME"] = "frame"; + TAG_NAMES2["FRAMESET"] = "frameset"; + TAG_NAMES2["H1"] = "h1"; + TAG_NAMES2["H2"] = "h2"; + TAG_NAMES2["H3"] = "h3"; + TAG_NAMES2["H4"] = "h4"; + TAG_NAMES2["H5"] = "h5"; + TAG_NAMES2["H6"] = "h6"; + TAG_NAMES2["HEAD"] = "head"; + TAG_NAMES2["HEADER"] = "header"; + TAG_NAMES2["HGROUP"] = "hgroup"; + TAG_NAMES2["HR"] = "hr"; + TAG_NAMES2["HTML"] = "html"; + TAG_NAMES2["I"] = "i"; + TAG_NAMES2["IMG"] = "img"; + TAG_NAMES2["IMAGE"] = "image"; + TAG_NAMES2["INPUT"] = "input"; + TAG_NAMES2["IFRAME"] = "iframe"; + TAG_NAMES2["KEYGEN"] = "keygen"; + TAG_NAMES2["LABEL"] = "label"; + TAG_NAMES2["LI"] = "li"; + TAG_NAMES2["LINK"] = "link"; + TAG_NAMES2["LISTING"] = "listing"; + TAG_NAMES2["MAIN"] = "main"; + TAG_NAMES2["MALIGNMARK"] = "malignmark"; + TAG_NAMES2["MARQUEE"] = "marquee"; + TAG_NAMES2["MATH"] = "math"; + TAG_NAMES2["MENU"] = "menu"; + TAG_NAMES2["META"] = "meta"; + TAG_NAMES2["MGLYPH"] = "mglyph"; + TAG_NAMES2["MI"] = "mi"; + TAG_NAMES2["MO"] = "mo"; + TAG_NAMES2["MN"] = "mn"; + TAG_NAMES2["MS"] = "ms"; + TAG_NAMES2["MTEXT"] = "mtext"; + TAG_NAMES2["NAV"] = "nav"; + TAG_NAMES2["NOBR"] = "nobr"; + TAG_NAMES2["NOFRAMES"] = "noframes"; + TAG_NAMES2["NOEMBED"] = "noembed"; + TAG_NAMES2["NOSCRIPT"] = "noscript"; + TAG_NAMES2["OBJECT"] = "object"; + TAG_NAMES2["OL"] = "ol"; + TAG_NAMES2["OPTGROUP"] = "optgroup"; + TAG_NAMES2["OPTION"] = "option"; + TAG_NAMES2["P"] = "p"; + TAG_NAMES2["PARAM"] = "param"; + TAG_NAMES2["PLAINTEXT"] = "plaintext"; + TAG_NAMES2["PRE"] = "pre"; + TAG_NAMES2["RB"] = "rb"; + TAG_NAMES2["RP"] = "rp"; + TAG_NAMES2["RT"] = "rt"; + TAG_NAMES2["RTC"] = "rtc"; + TAG_NAMES2["RUBY"] = "ruby"; + TAG_NAMES2["S"] = "s"; + TAG_NAMES2["SCRIPT"] = "script"; + TAG_NAMES2["SEARCH"] = "search"; + TAG_NAMES2["SECTION"] = "section"; + TAG_NAMES2["SELECT"] = "select"; + TAG_NAMES2["SOURCE"] = "source"; + TAG_NAMES2["SMALL"] = "small"; + TAG_NAMES2["SPAN"] = "span"; + TAG_NAMES2["STRIKE"] = "strike"; + TAG_NAMES2["STRONG"] = "strong"; + TAG_NAMES2["STYLE"] = "style"; + TAG_NAMES2["SUB"] = "sub"; + TAG_NAMES2["SUMMARY"] = "summary"; + TAG_NAMES2["SUP"] = "sup"; + TAG_NAMES2["TABLE"] = "table"; + TAG_NAMES2["TBODY"] = "tbody"; + TAG_NAMES2["TEMPLATE"] = "template"; + TAG_NAMES2["TEXTAREA"] = "textarea"; + TAG_NAMES2["TFOOT"] = "tfoot"; + TAG_NAMES2["TD"] = "td"; + TAG_NAMES2["TH"] = "th"; + TAG_NAMES2["THEAD"] = "thead"; + TAG_NAMES2["TITLE"] = "title"; + TAG_NAMES2["TR"] = "tr"; + TAG_NAMES2["TRACK"] = "track"; + TAG_NAMES2["TT"] = "tt"; + TAG_NAMES2["U"] = "u"; + TAG_NAMES2["UL"] = "ul"; + TAG_NAMES2["SVG"] = "svg"; + TAG_NAMES2["VAR"] = "var"; + TAG_NAMES2["WBR"] = "wbr"; + TAG_NAMES2["XMP"] = "xmp"; + })(TAG_NAMES || (TAG_NAMES = {})); + (function(TAG_ID2) { + TAG_ID2[TAG_ID2["UNKNOWN"] = 0] = "UNKNOWN"; + TAG_ID2[TAG_ID2["A"] = 1] = "A"; + TAG_ID2[TAG_ID2["ADDRESS"] = 2] = "ADDRESS"; + TAG_ID2[TAG_ID2["ANNOTATION_XML"] = 3] = "ANNOTATION_XML"; + TAG_ID2[TAG_ID2["APPLET"] = 4] = "APPLET"; + TAG_ID2[TAG_ID2["AREA"] = 5] = "AREA"; + TAG_ID2[TAG_ID2["ARTICLE"] = 6] = "ARTICLE"; + TAG_ID2[TAG_ID2["ASIDE"] = 7] = "ASIDE"; + TAG_ID2[TAG_ID2["B"] = 8] = "B"; + TAG_ID2[TAG_ID2["BASE"] = 9] = "BASE"; + TAG_ID2[TAG_ID2["BASEFONT"] = 10] = "BASEFONT"; + TAG_ID2[TAG_ID2["BGSOUND"] = 11] = "BGSOUND"; + TAG_ID2[TAG_ID2["BIG"] = 12] = "BIG"; + TAG_ID2[TAG_ID2["BLOCKQUOTE"] = 13] = "BLOCKQUOTE"; + TAG_ID2[TAG_ID2["BODY"] = 14] = "BODY"; + TAG_ID2[TAG_ID2["BR"] = 15] = "BR"; + TAG_ID2[TAG_ID2["BUTTON"] = 16] = "BUTTON"; + TAG_ID2[TAG_ID2["CAPTION"] = 17] = "CAPTION"; + TAG_ID2[TAG_ID2["CENTER"] = 18] = "CENTER"; + TAG_ID2[TAG_ID2["CODE"] = 19] = "CODE"; + TAG_ID2[TAG_ID2["COL"] = 20] = "COL"; + TAG_ID2[TAG_ID2["COLGROUP"] = 21] = "COLGROUP"; + TAG_ID2[TAG_ID2["DD"] = 22] = "DD"; + TAG_ID2[TAG_ID2["DESC"] = 23] = "DESC"; + TAG_ID2[TAG_ID2["DETAILS"] = 24] = "DETAILS"; + TAG_ID2[TAG_ID2["DIALOG"] = 25] = "DIALOG"; + TAG_ID2[TAG_ID2["DIR"] = 26] = "DIR"; + TAG_ID2[TAG_ID2["DIV"] = 27] = "DIV"; + TAG_ID2[TAG_ID2["DL"] = 28] = "DL"; + TAG_ID2[TAG_ID2["DT"] = 29] = "DT"; + TAG_ID2[TAG_ID2["EM"] = 30] = "EM"; + TAG_ID2[TAG_ID2["EMBED"] = 31] = "EMBED"; + TAG_ID2[TAG_ID2["FIELDSET"] = 32] = "FIELDSET"; + TAG_ID2[TAG_ID2["FIGCAPTION"] = 33] = "FIGCAPTION"; + TAG_ID2[TAG_ID2["FIGURE"] = 34] = "FIGURE"; + TAG_ID2[TAG_ID2["FONT"] = 35] = "FONT"; + TAG_ID2[TAG_ID2["FOOTER"] = 36] = "FOOTER"; + TAG_ID2[TAG_ID2["FOREIGN_OBJECT"] = 37] = "FOREIGN_OBJECT"; + TAG_ID2[TAG_ID2["FORM"] = 38] = "FORM"; + TAG_ID2[TAG_ID2["FRAME"] = 39] = "FRAME"; + TAG_ID2[TAG_ID2["FRAMESET"] = 40] = "FRAMESET"; + TAG_ID2[TAG_ID2["H1"] = 41] = "H1"; + TAG_ID2[TAG_ID2["H2"] = 42] = "H2"; + TAG_ID2[TAG_ID2["H3"] = 43] = "H3"; + TAG_ID2[TAG_ID2["H4"] = 44] = "H4"; + TAG_ID2[TAG_ID2["H5"] = 45] = "H5"; + TAG_ID2[TAG_ID2["H6"] = 46] = "H6"; + TAG_ID2[TAG_ID2["HEAD"] = 47] = "HEAD"; + TAG_ID2[TAG_ID2["HEADER"] = 48] = "HEADER"; + TAG_ID2[TAG_ID2["HGROUP"] = 49] = "HGROUP"; + TAG_ID2[TAG_ID2["HR"] = 50] = "HR"; + TAG_ID2[TAG_ID2["HTML"] = 51] = "HTML"; + TAG_ID2[TAG_ID2["I"] = 52] = "I"; + TAG_ID2[TAG_ID2["IMG"] = 53] = "IMG"; + TAG_ID2[TAG_ID2["IMAGE"] = 54] = "IMAGE"; + TAG_ID2[TAG_ID2["INPUT"] = 55] = "INPUT"; + TAG_ID2[TAG_ID2["IFRAME"] = 56] = "IFRAME"; + TAG_ID2[TAG_ID2["KEYGEN"] = 57] = "KEYGEN"; + TAG_ID2[TAG_ID2["LABEL"] = 58] = "LABEL"; + TAG_ID2[TAG_ID2["LI"] = 59] = "LI"; + TAG_ID2[TAG_ID2["LINK"] = 60] = "LINK"; + TAG_ID2[TAG_ID2["LISTING"] = 61] = "LISTING"; + TAG_ID2[TAG_ID2["MAIN"] = 62] = "MAIN"; + TAG_ID2[TAG_ID2["MALIGNMARK"] = 63] = "MALIGNMARK"; + TAG_ID2[TAG_ID2["MARQUEE"] = 64] = "MARQUEE"; + TAG_ID2[TAG_ID2["MATH"] = 65] = "MATH"; + TAG_ID2[TAG_ID2["MENU"] = 66] = "MENU"; + TAG_ID2[TAG_ID2["META"] = 67] = "META"; + TAG_ID2[TAG_ID2["MGLYPH"] = 68] = "MGLYPH"; + TAG_ID2[TAG_ID2["MI"] = 69] = "MI"; + TAG_ID2[TAG_ID2["MO"] = 70] = "MO"; + TAG_ID2[TAG_ID2["MN"] = 71] = "MN"; + TAG_ID2[TAG_ID2["MS"] = 72] = "MS"; + TAG_ID2[TAG_ID2["MTEXT"] = 73] = "MTEXT"; + TAG_ID2[TAG_ID2["NAV"] = 74] = "NAV"; + TAG_ID2[TAG_ID2["NOBR"] = 75] = "NOBR"; + TAG_ID2[TAG_ID2["NOFRAMES"] = 76] = "NOFRAMES"; + TAG_ID2[TAG_ID2["NOEMBED"] = 77] = "NOEMBED"; + TAG_ID2[TAG_ID2["NOSCRIPT"] = 78] = "NOSCRIPT"; + TAG_ID2[TAG_ID2["OBJECT"] = 79] = "OBJECT"; + TAG_ID2[TAG_ID2["OL"] = 80] = "OL"; + TAG_ID2[TAG_ID2["OPTGROUP"] = 81] = "OPTGROUP"; + TAG_ID2[TAG_ID2["OPTION"] = 82] = "OPTION"; + TAG_ID2[TAG_ID2["P"] = 83] = "P"; + TAG_ID2[TAG_ID2["PARAM"] = 84] = "PARAM"; + TAG_ID2[TAG_ID2["PLAINTEXT"] = 85] = "PLAINTEXT"; + TAG_ID2[TAG_ID2["PRE"] = 86] = "PRE"; + TAG_ID2[TAG_ID2["RB"] = 87] = "RB"; + TAG_ID2[TAG_ID2["RP"] = 88] = "RP"; + TAG_ID2[TAG_ID2["RT"] = 89] = "RT"; + TAG_ID2[TAG_ID2["RTC"] = 90] = "RTC"; + TAG_ID2[TAG_ID2["RUBY"] = 91] = "RUBY"; + TAG_ID2[TAG_ID2["S"] = 92] = "S"; + TAG_ID2[TAG_ID2["SCRIPT"] = 93] = "SCRIPT"; + TAG_ID2[TAG_ID2["SEARCH"] = 94] = "SEARCH"; + TAG_ID2[TAG_ID2["SECTION"] = 95] = "SECTION"; + TAG_ID2[TAG_ID2["SELECT"] = 96] = "SELECT"; + TAG_ID2[TAG_ID2["SOURCE"] = 97] = "SOURCE"; + TAG_ID2[TAG_ID2["SMALL"] = 98] = "SMALL"; + TAG_ID2[TAG_ID2["SPAN"] = 99] = "SPAN"; + TAG_ID2[TAG_ID2["STRIKE"] = 100] = "STRIKE"; + TAG_ID2[TAG_ID2["STRONG"] = 101] = "STRONG"; + TAG_ID2[TAG_ID2["STYLE"] = 102] = "STYLE"; + TAG_ID2[TAG_ID2["SUB"] = 103] = "SUB"; + TAG_ID2[TAG_ID2["SUMMARY"] = 104] = "SUMMARY"; + TAG_ID2[TAG_ID2["SUP"] = 105] = "SUP"; + TAG_ID2[TAG_ID2["TABLE"] = 106] = "TABLE"; + TAG_ID2[TAG_ID2["TBODY"] = 107] = "TBODY"; + TAG_ID2[TAG_ID2["TEMPLATE"] = 108] = "TEMPLATE"; + TAG_ID2[TAG_ID2["TEXTAREA"] = 109] = "TEXTAREA"; + TAG_ID2[TAG_ID2["TFOOT"] = 110] = "TFOOT"; + TAG_ID2[TAG_ID2["TD"] = 111] = "TD"; + TAG_ID2[TAG_ID2["TH"] = 112] = "TH"; + TAG_ID2[TAG_ID2["THEAD"] = 113] = "THEAD"; + TAG_ID2[TAG_ID2["TITLE"] = 114] = "TITLE"; + TAG_ID2[TAG_ID2["TR"] = 115] = "TR"; + TAG_ID2[TAG_ID2["TRACK"] = 116] = "TRACK"; + TAG_ID2[TAG_ID2["TT"] = 117] = "TT"; + TAG_ID2[TAG_ID2["U"] = 118] = "U"; + TAG_ID2[TAG_ID2["UL"] = 119] = "UL"; + TAG_ID2[TAG_ID2["SVG"] = 120] = "SVG"; + TAG_ID2[TAG_ID2["VAR"] = 121] = "VAR"; + TAG_ID2[TAG_ID2["WBR"] = 122] = "WBR"; + TAG_ID2[TAG_ID2["XMP"] = 123] = "XMP"; + })(TAG_ID || (TAG_ID = {})); + TAG_NAME_TO_ID = /* @__PURE__ */ new Map([ + [TAG_NAMES.A, TAG_ID.A], + [TAG_NAMES.ADDRESS, TAG_ID.ADDRESS], + [TAG_NAMES.ANNOTATION_XML, TAG_ID.ANNOTATION_XML], + [TAG_NAMES.APPLET, TAG_ID.APPLET], + [TAG_NAMES.AREA, TAG_ID.AREA], + [TAG_NAMES.ARTICLE, TAG_ID.ARTICLE], + [TAG_NAMES.ASIDE, TAG_ID.ASIDE], + [TAG_NAMES.B, TAG_ID.B], + [TAG_NAMES.BASE, TAG_ID.BASE], + [TAG_NAMES.BASEFONT, TAG_ID.BASEFONT], + [TAG_NAMES.BGSOUND, TAG_ID.BGSOUND], + [TAG_NAMES.BIG, TAG_ID.BIG], + [TAG_NAMES.BLOCKQUOTE, TAG_ID.BLOCKQUOTE], + [TAG_NAMES.BODY, TAG_ID.BODY], + [TAG_NAMES.BR, TAG_ID.BR], + [TAG_NAMES.BUTTON, TAG_ID.BUTTON], + [TAG_NAMES.CAPTION, TAG_ID.CAPTION], + [TAG_NAMES.CENTER, TAG_ID.CENTER], + [TAG_NAMES.CODE, TAG_ID.CODE], + [TAG_NAMES.COL, TAG_ID.COL], + [TAG_NAMES.COLGROUP, TAG_ID.COLGROUP], + [TAG_NAMES.DD, TAG_ID.DD], + [TAG_NAMES.DESC, TAG_ID.DESC], + [TAG_NAMES.DETAILS, TAG_ID.DETAILS], + [TAG_NAMES.DIALOG, TAG_ID.DIALOG], + [TAG_NAMES.DIR, TAG_ID.DIR], + [TAG_NAMES.DIV, TAG_ID.DIV], + [TAG_NAMES.DL, TAG_ID.DL], + [TAG_NAMES.DT, TAG_ID.DT], + [TAG_NAMES.EM, TAG_ID.EM], + [TAG_NAMES.EMBED, TAG_ID.EMBED], + [TAG_NAMES.FIELDSET, TAG_ID.FIELDSET], + [TAG_NAMES.FIGCAPTION, TAG_ID.FIGCAPTION], + [TAG_NAMES.FIGURE, TAG_ID.FIGURE], + [TAG_NAMES.FONT, TAG_ID.FONT], + [TAG_NAMES.FOOTER, TAG_ID.FOOTER], + [TAG_NAMES.FOREIGN_OBJECT, TAG_ID.FOREIGN_OBJECT], + [TAG_NAMES.FORM, TAG_ID.FORM], + [TAG_NAMES.FRAME, TAG_ID.FRAME], + [TAG_NAMES.FRAMESET, TAG_ID.FRAMESET], + [TAG_NAMES.H1, TAG_ID.H1], + [TAG_NAMES.H2, TAG_ID.H2], + [TAG_NAMES.H3, TAG_ID.H3], + [TAG_NAMES.H4, TAG_ID.H4], + [TAG_NAMES.H5, TAG_ID.H5], + [TAG_NAMES.H6, TAG_ID.H6], + [TAG_NAMES.HEAD, TAG_ID.HEAD], + [TAG_NAMES.HEADER, TAG_ID.HEADER], + [TAG_NAMES.HGROUP, TAG_ID.HGROUP], + [TAG_NAMES.HR, TAG_ID.HR], + [TAG_NAMES.HTML, TAG_ID.HTML], + [TAG_NAMES.I, TAG_ID.I], + [TAG_NAMES.IMG, TAG_ID.IMG], + [TAG_NAMES.IMAGE, TAG_ID.IMAGE], + [TAG_NAMES.INPUT, TAG_ID.INPUT], + [TAG_NAMES.IFRAME, TAG_ID.IFRAME], + [TAG_NAMES.KEYGEN, TAG_ID.KEYGEN], + [TAG_NAMES.LABEL, TAG_ID.LABEL], + [TAG_NAMES.LI, TAG_ID.LI], + [TAG_NAMES.LINK, TAG_ID.LINK], + [TAG_NAMES.LISTING, TAG_ID.LISTING], + [TAG_NAMES.MAIN, TAG_ID.MAIN], + [TAG_NAMES.MALIGNMARK, TAG_ID.MALIGNMARK], + [TAG_NAMES.MARQUEE, TAG_ID.MARQUEE], + [TAG_NAMES.MATH, TAG_ID.MATH], + [TAG_NAMES.MENU, TAG_ID.MENU], + [TAG_NAMES.META, TAG_ID.META], + [TAG_NAMES.MGLYPH, TAG_ID.MGLYPH], + [TAG_NAMES.MI, TAG_ID.MI], + [TAG_NAMES.MO, TAG_ID.MO], + [TAG_NAMES.MN, TAG_ID.MN], + [TAG_NAMES.MS, TAG_ID.MS], + [TAG_NAMES.MTEXT, TAG_ID.MTEXT], + [TAG_NAMES.NAV, TAG_ID.NAV], + [TAG_NAMES.NOBR, TAG_ID.NOBR], + [TAG_NAMES.NOFRAMES, TAG_ID.NOFRAMES], + [TAG_NAMES.NOEMBED, TAG_ID.NOEMBED], + [TAG_NAMES.NOSCRIPT, TAG_ID.NOSCRIPT], + [TAG_NAMES.OBJECT, TAG_ID.OBJECT], + [TAG_NAMES.OL, TAG_ID.OL], + [TAG_NAMES.OPTGROUP, TAG_ID.OPTGROUP], + [TAG_NAMES.OPTION, TAG_ID.OPTION], + [TAG_NAMES.P, TAG_ID.P], + [TAG_NAMES.PARAM, TAG_ID.PARAM], + [TAG_NAMES.PLAINTEXT, TAG_ID.PLAINTEXT], + [TAG_NAMES.PRE, TAG_ID.PRE], + [TAG_NAMES.RB, TAG_ID.RB], + [TAG_NAMES.RP, TAG_ID.RP], + [TAG_NAMES.RT, TAG_ID.RT], + [TAG_NAMES.RTC, TAG_ID.RTC], + [TAG_NAMES.RUBY, TAG_ID.RUBY], + [TAG_NAMES.S, TAG_ID.S], + [TAG_NAMES.SCRIPT, TAG_ID.SCRIPT], + [TAG_NAMES.SEARCH, TAG_ID.SEARCH], + [TAG_NAMES.SECTION, TAG_ID.SECTION], + [TAG_NAMES.SELECT, TAG_ID.SELECT], + [TAG_NAMES.SOURCE, TAG_ID.SOURCE], + [TAG_NAMES.SMALL, TAG_ID.SMALL], + [TAG_NAMES.SPAN, TAG_ID.SPAN], + [TAG_NAMES.STRIKE, TAG_ID.STRIKE], + [TAG_NAMES.STRONG, TAG_ID.STRONG], + [TAG_NAMES.STYLE, TAG_ID.STYLE], + [TAG_NAMES.SUB, TAG_ID.SUB], + [TAG_NAMES.SUMMARY, TAG_ID.SUMMARY], + [TAG_NAMES.SUP, TAG_ID.SUP], + [TAG_NAMES.TABLE, TAG_ID.TABLE], + [TAG_NAMES.TBODY, TAG_ID.TBODY], + [TAG_NAMES.TEMPLATE, TAG_ID.TEMPLATE], + [TAG_NAMES.TEXTAREA, TAG_ID.TEXTAREA], + [TAG_NAMES.TFOOT, TAG_ID.TFOOT], + [TAG_NAMES.TD, TAG_ID.TD], + [TAG_NAMES.TH, TAG_ID.TH], + [TAG_NAMES.THEAD, TAG_ID.THEAD], + [TAG_NAMES.TITLE, TAG_ID.TITLE], + [TAG_NAMES.TR, TAG_ID.TR], + [TAG_NAMES.TRACK, TAG_ID.TRACK], + [TAG_NAMES.TT, TAG_ID.TT], + [TAG_NAMES.U, TAG_ID.U], + [TAG_NAMES.UL, TAG_ID.UL], + [TAG_NAMES.SVG, TAG_ID.SVG], + [TAG_NAMES.VAR, TAG_ID.VAR], + [TAG_NAMES.WBR, TAG_ID.WBR], + [TAG_NAMES.XMP, TAG_ID.XMP] + ]); + $ = TAG_ID; + SPECIAL_ELEMENTS = { + [NS.HTML]: /* @__PURE__ */ new Set([ + $.ADDRESS, + $.APPLET, + $.AREA, + $.ARTICLE, + $.ASIDE, + $.BASE, + $.BASEFONT, + $.BGSOUND, + $.BLOCKQUOTE, + $.BODY, + $.BR, + $.BUTTON, + $.CAPTION, + $.CENTER, + $.COL, + $.COLGROUP, + $.DD, + $.DETAILS, + $.DIR, + $.DIV, + $.DL, + $.DT, + $.EMBED, + $.FIELDSET, + $.FIGCAPTION, + $.FIGURE, + $.FOOTER, + $.FORM, + $.FRAME, + $.FRAMESET, + $.H1, + $.H2, + $.H3, + $.H4, + $.H5, + $.H6, + $.HEAD, + $.HEADER, + $.HGROUP, + $.HR, + $.HTML, + $.IFRAME, + $.IMG, + $.INPUT, + $.LI, + $.LINK, + $.LISTING, + $.MAIN, + $.MARQUEE, + $.MENU, + $.META, + $.NAV, + $.NOEMBED, + $.NOFRAMES, + $.NOSCRIPT, + $.OBJECT, + $.OL, + $.P, + $.PARAM, + $.PLAINTEXT, + $.PRE, + $.SCRIPT, + $.SECTION, + $.SELECT, + $.SOURCE, + $.STYLE, + $.SUMMARY, + $.TABLE, + $.TBODY, + $.TD, + $.TEMPLATE, + $.TEXTAREA, + $.TFOOT, + $.TH, + $.THEAD, + $.TITLE, + $.TR, + $.TRACK, + $.UL, + $.WBR, + $.XMP + ]), + [NS.MATHML]: /* @__PURE__ */ new Set([$.MI, $.MO, $.MN, $.MS, $.MTEXT, $.ANNOTATION_XML]), + [NS.SVG]: /* @__PURE__ */ new Set([$.TITLE, $.FOREIGN_OBJECT, $.DESC]), + [NS.XLINK]: /* @__PURE__ */ new Set(), + [NS.XML]: /* @__PURE__ */ new Set(), + [NS.XMLNS]: /* @__PURE__ */ new Set() + }; + NUMBERED_HEADERS = /* @__PURE__ */ new Set([$.H1, $.H2, $.H3, $.H4, $.H5, $.H6]); + UNESCAPED_TEXT = /* @__PURE__ */ new Set([ + TAG_NAMES.STYLE, + TAG_NAMES.SCRIPT, + TAG_NAMES.XMP, + TAG_NAMES.IFRAME, + TAG_NAMES.NOEMBED, + TAG_NAMES.NOFRAMES, + TAG_NAMES.PLAINTEXT + ]); + } +}); + +// node_modules/parse5/dist/tokenizer/index.js +function isAsciiDigit(cp) { + return cp >= CODE_POINTS.DIGIT_0 && cp <= CODE_POINTS.DIGIT_9; +} +function isAsciiUpper(cp) { + return cp >= CODE_POINTS.LATIN_CAPITAL_A && cp <= CODE_POINTS.LATIN_CAPITAL_Z; +} +function isAsciiLower(cp) { + return cp >= CODE_POINTS.LATIN_SMALL_A && cp <= CODE_POINTS.LATIN_SMALL_Z; +} +function isAsciiLetter(cp) { + return isAsciiLower(cp) || isAsciiUpper(cp); +} +function isAsciiAlphaNumeric2(cp) { + return isAsciiLetter(cp) || isAsciiDigit(cp); +} +function toAsciiLower(cp) { + return cp + 32; +} +function isWhitespace(cp) { + return cp === CODE_POINTS.SPACE || cp === CODE_POINTS.LINE_FEED || cp === CODE_POINTS.TABULATION || cp === CODE_POINTS.FORM_FEED; +} +function isScriptDataDoubleEscapeSequenceEnd(cp) { + return isWhitespace(cp) || cp === CODE_POINTS.SOLIDUS || cp === CODE_POINTS.GREATER_THAN_SIGN; +} +function getErrorForNumericCharacterReference(code) { + if (code === CODE_POINTS.NULL) { + return ERR.nullCharacterReference; + } else if (code > 1114111) { + return ERR.characterReferenceOutsideUnicodeRange; + } else if (isSurrogate(code)) { + return ERR.surrogateCharacterReference; + } else if (isUndefinedCodePoint(code)) { + return ERR.noncharacterCharacterReference; + } else if (isControlCodePoint(code) || code === CODE_POINTS.CARRIAGE_RETURN) { + return ERR.controlCharacterReference; + } + return null; +} +var State, TokenizerMode, Tokenizer; +var init_tokenizer = __esm({ + "node_modules/parse5/dist/tokenizer/index.js"() { + init_preprocessor(); + init_unicode(); + init_token(); + init_decode(); + init_error_codes(); + init_html(); + (function(State2) { + State2[State2["DATA"] = 0] = "DATA"; + State2[State2["RCDATA"] = 1] = "RCDATA"; + State2[State2["RAWTEXT"] = 2] = "RAWTEXT"; + State2[State2["SCRIPT_DATA"] = 3] = "SCRIPT_DATA"; + State2[State2["PLAINTEXT"] = 4] = "PLAINTEXT"; + State2[State2["TAG_OPEN"] = 5] = "TAG_OPEN"; + State2[State2["END_TAG_OPEN"] = 6] = "END_TAG_OPEN"; + State2[State2["TAG_NAME"] = 7] = "TAG_NAME"; + State2[State2["RCDATA_LESS_THAN_SIGN"] = 8] = "RCDATA_LESS_THAN_SIGN"; + State2[State2["RCDATA_END_TAG_OPEN"] = 9] = "RCDATA_END_TAG_OPEN"; + State2[State2["RCDATA_END_TAG_NAME"] = 10] = "RCDATA_END_TAG_NAME"; + State2[State2["RAWTEXT_LESS_THAN_SIGN"] = 11] = "RAWTEXT_LESS_THAN_SIGN"; + State2[State2["RAWTEXT_END_TAG_OPEN"] = 12] = "RAWTEXT_END_TAG_OPEN"; + State2[State2["RAWTEXT_END_TAG_NAME"] = 13] = "RAWTEXT_END_TAG_NAME"; + State2[State2["SCRIPT_DATA_LESS_THAN_SIGN"] = 14] = "SCRIPT_DATA_LESS_THAN_SIGN"; + State2[State2["SCRIPT_DATA_END_TAG_OPEN"] = 15] = "SCRIPT_DATA_END_TAG_OPEN"; + State2[State2["SCRIPT_DATA_END_TAG_NAME"] = 16] = "SCRIPT_DATA_END_TAG_NAME"; + State2[State2["SCRIPT_DATA_ESCAPE_START"] = 17] = "SCRIPT_DATA_ESCAPE_START"; + State2[State2["SCRIPT_DATA_ESCAPE_START_DASH"] = 18] = "SCRIPT_DATA_ESCAPE_START_DASH"; + State2[State2["SCRIPT_DATA_ESCAPED"] = 19] = "SCRIPT_DATA_ESCAPED"; + State2[State2["SCRIPT_DATA_ESCAPED_DASH"] = 20] = "SCRIPT_DATA_ESCAPED_DASH"; + State2[State2["SCRIPT_DATA_ESCAPED_DASH_DASH"] = 21] = "SCRIPT_DATA_ESCAPED_DASH_DASH"; + State2[State2["SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN"] = 22] = "SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN"; + State2[State2["SCRIPT_DATA_ESCAPED_END_TAG_OPEN"] = 23] = "SCRIPT_DATA_ESCAPED_END_TAG_OPEN"; + State2[State2["SCRIPT_DATA_ESCAPED_END_TAG_NAME"] = 24] = "SCRIPT_DATA_ESCAPED_END_TAG_NAME"; + State2[State2["SCRIPT_DATA_DOUBLE_ESCAPE_START"] = 25] = "SCRIPT_DATA_DOUBLE_ESCAPE_START"; + State2[State2["SCRIPT_DATA_DOUBLE_ESCAPED"] = 26] = "SCRIPT_DATA_DOUBLE_ESCAPED"; + State2[State2["SCRIPT_DATA_DOUBLE_ESCAPED_DASH"] = 27] = "SCRIPT_DATA_DOUBLE_ESCAPED_DASH"; + State2[State2["SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH"] = 28] = "SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH"; + State2[State2["SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN"] = 29] = "SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN"; + State2[State2["SCRIPT_DATA_DOUBLE_ESCAPE_END"] = 30] = "SCRIPT_DATA_DOUBLE_ESCAPE_END"; + State2[State2["BEFORE_ATTRIBUTE_NAME"] = 31] = "BEFORE_ATTRIBUTE_NAME"; + State2[State2["ATTRIBUTE_NAME"] = 32] = "ATTRIBUTE_NAME"; + State2[State2["AFTER_ATTRIBUTE_NAME"] = 33] = "AFTER_ATTRIBUTE_NAME"; + State2[State2["BEFORE_ATTRIBUTE_VALUE"] = 34] = "BEFORE_ATTRIBUTE_VALUE"; + State2[State2["ATTRIBUTE_VALUE_DOUBLE_QUOTED"] = 35] = "ATTRIBUTE_VALUE_DOUBLE_QUOTED"; + State2[State2["ATTRIBUTE_VALUE_SINGLE_QUOTED"] = 36] = "ATTRIBUTE_VALUE_SINGLE_QUOTED"; + State2[State2["ATTRIBUTE_VALUE_UNQUOTED"] = 37] = "ATTRIBUTE_VALUE_UNQUOTED"; + State2[State2["AFTER_ATTRIBUTE_VALUE_QUOTED"] = 38] = "AFTER_ATTRIBUTE_VALUE_QUOTED"; + State2[State2["SELF_CLOSING_START_TAG"] = 39] = "SELF_CLOSING_START_TAG"; + State2[State2["BOGUS_COMMENT"] = 40] = "BOGUS_COMMENT"; + State2[State2["MARKUP_DECLARATION_OPEN"] = 41] = "MARKUP_DECLARATION_OPEN"; + State2[State2["COMMENT_START"] = 42] = "COMMENT_START"; + State2[State2["COMMENT_START_DASH"] = 43] = "COMMENT_START_DASH"; + State2[State2["COMMENT"] = 44] = "COMMENT"; + State2[State2["COMMENT_LESS_THAN_SIGN"] = 45] = "COMMENT_LESS_THAN_SIGN"; + State2[State2["COMMENT_LESS_THAN_SIGN_BANG"] = 46] = "COMMENT_LESS_THAN_SIGN_BANG"; + State2[State2["COMMENT_LESS_THAN_SIGN_BANG_DASH"] = 47] = "COMMENT_LESS_THAN_SIGN_BANG_DASH"; + State2[State2["COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH"] = 48] = "COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH"; + State2[State2["COMMENT_END_DASH"] = 49] = "COMMENT_END_DASH"; + State2[State2["COMMENT_END"] = 50] = "COMMENT_END"; + State2[State2["COMMENT_END_BANG"] = 51] = "COMMENT_END_BANG"; + State2[State2["DOCTYPE"] = 52] = "DOCTYPE"; + State2[State2["BEFORE_DOCTYPE_NAME"] = 53] = "BEFORE_DOCTYPE_NAME"; + State2[State2["DOCTYPE_NAME"] = 54] = "DOCTYPE_NAME"; + State2[State2["AFTER_DOCTYPE_NAME"] = 55] = "AFTER_DOCTYPE_NAME"; + State2[State2["AFTER_DOCTYPE_PUBLIC_KEYWORD"] = 56] = "AFTER_DOCTYPE_PUBLIC_KEYWORD"; + State2[State2["BEFORE_DOCTYPE_PUBLIC_IDENTIFIER"] = 57] = "BEFORE_DOCTYPE_PUBLIC_IDENTIFIER"; + State2[State2["DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED"] = 58] = "DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED"; + State2[State2["DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED"] = 59] = "DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED"; + State2[State2["AFTER_DOCTYPE_PUBLIC_IDENTIFIER"] = 60] = "AFTER_DOCTYPE_PUBLIC_IDENTIFIER"; + State2[State2["BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS"] = 61] = "BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS"; + State2[State2["AFTER_DOCTYPE_SYSTEM_KEYWORD"] = 62] = "AFTER_DOCTYPE_SYSTEM_KEYWORD"; + State2[State2["BEFORE_DOCTYPE_SYSTEM_IDENTIFIER"] = 63] = "BEFORE_DOCTYPE_SYSTEM_IDENTIFIER"; + State2[State2["DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED"] = 64] = "DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED"; + State2[State2["DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED"] = 65] = "DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED"; + State2[State2["AFTER_DOCTYPE_SYSTEM_IDENTIFIER"] = 66] = "AFTER_DOCTYPE_SYSTEM_IDENTIFIER"; + State2[State2["BOGUS_DOCTYPE"] = 67] = "BOGUS_DOCTYPE"; + State2[State2["CDATA_SECTION"] = 68] = "CDATA_SECTION"; + State2[State2["CDATA_SECTION_BRACKET"] = 69] = "CDATA_SECTION_BRACKET"; + State2[State2["CDATA_SECTION_END"] = 70] = "CDATA_SECTION_END"; + State2[State2["CHARACTER_REFERENCE"] = 71] = "CHARACTER_REFERENCE"; + State2[State2["AMBIGUOUS_AMPERSAND"] = 72] = "AMBIGUOUS_AMPERSAND"; + })(State || (State = {})); + TokenizerMode = { + DATA: State.DATA, + RCDATA: State.RCDATA, + RAWTEXT: State.RAWTEXT, + SCRIPT_DATA: State.SCRIPT_DATA, + PLAINTEXT: State.PLAINTEXT, + CDATA_SECTION: State.CDATA_SECTION + }; + Tokenizer = class { + constructor(options, handler) { + this.options = options; + this.handler = handler; + this.paused = false; + this.inLoop = false; + this.inForeignNode = false; + this.lastStartTagName = ""; + this.active = false; + this.state = State.DATA; + this.returnState = State.DATA; + this.entityStartPos = 0; + this.consumedAfterSnapshot = -1; + this.currentCharacterToken = null; + this.currentToken = null; + this.currentAttr = { name: "", value: "" }; + this.preprocessor = new Preprocessor(handler); + this.currentLocation = this.getCurrentLocation(-1); + this.entityDecoder = new EntityDecoder(htmlDecodeTree, (cp, consumed) => { + this.preprocessor.pos = this.entityStartPos + consumed - 1; + this._flushCodePointConsumedAsCharacterReference(cp); + }, handler.onParseError ? { + missingSemicolonAfterCharacterReference: () => { + this._err(ERR.missingSemicolonAfterCharacterReference, 1); + }, + absenceOfDigitsInNumericCharacterReference: (consumed) => { + this._err(ERR.absenceOfDigitsInNumericCharacterReference, this.entityStartPos - this.preprocessor.pos + consumed); + }, + validateNumericCharacterReference: (code) => { + const error = getErrorForNumericCharacterReference(code); + if (error) + this._err(error, 1); + } + } : void 0); + } + //Errors + _err(code, cpOffset = 0) { + var _a2, _b; + (_b = (_a2 = this.handler).onParseError) === null || _b === void 0 ? void 0 : _b.call(_a2, this.preprocessor.getError(code, cpOffset)); + } + // NOTE: `offset` may never run across line boundaries. + getCurrentLocation(offset) { + if (!this.options.sourceCodeLocationInfo) { + return null; + } + return { + startLine: this.preprocessor.line, + startCol: this.preprocessor.col - offset, + startOffset: this.preprocessor.offset - offset, + endLine: -1, + endCol: -1, + endOffset: -1 + }; + } + _runParsingLoop() { + if (this.inLoop) + return; + this.inLoop = true; + while (this.active && !this.paused) { + this.consumedAfterSnapshot = 0; + const cp = this._consume(); + if (!this._ensureHibernation()) { + this._callState(cp); + } + } + this.inLoop = false; + } + //API + pause() { + this.paused = true; + } + resume(writeCallback) { + if (!this.paused) { + throw new Error("Parser was already resumed"); + } + this.paused = false; + if (this.inLoop) + return; + this._runParsingLoop(); + if (!this.paused) { + writeCallback === null || writeCallback === void 0 ? void 0 : writeCallback(); + } + } + write(chunk, isLastChunk, writeCallback) { + this.active = true; + this.preprocessor.write(chunk, isLastChunk); + this._runParsingLoop(); + if (!this.paused) { + writeCallback === null || writeCallback === void 0 ? void 0 : writeCallback(); + } + } + insertHtmlAtCurrentPos(chunk) { + this.active = true; + this.preprocessor.insertHtmlAtCurrentPos(chunk); + this._runParsingLoop(); + } + //Hibernation + _ensureHibernation() { + if (this.preprocessor.endOfChunkHit) { + this.preprocessor.retreat(this.consumedAfterSnapshot); + this.consumedAfterSnapshot = 0; + this.active = false; + return true; + } + return false; + } + //Consumption + _consume() { + this.consumedAfterSnapshot++; + return this.preprocessor.advance(); + } + _advanceBy(count) { + this.consumedAfterSnapshot += count; + for (let i = 0; i < count; i++) { + this.preprocessor.advance(); + } + } + _consumeSequenceIfMatch(pattern, caseSensitive) { + if (this.preprocessor.startsWith(pattern, caseSensitive)) { + this._advanceBy(pattern.length - 1); + return true; + } + return false; + } + //Token creation + _createStartTagToken() { + this.currentToken = { + type: TokenType.START_TAG, + tagName: "", + tagID: TAG_ID.UNKNOWN, + selfClosing: false, + ackSelfClosing: false, + attrs: [], + location: this.getCurrentLocation(1) + }; + } + _createEndTagToken() { + this.currentToken = { + type: TokenType.END_TAG, + tagName: "", + tagID: TAG_ID.UNKNOWN, + selfClosing: false, + ackSelfClosing: false, + attrs: [], + location: this.getCurrentLocation(2) + }; + } + _createCommentToken(offset) { + this.currentToken = { + type: TokenType.COMMENT, + data: "", + location: this.getCurrentLocation(offset) + }; + } + _createDoctypeToken(initialName) { + this.currentToken = { + type: TokenType.DOCTYPE, + name: initialName, + forceQuirks: false, + publicId: null, + systemId: null, + location: this.currentLocation + }; + } + _createCharacterToken(type, chars) { + this.currentCharacterToken = { + type, + chars, + location: this.currentLocation + }; + } + //Tag attributes + _createAttr(attrNameFirstCh) { + this.currentAttr = { + name: attrNameFirstCh, + value: "" + }; + this.currentLocation = this.getCurrentLocation(0); + } + _leaveAttrName() { + var _a2; + var _b; + const token = this.currentToken; + if (getTokenAttr(token, this.currentAttr.name) === null) { + token.attrs.push(this.currentAttr); + if (token.location && this.currentLocation) { + const attrLocations = (_a2 = (_b = token.location).attrs) !== null && _a2 !== void 0 ? _a2 : _b.attrs = /* @__PURE__ */ Object.create(null); + attrLocations[this.currentAttr.name] = this.currentLocation; + this._leaveAttrValue(); + } + } else { + this._err(ERR.duplicateAttribute); + } + } + _leaveAttrValue() { + if (this.currentLocation) { + this.currentLocation.endLine = this.preprocessor.line; + this.currentLocation.endCol = this.preprocessor.col; + this.currentLocation.endOffset = this.preprocessor.offset; + } + } + //Token emission + prepareToken(ct) { + this._emitCurrentCharacterToken(ct.location); + this.currentToken = null; + if (ct.location) { + ct.location.endLine = this.preprocessor.line; + ct.location.endCol = this.preprocessor.col + 1; + ct.location.endOffset = this.preprocessor.offset + 1; + } + this.currentLocation = this.getCurrentLocation(-1); + } + emitCurrentTagToken() { + const ct = this.currentToken; + this.prepareToken(ct); + ct.tagID = getTagID(ct.tagName); + if (ct.type === TokenType.START_TAG) { + this.lastStartTagName = ct.tagName; + this.handler.onStartTag(ct); + } else { + if (ct.attrs.length > 0) { + this._err(ERR.endTagWithAttributes); + } + if (ct.selfClosing) { + this._err(ERR.endTagWithTrailingSolidus); + } + this.handler.onEndTag(ct); + } + this.preprocessor.dropParsedChunk(); + } + emitCurrentComment(ct) { + this.prepareToken(ct); + this.handler.onComment(ct); + this.preprocessor.dropParsedChunk(); + } + emitCurrentDoctype(ct) { + this.prepareToken(ct); + this.handler.onDoctype(ct); + this.preprocessor.dropParsedChunk(); + } + _emitCurrentCharacterToken(nextLocation) { + if (this.currentCharacterToken) { + if (nextLocation && this.currentCharacterToken.location) { + this.currentCharacterToken.location.endLine = nextLocation.startLine; + this.currentCharacterToken.location.endCol = nextLocation.startCol; + this.currentCharacterToken.location.endOffset = nextLocation.startOffset; + } + switch (this.currentCharacterToken.type) { + case TokenType.CHARACTER: { + this.handler.onCharacter(this.currentCharacterToken); + break; + } + case TokenType.NULL_CHARACTER: { + this.handler.onNullCharacter(this.currentCharacterToken); + break; + } + case TokenType.WHITESPACE_CHARACTER: { + this.handler.onWhitespaceCharacter(this.currentCharacterToken); + break; + } + } + this.currentCharacterToken = null; + } + } + _emitEOFToken() { + const location = this.getCurrentLocation(0); + if (location) { + location.endLine = location.startLine; + location.endCol = location.startCol; + location.endOffset = location.startOffset; + } + this._emitCurrentCharacterToken(location); + this.handler.onEof({ type: TokenType.EOF, location }); + this.active = false; + } + //Characters emission + //OPTIMIZATION: The specification uses only one type of character token (one token per character). + //This causes a huge memory overhead and a lot of unnecessary parser loops. parse5 uses 3 groups of characters. + //If we have a sequence of characters that belong to the same group, the parser can process it + //as a single solid character token. + //So, there are 3 types of character tokens in parse5: + //1)TokenType.NULL_CHARACTER - \u0000-character sequences (e.g. '\u0000\u0000\u0000') + //2)TokenType.WHITESPACE_CHARACTER - any whitespace/new-line character sequences (e.g. '\n \r\t \f') + //3)TokenType.CHARACTER - any character sequence which don't belong to groups 1 and 2 (e.g. 'abcdef1234@@#$%^') + _appendCharToCurrentCharacterToken(type, ch) { + if (this.currentCharacterToken) { + if (this.currentCharacterToken.type === type) { + this.currentCharacterToken.chars += ch; + return; + } else { + this.currentLocation = this.getCurrentLocation(0); + this._emitCurrentCharacterToken(this.currentLocation); + this.preprocessor.dropParsedChunk(); + } + } + this._createCharacterToken(type, ch); + } + _emitCodePoint(cp) { + const type = isWhitespace(cp) ? TokenType.WHITESPACE_CHARACTER : cp === CODE_POINTS.NULL ? TokenType.NULL_CHARACTER : TokenType.CHARACTER; + this._appendCharToCurrentCharacterToken(type, String.fromCodePoint(cp)); + } + //NOTE: used when we emit characters explicitly. + //This is always for non-whitespace and non-null characters, which allows us to avoid additional checks. + _emitChars(ch) { + this._appendCharToCurrentCharacterToken(TokenType.CHARACTER, ch); + } + // Character reference helpers + _startCharacterReference() { + this.returnState = this.state; + this.state = State.CHARACTER_REFERENCE; + this.entityStartPos = this.preprocessor.pos; + this.entityDecoder.startEntity(this._isCharacterReferenceInAttribute() ? DecodingMode.Attribute : DecodingMode.Legacy); + } + _isCharacterReferenceInAttribute() { + return this.returnState === State.ATTRIBUTE_VALUE_DOUBLE_QUOTED || this.returnState === State.ATTRIBUTE_VALUE_SINGLE_QUOTED || this.returnState === State.ATTRIBUTE_VALUE_UNQUOTED; + } + _flushCodePointConsumedAsCharacterReference(cp) { + if (this._isCharacterReferenceInAttribute()) { + this.currentAttr.value += String.fromCodePoint(cp); + } else { + this._emitCodePoint(cp); + } + } + // Calling states this way turns out to be much faster than any other approach. + _callState(cp) { + switch (this.state) { + case State.DATA: { + this._stateData(cp); + break; + } + case State.RCDATA: { + this._stateRcdata(cp); + break; + } + case State.RAWTEXT: { + this._stateRawtext(cp); + break; + } + case State.SCRIPT_DATA: { + this._stateScriptData(cp); + break; + } + case State.PLAINTEXT: { + this._statePlaintext(cp); + break; + } + case State.TAG_OPEN: { + this._stateTagOpen(cp); + break; + } + case State.END_TAG_OPEN: { + this._stateEndTagOpen(cp); + break; + } + case State.TAG_NAME: { + this._stateTagName(cp); + break; + } + case State.RCDATA_LESS_THAN_SIGN: { + this._stateRcdataLessThanSign(cp); + break; + } + case State.RCDATA_END_TAG_OPEN: { + this._stateRcdataEndTagOpen(cp); + break; + } + case State.RCDATA_END_TAG_NAME: { + this._stateRcdataEndTagName(cp); + break; + } + case State.RAWTEXT_LESS_THAN_SIGN: { + this._stateRawtextLessThanSign(cp); + break; + } + case State.RAWTEXT_END_TAG_OPEN: { + this._stateRawtextEndTagOpen(cp); + break; + } + case State.RAWTEXT_END_TAG_NAME: { + this._stateRawtextEndTagName(cp); + break; + } + case State.SCRIPT_DATA_LESS_THAN_SIGN: { + this._stateScriptDataLessThanSign(cp); + break; + } + case State.SCRIPT_DATA_END_TAG_OPEN: { + this._stateScriptDataEndTagOpen(cp); + break; + } + case State.SCRIPT_DATA_END_TAG_NAME: { + this._stateScriptDataEndTagName(cp); + break; + } + case State.SCRIPT_DATA_ESCAPE_START: { + this._stateScriptDataEscapeStart(cp); + break; + } + case State.SCRIPT_DATA_ESCAPE_START_DASH: { + this._stateScriptDataEscapeStartDash(cp); + break; + } + case State.SCRIPT_DATA_ESCAPED: { + this._stateScriptDataEscaped(cp); + break; + } + case State.SCRIPT_DATA_ESCAPED_DASH: { + this._stateScriptDataEscapedDash(cp); + break; + } + case State.SCRIPT_DATA_ESCAPED_DASH_DASH: { + this._stateScriptDataEscapedDashDash(cp); + break; + } + case State.SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN: { + this._stateScriptDataEscapedLessThanSign(cp); + break; + } + case State.SCRIPT_DATA_ESCAPED_END_TAG_OPEN: { + this._stateScriptDataEscapedEndTagOpen(cp); + break; + } + case State.SCRIPT_DATA_ESCAPED_END_TAG_NAME: { + this._stateScriptDataEscapedEndTagName(cp); + break; + } + case State.SCRIPT_DATA_DOUBLE_ESCAPE_START: { + this._stateScriptDataDoubleEscapeStart(cp); + break; + } + case State.SCRIPT_DATA_DOUBLE_ESCAPED: { + this._stateScriptDataDoubleEscaped(cp); + break; + } + case State.SCRIPT_DATA_DOUBLE_ESCAPED_DASH: { + this._stateScriptDataDoubleEscapedDash(cp); + break; + } + case State.SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH: { + this._stateScriptDataDoubleEscapedDashDash(cp); + break; + } + case State.SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN: { + this._stateScriptDataDoubleEscapedLessThanSign(cp); + break; + } + case State.SCRIPT_DATA_DOUBLE_ESCAPE_END: { + this._stateScriptDataDoubleEscapeEnd(cp); + break; + } + case State.BEFORE_ATTRIBUTE_NAME: { + this._stateBeforeAttributeName(cp); + break; + } + case State.ATTRIBUTE_NAME: { + this._stateAttributeName(cp); + break; + } + case State.AFTER_ATTRIBUTE_NAME: { + this._stateAfterAttributeName(cp); + break; + } + case State.BEFORE_ATTRIBUTE_VALUE: { + this._stateBeforeAttributeValue(cp); + break; + } + case State.ATTRIBUTE_VALUE_DOUBLE_QUOTED: { + this._stateAttributeValueDoubleQuoted(cp); + break; + } + case State.ATTRIBUTE_VALUE_SINGLE_QUOTED: { + this._stateAttributeValueSingleQuoted(cp); + break; + } + case State.ATTRIBUTE_VALUE_UNQUOTED: { + this._stateAttributeValueUnquoted(cp); + break; + } + case State.AFTER_ATTRIBUTE_VALUE_QUOTED: { + this._stateAfterAttributeValueQuoted(cp); + break; + } + case State.SELF_CLOSING_START_TAG: { + this._stateSelfClosingStartTag(cp); + break; + } + case State.BOGUS_COMMENT: { + this._stateBogusComment(cp); + break; + } + case State.MARKUP_DECLARATION_OPEN: { + this._stateMarkupDeclarationOpen(cp); + break; + } + case State.COMMENT_START: { + this._stateCommentStart(cp); + break; + } + case State.COMMENT_START_DASH: { + this._stateCommentStartDash(cp); + break; + } + case State.COMMENT: { + this._stateComment(cp); + break; + } + case State.COMMENT_LESS_THAN_SIGN: { + this._stateCommentLessThanSign(cp); + break; + } + case State.COMMENT_LESS_THAN_SIGN_BANG: { + this._stateCommentLessThanSignBang(cp); + break; + } + case State.COMMENT_LESS_THAN_SIGN_BANG_DASH: { + this._stateCommentLessThanSignBangDash(cp); + break; + } + case State.COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH: { + this._stateCommentLessThanSignBangDashDash(cp); + break; + } + case State.COMMENT_END_DASH: { + this._stateCommentEndDash(cp); + break; + } + case State.COMMENT_END: { + this._stateCommentEnd(cp); + break; + } + case State.COMMENT_END_BANG: { + this._stateCommentEndBang(cp); + break; + } + case State.DOCTYPE: { + this._stateDoctype(cp); + break; + } + case State.BEFORE_DOCTYPE_NAME: { + this._stateBeforeDoctypeName(cp); + break; + } + case State.DOCTYPE_NAME: { + this._stateDoctypeName(cp); + break; + } + case State.AFTER_DOCTYPE_NAME: { + this._stateAfterDoctypeName(cp); + break; + } + case State.AFTER_DOCTYPE_PUBLIC_KEYWORD: { + this._stateAfterDoctypePublicKeyword(cp); + break; + } + case State.BEFORE_DOCTYPE_PUBLIC_IDENTIFIER: { + this._stateBeforeDoctypePublicIdentifier(cp); + break; + } + case State.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED: { + this._stateDoctypePublicIdentifierDoubleQuoted(cp); + break; + } + case State.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED: { + this._stateDoctypePublicIdentifierSingleQuoted(cp); + break; + } + case State.AFTER_DOCTYPE_PUBLIC_IDENTIFIER: { + this._stateAfterDoctypePublicIdentifier(cp); + break; + } + case State.BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS: { + this._stateBetweenDoctypePublicAndSystemIdentifiers(cp); + break; + } + case State.AFTER_DOCTYPE_SYSTEM_KEYWORD: { + this._stateAfterDoctypeSystemKeyword(cp); + break; + } + case State.BEFORE_DOCTYPE_SYSTEM_IDENTIFIER: { + this._stateBeforeDoctypeSystemIdentifier(cp); + break; + } + case State.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED: { + this._stateDoctypeSystemIdentifierDoubleQuoted(cp); + break; + } + case State.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED: { + this._stateDoctypeSystemIdentifierSingleQuoted(cp); + break; + } + case State.AFTER_DOCTYPE_SYSTEM_IDENTIFIER: { + this._stateAfterDoctypeSystemIdentifier(cp); + break; + } + case State.BOGUS_DOCTYPE: { + this._stateBogusDoctype(cp); + break; + } + case State.CDATA_SECTION: { + this._stateCdataSection(cp); + break; + } + case State.CDATA_SECTION_BRACKET: { + this._stateCdataSectionBracket(cp); + break; + } + case State.CDATA_SECTION_END: { + this._stateCdataSectionEnd(cp); + break; + } + case State.CHARACTER_REFERENCE: { + this._stateCharacterReference(); + break; + } + case State.AMBIGUOUS_AMPERSAND: { + this._stateAmbiguousAmpersand(cp); + break; + } + default: { + throw new Error("Unknown state"); + } + } + } + // State machine + // Data state + //------------------------------------------------------------------ + _stateData(cp) { + switch (cp) { + case CODE_POINTS.LESS_THAN_SIGN: { + this.state = State.TAG_OPEN; + break; + } + case CODE_POINTS.AMPERSAND: { + this._startCharacterReference(); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this._emitCodePoint(cp); + break; + } + case CODE_POINTS.EOF: { + this._emitEOFToken(); + break; + } + default: { + this._emitCodePoint(cp); + } + } + } + // RCDATA state + //------------------------------------------------------------------ + _stateRcdata(cp) { + switch (cp) { + case CODE_POINTS.AMPERSAND: { + this._startCharacterReference(); + break; + } + case CODE_POINTS.LESS_THAN_SIGN: { + this.state = State.RCDATA_LESS_THAN_SIGN; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this._emitChars(REPLACEMENT_CHARACTER); + break; + } + case CODE_POINTS.EOF: { + this._emitEOFToken(); + break; + } + default: { + this._emitCodePoint(cp); + } + } + } + // RAWTEXT state + //------------------------------------------------------------------ + _stateRawtext(cp) { + switch (cp) { + case CODE_POINTS.LESS_THAN_SIGN: { + this.state = State.RAWTEXT_LESS_THAN_SIGN; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this._emitChars(REPLACEMENT_CHARACTER); + break; + } + case CODE_POINTS.EOF: { + this._emitEOFToken(); + break; + } + default: { + this._emitCodePoint(cp); + } + } + } + // Script data state + //------------------------------------------------------------------ + _stateScriptData(cp) { + switch (cp) { + case CODE_POINTS.LESS_THAN_SIGN: { + this.state = State.SCRIPT_DATA_LESS_THAN_SIGN; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this._emitChars(REPLACEMENT_CHARACTER); + break; + } + case CODE_POINTS.EOF: { + this._emitEOFToken(); + break; + } + default: { + this._emitCodePoint(cp); + } + } + } + // PLAINTEXT state + //------------------------------------------------------------------ + _statePlaintext(cp) { + switch (cp) { + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this._emitChars(REPLACEMENT_CHARACTER); + break; + } + case CODE_POINTS.EOF: { + this._emitEOFToken(); + break; + } + default: { + this._emitCodePoint(cp); + } + } + } + // Tag open state + //------------------------------------------------------------------ + _stateTagOpen(cp) { + if (isAsciiLetter(cp)) { + this._createStartTagToken(); + this.state = State.TAG_NAME; + this._stateTagName(cp); + } else + switch (cp) { + case CODE_POINTS.EXCLAMATION_MARK: { + this.state = State.MARKUP_DECLARATION_OPEN; + break; + } + case CODE_POINTS.SOLIDUS: { + this.state = State.END_TAG_OPEN; + break; + } + case CODE_POINTS.QUESTION_MARK: { + this._err(ERR.unexpectedQuestionMarkInsteadOfTagName); + this._createCommentToken(1); + this.state = State.BOGUS_COMMENT; + this._stateBogusComment(cp); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofBeforeTagName); + this._emitChars("<"); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.invalidFirstCharacterOfTagName); + this._emitChars("<"); + this.state = State.DATA; + this._stateData(cp); + } + } + } + // End tag open state + //------------------------------------------------------------------ + _stateEndTagOpen(cp) { + if (isAsciiLetter(cp)) { + this._createEndTagToken(); + this.state = State.TAG_NAME; + this._stateTagName(cp); + } else + switch (cp) { + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.missingEndTagName); + this.state = State.DATA; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofBeforeTagName); + this._emitChars(""); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this.state = State.SCRIPT_DATA_ESCAPED; + this._emitChars(REPLACEMENT_CHARACTER); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInScriptHtmlCommentLikeText); + this._emitEOFToken(); + break; + } + default: { + this.state = State.SCRIPT_DATA_ESCAPED; + this._emitCodePoint(cp); + } + } + } + // Script data escaped less-than sign state + //------------------------------------------------------------------ + _stateScriptDataEscapedLessThanSign(cp) { + if (cp === CODE_POINTS.SOLIDUS) { + this.state = State.SCRIPT_DATA_ESCAPED_END_TAG_OPEN; + } else if (isAsciiLetter(cp)) { + this._emitChars("<"); + this.state = State.SCRIPT_DATA_DOUBLE_ESCAPE_START; + this._stateScriptDataDoubleEscapeStart(cp); + } else { + this._emitChars("<"); + this.state = State.SCRIPT_DATA_ESCAPED; + this._stateScriptDataEscaped(cp); + } + } + // Script data escaped end tag open state + //------------------------------------------------------------------ + _stateScriptDataEscapedEndTagOpen(cp) { + if (isAsciiLetter(cp)) { + this.state = State.SCRIPT_DATA_ESCAPED_END_TAG_NAME; + this._stateScriptDataEscapedEndTagName(cp); + } else { + this._emitChars(""); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this.state = State.SCRIPT_DATA_DOUBLE_ESCAPED; + this._emitChars(REPLACEMENT_CHARACTER); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInScriptHtmlCommentLikeText); + this._emitEOFToken(); + break; + } + default: { + this.state = State.SCRIPT_DATA_DOUBLE_ESCAPED; + this._emitCodePoint(cp); + } + } + } + // Script data double escaped less-than sign state + //------------------------------------------------------------------ + _stateScriptDataDoubleEscapedLessThanSign(cp) { + if (cp === CODE_POINTS.SOLIDUS) { + this.state = State.SCRIPT_DATA_DOUBLE_ESCAPE_END; + this._emitChars("/"); + } else { + this.state = State.SCRIPT_DATA_DOUBLE_ESCAPED; + this._stateScriptDataDoubleEscaped(cp); + } + } + // Script data double escape end state + //------------------------------------------------------------------ + _stateScriptDataDoubleEscapeEnd(cp) { + if (this.preprocessor.startsWith(SEQUENCES.SCRIPT, false) && isScriptDataDoubleEscapeSequenceEnd(this.preprocessor.peek(SEQUENCES.SCRIPT.length))) { + this._emitCodePoint(cp); + for (let i = 0; i < SEQUENCES.SCRIPT.length; i++) { + this._emitCodePoint(this._consume()); + } + this.state = State.SCRIPT_DATA_ESCAPED; + } else if (!this._ensureHibernation()) { + this.state = State.SCRIPT_DATA_DOUBLE_ESCAPED; + this._stateScriptDataDoubleEscaped(cp); + } + } + // Before attribute name state + //------------------------------------------------------------------ + _stateBeforeAttributeName(cp) { + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.SOLIDUS: + case CODE_POINTS.GREATER_THAN_SIGN: + case CODE_POINTS.EOF: { + this.state = State.AFTER_ATTRIBUTE_NAME; + this._stateAfterAttributeName(cp); + break; + } + case CODE_POINTS.EQUALS_SIGN: { + this._err(ERR.unexpectedEqualsSignBeforeAttributeName); + this._createAttr("="); + this.state = State.ATTRIBUTE_NAME; + break; + } + default: { + this._createAttr(""); + this.state = State.ATTRIBUTE_NAME; + this._stateAttributeName(cp); + } + } + } + // Attribute name state + //------------------------------------------------------------------ + _stateAttributeName(cp) { + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: + case CODE_POINTS.SOLIDUS: + case CODE_POINTS.GREATER_THAN_SIGN: + case CODE_POINTS.EOF: { + this._leaveAttrName(); + this.state = State.AFTER_ATTRIBUTE_NAME; + this._stateAfterAttributeName(cp); + break; + } + case CODE_POINTS.EQUALS_SIGN: { + this._leaveAttrName(); + this.state = State.BEFORE_ATTRIBUTE_VALUE; + break; + } + case CODE_POINTS.QUOTATION_MARK: + case CODE_POINTS.APOSTROPHE: + case CODE_POINTS.LESS_THAN_SIGN: { + this._err(ERR.unexpectedCharacterInAttributeName); + this.currentAttr.name += String.fromCodePoint(cp); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this.currentAttr.name += REPLACEMENT_CHARACTER; + break; + } + default: { + this.currentAttr.name += String.fromCodePoint(isAsciiUpper(cp) ? toAsciiLower(cp) : cp); + } + } + } + // After attribute name state + //------------------------------------------------------------------ + _stateAfterAttributeName(cp) { + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.SOLIDUS: { + this.state = State.SELF_CLOSING_START_TAG; + break; + } + case CODE_POINTS.EQUALS_SIGN: { + this.state = State.BEFORE_ATTRIBUTE_VALUE; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this.state = State.DATA; + this.emitCurrentTagToken(); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInTag); + this._emitEOFToken(); + break; + } + default: { + this._createAttr(""); + this.state = State.ATTRIBUTE_NAME; + this._stateAttributeName(cp); + } + } + } + // Before attribute value state + //------------------------------------------------------------------ + _stateBeforeAttributeValue(cp) { + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.QUOTATION_MARK: { + this.state = State.ATTRIBUTE_VALUE_DOUBLE_QUOTED; + break; + } + case CODE_POINTS.APOSTROPHE: { + this.state = State.ATTRIBUTE_VALUE_SINGLE_QUOTED; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.missingAttributeValue); + this.state = State.DATA; + this.emitCurrentTagToken(); + break; + } + default: { + this.state = State.ATTRIBUTE_VALUE_UNQUOTED; + this._stateAttributeValueUnquoted(cp); + } + } + } + // Attribute value (double-quoted) state + //------------------------------------------------------------------ + _stateAttributeValueDoubleQuoted(cp) { + switch (cp) { + case CODE_POINTS.QUOTATION_MARK: { + this.state = State.AFTER_ATTRIBUTE_VALUE_QUOTED; + break; + } + case CODE_POINTS.AMPERSAND: { + this._startCharacterReference(); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this.currentAttr.value += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInTag); + this._emitEOFToken(); + break; + } + default: { + this.currentAttr.value += String.fromCodePoint(cp); + } + } + } + // Attribute value (single-quoted) state + //------------------------------------------------------------------ + _stateAttributeValueSingleQuoted(cp) { + switch (cp) { + case CODE_POINTS.APOSTROPHE: { + this.state = State.AFTER_ATTRIBUTE_VALUE_QUOTED; + break; + } + case CODE_POINTS.AMPERSAND: { + this._startCharacterReference(); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this.currentAttr.value += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInTag); + this._emitEOFToken(); + break; + } + default: { + this.currentAttr.value += String.fromCodePoint(cp); + } + } + } + // Attribute value (unquoted) state + //------------------------------------------------------------------ + _stateAttributeValueUnquoted(cp) { + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + this._leaveAttrValue(); + this.state = State.BEFORE_ATTRIBUTE_NAME; + break; + } + case CODE_POINTS.AMPERSAND: { + this._startCharacterReference(); + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._leaveAttrValue(); + this.state = State.DATA; + this.emitCurrentTagToken(); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this.currentAttr.value += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.QUOTATION_MARK: + case CODE_POINTS.APOSTROPHE: + case CODE_POINTS.LESS_THAN_SIGN: + case CODE_POINTS.EQUALS_SIGN: + case CODE_POINTS.GRAVE_ACCENT: { + this._err(ERR.unexpectedCharacterInUnquotedAttributeValue); + this.currentAttr.value += String.fromCodePoint(cp); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInTag); + this._emitEOFToken(); + break; + } + default: { + this.currentAttr.value += String.fromCodePoint(cp); + } + } + } + // After attribute value (quoted) state + //------------------------------------------------------------------ + _stateAfterAttributeValueQuoted(cp) { + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + this._leaveAttrValue(); + this.state = State.BEFORE_ATTRIBUTE_NAME; + break; + } + case CODE_POINTS.SOLIDUS: { + this._leaveAttrValue(); + this.state = State.SELF_CLOSING_START_TAG; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._leaveAttrValue(); + this.state = State.DATA; + this.emitCurrentTagToken(); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInTag); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.missingWhitespaceBetweenAttributes); + this.state = State.BEFORE_ATTRIBUTE_NAME; + this._stateBeforeAttributeName(cp); + } + } + } + // Self-closing start tag state + //------------------------------------------------------------------ + _stateSelfClosingStartTag(cp) { + switch (cp) { + case CODE_POINTS.GREATER_THAN_SIGN: { + const token = this.currentToken; + token.selfClosing = true; + this.state = State.DATA; + this.emitCurrentTagToken(); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInTag); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.unexpectedSolidusInTag); + this.state = State.BEFORE_ATTRIBUTE_NAME; + this._stateBeforeAttributeName(cp); + } + } + } + // Bogus comment state + //------------------------------------------------------------------ + _stateBogusComment(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.GREATER_THAN_SIGN: { + this.state = State.DATA; + this.emitCurrentComment(token); + break; + } + case CODE_POINTS.EOF: { + this.emitCurrentComment(token); + this._emitEOFToken(); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + token.data += REPLACEMENT_CHARACTER; + break; + } + default: { + token.data += String.fromCodePoint(cp); + } + } + } + // Markup declaration open state + //------------------------------------------------------------------ + _stateMarkupDeclarationOpen(cp) { + if (this._consumeSequenceIfMatch(SEQUENCES.DASH_DASH, true)) { + this._createCommentToken(SEQUENCES.DASH_DASH.length + 1); + this.state = State.COMMENT_START; + } else if (this._consumeSequenceIfMatch(SEQUENCES.DOCTYPE, false)) { + this.currentLocation = this.getCurrentLocation(SEQUENCES.DOCTYPE.length + 1); + this.state = State.DOCTYPE; + } else if (this._consumeSequenceIfMatch(SEQUENCES.CDATA_START, true)) { + if (this.inForeignNode) { + this.state = State.CDATA_SECTION; + } else { + this._err(ERR.cdataInHtmlContent); + this._createCommentToken(SEQUENCES.CDATA_START.length + 1); + this.currentToken.data = "[CDATA["; + this.state = State.BOGUS_COMMENT; + } + } else if (!this._ensureHibernation()) { + this._err(ERR.incorrectlyOpenedComment); + this._createCommentToken(2); + this.state = State.BOGUS_COMMENT; + this._stateBogusComment(cp); + } + } + // Comment start state + //------------------------------------------------------------------ + _stateCommentStart(cp) { + switch (cp) { + case CODE_POINTS.HYPHEN_MINUS: { + this.state = State.COMMENT_START_DASH; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.abruptClosingOfEmptyComment); + this.state = State.DATA; + const token = this.currentToken; + this.emitCurrentComment(token); + break; + } + default: { + this.state = State.COMMENT; + this._stateComment(cp); + } + } + } + // Comment start dash state + //------------------------------------------------------------------ + _stateCommentStartDash(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.HYPHEN_MINUS: { + this.state = State.COMMENT_END; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.abruptClosingOfEmptyComment); + this.state = State.DATA; + this.emitCurrentComment(token); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInComment); + this.emitCurrentComment(token); + this._emitEOFToken(); + break; + } + default: { + token.data += "-"; + this.state = State.COMMENT; + this._stateComment(cp); + } + } + } + // Comment state + //------------------------------------------------------------------ + _stateComment(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.HYPHEN_MINUS: { + this.state = State.COMMENT_END_DASH; + break; + } + case CODE_POINTS.LESS_THAN_SIGN: { + token.data += "<"; + this.state = State.COMMENT_LESS_THAN_SIGN; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + token.data += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInComment); + this.emitCurrentComment(token); + this._emitEOFToken(); + break; + } + default: { + token.data += String.fromCodePoint(cp); + } + } + } + // Comment less-than sign state + //------------------------------------------------------------------ + _stateCommentLessThanSign(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.EXCLAMATION_MARK: { + token.data += "!"; + this.state = State.COMMENT_LESS_THAN_SIGN_BANG; + break; + } + case CODE_POINTS.LESS_THAN_SIGN: { + token.data += "<"; + break; + } + default: { + this.state = State.COMMENT; + this._stateComment(cp); + } + } + } + // Comment less-than sign bang state + //------------------------------------------------------------------ + _stateCommentLessThanSignBang(cp) { + if (cp === CODE_POINTS.HYPHEN_MINUS) { + this.state = State.COMMENT_LESS_THAN_SIGN_BANG_DASH; + } else { + this.state = State.COMMENT; + this._stateComment(cp); + } + } + // Comment less-than sign bang dash state + //------------------------------------------------------------------ + _stateCommentLessThanSignBangDash(cp) { + if (cp === CODE_POINTS.HYPHEN_MINUS) { + this.state = State.COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH; + } else { + this.state = State.COMMENT_END_DASH; + this._stateCommentEndDash(cp); + } + } + // Comment less-than sign bang dash dash state + //------------------------------------------------------------------ + _stateCommentLessThanSignBangDashDash(cp) { + if (cp !== CODE_POINTS.GREATER_THAN_SIGN && cp !== CODE_POINTS.EOF) { + this._err(ERR.nestedComment); + } + this.state = State.COMMENT_END; + this._stateCommentEnd(cp); + } + // Comment end dash state + //------------------------------------------------------------------ + _stateCommentEndDash(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.HYPHEN_MINUS: { + this.state = State.COMMENT_END; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInComment); + this.emitCurrentComment(token); + this._emitEOFToken(); + break; + } + default: { + token.data += "-"; + this.state = State.COMMENT; + this._stateComment(cp); + } + } + } + // Comment end state + //------------------------------------------------------------------ + _stateCommentEnd(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.GREATER_THAN_SIGN: { + this.state = State.DATA; + this.emitCurrentComment(token); + break; + } + case CODE_POINTS.EXCLAMATION_MARK: { + this.state = State.COMMENT_END_BANG; + break; + } + case CODE_POINTS.HYPHEN_MINUS: { + token.data += "-"; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInComment); + this.emitCurrentComment(token); + this._emitEOFToken(); + break; + } + default: { + token.data += "--"; + this.state = State.COMMENT; + this._stateComment(cp); + } + } + } + // Comment end bang state + //------------------------------------------------------------------ + _stateCommentEndBang(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.HYPHEN_MINUS: { + token.data += "--!"; + this.state = State.COMMENT_END_DASH; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.incorrectlyClosedComment); + this.state = State.DATA; + this.emitCurrentComment(token); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInComment); + this.emitCurrentComment(token); + this._emitEOFToken(); + break; + } + default: { + token.data += "--!"; + this.state = State.COMMENT; + this._stateComment(cp); + } + } + } + // DOCTYPE state + //------------------------------------------------------------------ + _stateDoctype(cp) { + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + this.state = State.BEFORE_DOCTYPE_NAME; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this.state = State.BEFORE_DOCTYPE_NAME; + this._stateBeforeDoctypeName(cp); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + this._createDoctypeToken(null); + const token = this.currentToken; + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.missingWhitespaceBeforeDoctypeName); + this.state = State.BEFORE_DOCTYPE_NAME; + this._stateBeforeDoctypeName(cp); + } + } + } + // Before DOCTYPE name state + //------------------------------------------------------------------ + _stateBeforeDoctypeName(cp) { + if (isAsciiUpper(cp)) { + this._createDoctypeToken(String.fromCharCode(toAsciiLower(cp))); + this.state = State.DOCTYPE_NAME; + } else + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + this._createDoctypeToken(REPLACEMENT_CHARACTER); + this.state = State.DOCTYPE_NAME; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.missingDoctypeName); + this._createDoctypeToken(null); + const token = this.currentToken; + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this.state = State.DATA; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + this._createDoctypeToken(null); + const token = this.currentToken; + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._createDoctypeToken(String.fromCodePoint(cp)); + this.state = State.DOCTYPE_NAME; + } + } + } + // DOCTYPE name state + //------------------------------------------------------------------ + _stateDoctypeName(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + this.state = State.AFTER_DOCTYPE_NAME; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this.state = State.DATA; + this.emitCurrentDoctype(token); + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + token.name += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + token.name += String.fromCodePoint(isAsciiUpper(cp) ? toAsciiLower(cp) : cp); + } + } + } + // After DOCTYPE name state + //------------------------------------------------------------------ + _stateAfterDoctypeName(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this.state = State.DATA; + this.emitCurrentDoctype(token); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + if (this._consumeSequenceIfMatch(SEQUENCES.PUBLIC, false)) { + this.state = State.AFTER_DOCTYPE_PUBLIC_KEYWORD; + } else if (this._consumeSequenceIfMatch(SEQUENCES.SYSTEM, false)) { + this.state = State.AFTER_DOCTYPE_SYSTEM_KEYWORD; + } else if (!this._ensureHibernation()) { + this._err(ERR.invalidCharacterSequenceAfterDoctypeName); + token.forceQuirks = true; + this.state = State.BOGUS_DOCTYPE; + this._stateBogusDoctype(cp); + } + } + } + } + // After DOCTYPE public keyword state + //------------------------------------------------------------------ + _stateAfterDoctypePublicKeyword(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + this.state = State.BEFORE_DOCTYPE_PUBLIC_IDENTIFIER; + break; + } + case CODE_POINTS.QUOTATION_MARK: { + this._err(ERR.missingWhitespaceAfterDoctypePublicKeyword); + token.publicId = ""; + this.state = State.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED; + break; + } + case CODE_POINTS.APOSTROPHE: { + this._err(ERR.missingWhitespaceAfterDoctypePublicKeyword); + token.publicId = ""; + this.state = State.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.missingDoctypePublicIdentifier); + token.forceQuirks = true; + this.state = State.DATA; + this.emitCurrentDoctype(token); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.missingQuoteBeforeDoctypePublicIdentifier); + token.forceQuirks = true; + this.state = State.BOGUS_DOCTYPE; + this._stateBogusDoctype(cp); + } + } + } + // Before DOCTYPE public identifier state + //------------------------------------------------------------------ + _stateBeforeDoctypePublicIdentifier(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.QUOTATION_MARK: { + token.publicId = ""; + this.state = State.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED; + break; + } + case CODE_POINTS.APOSTROPHE: { + token.publicId = ""; + this.state = State.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.missingDoctypePublicIdentifier); + token.forceQuirks = true; + this.state = State.DATA; + this.emitCurrentDoctype(token); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.missingQuoteBeforeDoctypePublicIdentifier); + token.forceQuirks = true; + this.state = State.BOGUS_DOCTYPE; + this._stateBogusDoctype(cp); + } + } + } + // DOCTYPE public identifier (double-quoted) state + //------------------------------------------------------------------ + _stateDoctypePublicIdentifierDoubleQuoted(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.QUOTATION_MARK: { + this.state = State.AFTER_DOCTYPE_PUBLIC_IDENTIFIER; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + token.publicId += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.abruptDoctypePublicIdentifier); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this.state = State.DATA; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + token.publicId += String.fromCodePoint(cp); + } + } + } + // DOCTYPE public identifier (single-quoted) state + //------------------------------------------------------------------ + _stateDoctypePublicIdentifierSingleQuoted(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.APOSTROPHE: { + this.state = State.AFTER_DOCTYPE_PUBLIC_IDENTIFIER; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + token.publicId += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.abruptDoctypePublicIdentifier); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this.state = State.DATA; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + token.publicId += String.fromCodePoint(cp); + } + } + } + // After DOCTYPE public identifier state + //------------------------------------------------------------------ + _stateAfterDoctypePublicIdentifier(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + this.state = State.BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this.state = State.DATA; + this.emitCurrentDoctype(token); + break; + } + case CODE_POINTS.QUOTATION_MARK: { + this._err(ERR.missingWhitespaceBetweenDoctypePublicAndSystemIdentifiers); + token.systemId = ""; + this.state = State.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED; + break; + } + case CODE_POINTS.APOSTROPHE: { + this._err(ERR.missingWhitespaceBetweenDoctypePublicAndSystemIdentifiers); + token.systemId = ""; + this.state = State.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.missingQuoteBeforeDoctypeSystemIdentifier); + token.forceQuirks = true; + this.state = State.BOGUS_DOCTYPE; + this._stateBogusDoctype(cp); + } + } + } + // Between DOCTYPE public and system identifiers state + //------------------------------------------------------------------ + _stateBetweenDoctypePublicAndSystemIdentifiers(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this.emitCurrentDoctype(token); + this.state = State.DATA; + break; + } + case CODE_POINTS.QUOTATION_MARK: { + token.systemId = ""; + this.state = State.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED; + break; + } + case CODE_POINTS.APOSTROPHE: { + token.systemId = ""; + this.state = State.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.missingQuoteBeforeDoctypeSystemIdentifier); + token.forceQuirks = true; + this.state = State.BOGUS_DOCTYPE; + this._stateBogusDoctype(cp); + } + } + } + // After DOCTYPE system keyword state + //------------------------------------------------------------------ + _stateAfterDoctypeSystemKeyword(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + this.state = State.BEFORE_DOCTYPE_SYSTEM_IDENTIFIER; + break; + } + case CODE_POINTS.QUOTATION_MARK: { + this._err(ERR.missingWhitespaceAfterDoctypeSystemKeyword); + token.systemId = ""; + this.state = State.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED; + break; + } + case CODE_POINTS.APOSTROPHE: { + this._err(ERR.missingWhitespaceAfterDoctypeSystemKeyword); + token.systemId = ""; + this.state = State.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.missingDoctypeSystemIdentifier); + token.forceQuirks = true; + this.state = State.DATA; + this.emitCurrentDoctype(token); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.missingQuoteBeforeDoctypeSystemIdentifier); + token.forceQuirks = true; + this.state = State.BOGUS_DOCTYPE; + this._stateBogusDoctype(cp); + } + } + } + // Before DOCTYPE system identifier state + //------------------------------------------------------------------ + _stateBeforeDoctypeSystemIdentifier(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.QUOTATION_MARK: { + token.systemId = ""; + this.state = State.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED; + break; + } + case CODE_POINTS.APOSTROPHE: { + token.systemId = ""; + this.state = State.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.missingDoctypeSystemIdentifier); + token.forceQuirks = true; + this.state = State.DATA; + this.emitCurrentDoctype(token); + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.missingQuoteBeforeDoctypeSystemIdentifier); + token.forceQuirks = true; + this.state = State.BOGUS_DOCTYPE; + this._stateBogusDoctype(cp); + } + } + } + // DOCTYPE system identifier (double-quoted) state + //------------------------------------------------------------------ + _stateDoctypeSystemIdentifierDoubleQuoted(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.QUOTATION_MARK: { + this.state = State.AFTER_DOCTYPE_SYSTEM_IDENTIFIER; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + token.systemId += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.abruptDoctypeSystemIdentifier); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this.state = State.DATA; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + token.systemId += String.fromCodePoint(cp); + } + } + } + // DOCTYPE system identifier (single-quoted) state + //------------------------------------------------------------------ + _stateDoctypeSystemIdentifierSingleQuoted(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.APOSTROPHE: { + this.state = State.AFTER_DOCTYPE_SYSTEM_IDENTIFIER; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + token.systemId += REPLACEMENT_CHARACTER; + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this._err(ERR.abruptDoctypeSystemIdentifier); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this.state = State.DATA; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + token.systemId += String.fromCodePoint(cp); + } + } + } + // After DOCTYPE system identifier state + //------------------------------------------------------------------ + _stateAfterDoctypeSystemIdentifier(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.SPACE: + case CODE_POINTS.LINE_FEED: + case CODE_POINTS.TABULATION: + case CODE_POINTS.FORM_FEED: { + break; + } + case CODE_POINTS.GREATER_THAN_SIGN: { + this.emitCurrentDoctype(token); + this.state = State.DATA; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInDoctype); + token.forceQuirks = true; + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: { + this._err(ERR.unexpectedCharacterAfterDoctypeSystemIdentifier); + this.state = State.BOGUS_DOCTYPE; + this._stateBogusDoctype(cp); + } + } + } + // Bogus DOCTYPE state + //------------------------------------------------------------------ + _stateBogusDoctype(cp) { + const token = this.currentToken; + switch (cp) { + case CODE_POINTS.GREATER_THAN_SIGN: { + this.emitCurrentDoctype(token); + this.state = State.DATA; + break; + } + case CODE_POINTS.NULL: { + this._err(ERR.unexpectedNullCharacter); + break; + } + case CODE_POINTS.EOF: { + this.emitCurrentDoctype(token); + this._emitEOFToken(); + break; + } + default: + } + } + // CDATA section state + //------------------------------------------------------------------ + _stateCdataSection(cp) { + switch (cp) { + case CODE_POINTS.RIGHT_SQUARE_BRACKET: { + this.state = State.CDATA_SECTION_BRACKET; + break; + } + case CODE_POINTS.EOF: { + this._err(ERR.eofInCdata); + this._emitEOFToken(); + break; + } + default: { + this._emitCodePoint(cp); + } + } + } + // CDATA section bracket state + //------------------------------------------------------------------ + _stateCdataSectionBracket(cp) { + if (cp === CODE_POINTS.RIGHT_SQUARE_BRACKET) { + this.state = State.CDATA_SECTION_END; + } else { + this._emitChars("]"); + this.state = State.CDATA_SECTION; + this._stateCdataSection(cp); + } + } + // CDATA section end state + //------------------------------------------------------------------ + _stateCdataSectionEnd(cp) { + switch (cp) { + case CODE_POINTS.GREATER_THAN_SIGN: { + this.state = State.DATA; + break; + } + case CODE_POINTS.RIGHT_SQUARE_BRACKET: { + this._emitChars("]"); + break; + } + default: { + this._emitChars("]]"); + this.state = State.CDATA_SECTION; + this._stateCdataSection(cp); + } + } + } + // Character reference state + //------------------------------------------------------------------ + _stateCharacterReference() { + let length = this.entityDecoder.write(this.preprocessor.html, this.preprocessor.pos); + if (length < 0) { + if (this.preprocessor.lastChunkWritten) { + length = this.entityDecoder.end(); + } else { + this.active = false; + this.preprocessor.pos = this.preprocessor.html.length - 1; + this.consumedAfterSnapshot = 0; + this.preprocessor.endOfChunkHit = true; + return; + } + } + if (length === 0) { + this.preprocessor.pos = this.entityStartPos; + this._flushCodePointConsumedAsCharacterReference(CODE_POINTS.AMPERSAND); + this.state = !this._isCharacterReferenceInAttribute() && isAsciiAlphaNumeric2(this.preprocessor.peek(1)) ? State.AMBIGUOUS_AMPERSAND : this.returnState; + } else { + this.state = this.returnState; + } + } + // Ambiguos ampersand state + //------------------------------------------------------------------ + _stateAmbiguousAmpersand(cp) { + if (isAsciiAlphaNumeric2(cp)) { + this._flushCodePointConsumedAsCharacterReference(cp); + } else { + if (cp === CODE_POINTS.SEMICOLON) { + this._err(ERR.unknownNamedCharacterReference); + } + this.state = this.returnState; + this._callState(cp); + } + } + }; + } +}); + +// node_modules/parse5/dist/parser/open-element-stack.js +var IMPLICIT_END_TAG_REQUIRED, IMPLICIT_END_TAG_REQUIRED_THOROUGHLY, SCOPING_ELEMENTS_HTML, SCOPING_ELEMENTS_HTML_LIST, SCOPING_ELEMENTS_HTML_BUTTON, SCOPING_ELEMENTS_MATHML, SCOPING_ELEMENTS_SVG, TABLE_ROW_CONTEXT, TABLE_BODY_CONTEXT, TABLE_CONTEXT, TABLE_CELLS, OpenElementStack; +var init_open_element_stack = __esm({ + "node_modules/parse5/dist/parser/open-element-stack.js"() { + init_html(); + IMPLICIT_END_TAG_REQUIRED = /* @__PURE__ */ new Set([TAG_ID.DD, TAG_ID.DT, TAG_ID.LI, TAG_ID.OPTGROUP, TAG_ID.OPTION, TAG_ID.P, TAG_ID.RB, TAG_ID.RP, TAG_ID.RT, TAG_ID.RTC]); + IMPLICIT_END_TAG_REQUIRED_THOROUGHLY = /* @__PURE__ */ new Set([ + ...IMPLICIT_END_TAG_REQUIRED, + TAG_ID.CAPTION, + TAG_ID.COLGROUP, + TAG_ID.TBODY, + TAG_ID.TD, + TAG_ID.TFOOT, + TAG_ID.TH, + TAG_ID.THEAD, + TAG_ID.TR + ]); + SCOPING_ELEMENTS_HTML = /* @__PURE__ */ new Set([ + TAG_ID.APPLET, + TAG_ID.CAPTION, + TAG_ID.HTML, + TAG_ID.MARQUEE, + TAG_ID.OBJECT, + TAG_ID.TABLE, + TAG_ID.TD, + TAG_ID.TEMPLATE, + TAG_ID.TH + ]); + SCOPING_ELEMENTS_HTML_LIST = /* @__PURE__ */ new Set([...SCOPING_ELEMENTS_HTML, TAG_ID.OL, TAG_ID.UL]); + SCOPING_ELEMENTS_HTML_BUTTON = /* @__PURE__ */ new Set([...SCOPING_ELEMENTS_HTML, TAG_ID.BUTTON]); + SCOPING_ELEMENTS_MATHML = /* @__PURE__ */ new Set([TAG_ID.ANNOTATION_XML, TAG_ID.MI, TAG_ID.MN, TAG_ID.MO, TAG_ID.MS, TAG_ID.MTEXT]); + SCOPING_ELEMENTS_SVG = /* @__PURE__ */ new Set([TAG_ID.DESC, TAG_ID.FOREIGN_OBJECT, TAG_ID.TITLE]); + TABLE_ROW_CONTEXT = /* @__PURE__ */ new Set([TAG_ID.TR, TAG_ID.TEMPLATE, TAG_ID.HTML]); + TABLE_BODY_CONTEXT = /* @__PURE__ */ new Set([TAG_ID.TBODY, TAG_ID.TFOOT, TAG_ID.THEAD, TAG_ID.TEMPLATE, TAG_ID.HTML]); + TABLE_CONTEXT = /* @__PURE__ */ new Set([TAG_ID.TABLE, TAG_ID.TEMPLATE, TAG_ID.HTML]); + TABLE_CELLS = /* @__PURE__ */ new Set([TAG_ID.TD, TAG_ID.TH]); + OpenElementStack = class { + get currentTmplContentOrNode() { + return this._isInTemplate() ? this.treeAdapter.getTemplateContent(this.current) : this.current; + } + constructor(document, treeAdapter, handler) { + this.treeAdapter = treeAdapter; + this.handler = handler; + this.items = []; + this.tagIDs = []; + this.stackTop = -1; + this.tmplCount = 0; + this.currentTagId = TAG_ID.UNKNOWN; + this.current = document; + } + //Index of element + _indexOf(element) { + return this.items.lastIndexOf(element, this.stackTop); + } + //Update current element + _isInTemplate() { + return this.currentTagId === TAG_ID.TEMPLATE && this.treeAdapter.getNamespaceURI(this.current) === NS.HTML; + } + _updateCurrentElement() { + this.current = this.items[this.stackTop]; + this.currentTagId = this.tagIDs[this.stackTop]; + } + //Mutations + push(element, tagID) { + this.stackTop++; + this.items[this.stackTop] = element; + this.current = element; + this.tagIDs[this.stackTop] = tagID; + this.currentTagId = tagID; + if (this._isInTemplate()) { + this.tmplCount++; + } + this.handler.onItemPush(element, tagID, true); + } + pop() { + const popped = this.current; + if (this.tmplCount > 0 && this._isInTemplate()) { + this.tmplCount--; + } + this.stackTop--; + this._updateCurrentElement(); + this.handler.onItemPop(popped, true); + } + replace(oldElement, newElement) { + const idx = this._indexOf(oldElement); + this.items[idx] = newElement; + if (idx === this.stackTop) { + this.current = newElement; + } + } + insertAfter(referenceElement, newElement, newElementID) { + const insertionIdx = this._indexOf(referenceElement) + 1; + this.items.splice(insertionIdx, 0, newElement); + this.tagIDs.splice(insertionIdx, 0, newElementID); + this.stackTop++; + if (insertionIdx === this.stackTop) { + this._updateCurrentElement(); + } + if (this.current && this.currentTagId !== void 0) { + this.handler.onItemPush(this.current, this.currentTagId, insertionIdx === this.stackTop); + } + } + popUntilTagNamePopped(tagName) { + let targetIdx = this.stackTop + 1; + do { + targetIdx = this.tagIDs.lastIndexOf(tagName, targetIdx - 1); + } while (targetIdx > 0 && this.treeAdapter.getNamespaceURI(this.items[targetIdx]) !== NS.HTML); + this.shortenToLength(Math.max(targetIdx, 0)); + } + shortenToLength(idx) { + while (this.stackTop >= idx) { + const popped = this.current; + if (this.tmplCount > 0 && this._isInTemplate()) { + this.tmplCount -= 1; + } + this.stackTop--; + this._updateCurrentElement(); + this.handler.onItemPop(popped, this.stackTop < idx); + } + } + popUntilElementPopped(element) { + const idx = this._indexOf(element); + this.shortenToLength(Math.max(idx, 0)); + } + popUntilPopped(tagNames, targetNS) { + const idx = this._indexOfTagNames(tagNames, targetNS); + this.shortenToLength(Math.max(idx, 0)); + } + popUntilNumberedHeaderPopped() { + this.popUntilPopped(NUMBERED_HEADERS, NS.HTML); + } + popUntilTableCellPopped() { + this.popUntilPopped(TABLE_CELLS, NS.HTML); + } + popAllUpToHtmlElement() { + this.tmplCount = 0; + this.shortenToLength(1); + } + _indexOfTagNames(tagNames, namespace) { + for (let i = this.stackTop; i >= 0; i--) { + if (tagNames.has(this.tagIDs[i]) && this.treeAdapter.getNamespaceURI(this.items[i]) === namespace) { + return i; + } + } + return -1; + } + clearBackTo(tagNames, targetNS) { + const idx = this._indexOfTagNames(tagNames, targetNS); + this.shortenToLength(idx + 1); + } + clearBackToTableContext() { + this.clearBackTo(TABLE_CONTEXT, NS.HTML); + } + clearBackToTableBodyContext() { + this.clearBackTo(TABLE_BODY_CONTEXT, NS.HTML); + } + clearBackToTableRowContext() { + this.clearBackTo(TABLE_ROW_CONTEXT, NS.HTML); + } + remove(element) { + const idx = this._indexOf(element); + if (idx >= 0) { + if (idx === this.stackTop) { + this.pop(); + } else { + this.items.splice(idx, 1); + this.tagIDs.splice(idx, 1); + this.stackTop--; + this._updateCurrentElement(); + this.handler.onItemPop(element, false); + } + } + } + //Search + tryPeekProperlyNestedBodyElement() { + return this.stackTop >= 1 && this.tagIDs[1] === TAG_ID.BODY ? this.items[1] : null; + } + contains(element) { + return this._indexOf(element) > -1; + } + getCommonAncestor(element) { + const elementIdx = this._indexOf(element) - 1; + return elementIdx >= 0 ? this.items[elementIdx] : null; + } + isRootHtmlElementCurrent() { + return this.stackTop === 0 && this.tagIDs[0] === TAG_ID.HTML; + } + //Element in scope + hasInDynamicScope(tagName, htmlScope) { + for (let i = this.stackTop; i >= 0; i--) { + const tn = this.tagIDs[i]; + switch (this.treeAdapter.getNamespaceURI(this.items[i])) { + case NS.HTML: { + if (tn === tagName) + return true; + if (htmlScope.has(tn)) + return false; + break; + } + case NS.SVG: { + if (SCOPING_ELEMENTS_SVG.has(tn)) + return false; + break; + } + case NS.MATHML: { + if (SCOPING_ELEMENTS_MATHML.has(tn)) + return false; + break; + } + } + } + return true; + } + hasInScope(tagName) { + return this.hasInDynamicScope(tagName, SCOPING_ELEMENTS_HTML); + } + hasInListItemScope(tagName) { + return this.hasInDynamicScope(tagName, SCOPING_ELEMENTS_HTML_LIST); + } + hasInButtonScope(tagName) { + return this.hasInDynamicScope(tagName, SCOPING_ELEMENTS_HTML_BUTTON); + } + hasNumberedHeaderInScope() { + for (let i = this.stackTop; i >= 0; i--) { + const tn = this.tagIDs[i]; + switch (this.treeAdapter.getNamespaceURI(this.items[i])) { + case NS.HTML: { + if (NUMBERED_HEADERS.has(tn)) + return true; + if (SCOPING_ELEMENTS_HTML.has(tn)) + return false; + break; + } + case NS.SVG: { + if (SCOPING_ELEMENTS_SVG.has(tn)) + return false; + break; + } + case NS.MATHML: { + if (SCOPING_ELEMENTS_MATHML.has(tn)) + return false; + break; + } + } + } + return true; + } + hasInTableScope(tagName) { + for (let i = this.stackTop; i >= 0; i--) { + if (this.treeAdapter.getNamespaceURI(this.items[i]) !== NS.HTML) { + continue; + } + switch (this.tagIDs[i]) { + case tagName: { + return true; + } + case TAG_ID.TABLE: + case TAG_ID.HTML: { + return false; + } + } + } + return true; + } + hasTableBodyContextInTableScope() { + for (let i = this.stackTop; i >= 0; i--) { + if (this.treeAdapter.getNamespaceURI(this.items[i]) !== NS.HTML) { + continue; + } + switch (this.tagIDs[i]) { + case TAG_ID.TBODY: + case TAG_ID.THEAD: + case TAG_ID.TFOOT: { + return true; + } + case TAG_ID.TABLE: + case TAG_ID.HTML: { + return false; + } + } + } + return true; + } + hasInSelectScope(tagName) { + for (let i = this.stackTop; i >= 0; i--) { + if (this.treeAdapter.getNamespaceURI(this.items[i]) !== NS.HTML) { + continue; + } + switch (this.tagIDs[i]) { + case tagName: { + return true; + } + case TAG_ID.OPTION: + case TAG_ID.OPTGROUP: { + break; + } + default: { + return false; + } + } + } + return true; + } + //Implied end tags + generateImpliedEndTags() { + while (this.currentTagId !== void 0 && IMPLICIT_END_TAG_REQUIRED.has(this.currentTagId)) { + this.pop(); + } + } + generateImpliedEndTagsThoroughly() { + while (this.currentTagId !== void 0 && IMPLICIT_END_TAG_REQUIRED_THOROUGHLY.has(this.currentTagId)) { + this.pop(); + } + } + generateImpliedEndTagsWithExclusion(exclusionId) { + while (this.currentTagId !== void 0 && this.currentTagId !== exclusionId && IMPLICIT_END_TAG_REQUIRED_THOROUGHLY.has(this.currentTagId)) { + this.pop(); + } + } + }; + } +}); + +// node_modules/parse5/dist/parser/formatting-element-list.js +var NOAH_ARK_CAPACITY, EntryType, MARKER, FormattingElementList; +var init_formatting_element_list = __esm({ + "node_modules/parse5/dist/parser/formatting-element-list.js"() { + NOAH_ARK_CAPACITY = 3; + (function(EntryType2) { + EntryType2[EntryType2["Marker"] = 0] = "Marker"; + EntryType2[EntryType2["Element"] = 1] = "Element"; + })(EntryType || (EntryType = {})); + MARKER = { type: EntryType.Marker }; + FormattingElementList = class { + constructor(treeAdapter) { + this.treeAdapter = treeAdapter; + this.entries = []; + this.bookmark = null; + } + //Noah Ark's condition + //OPTIMIZATION: at first we try to find possible candidates for exclusion using + //lightweight heuristics without thorough attributes check. + _getNoahArkConditionCandidates(newElement, neAttrs) { + const candidates = []; + const neAttrsLength = neAttrs.length; + const neTagName = this.treeAdapter.getTagName(newElement); + const neNamespaceURI = this.treeAdapter.getNamespaceURI(newElement); + for (let i = 0; i < this.entries.length; i++) { + const entry = this.entries[i]; + if (entry.type === EntryType.Marker) { + break; + } + const { element } = entry; + if (this.treeAdapter.getTagName(element) === neTagName && this.treeAdapter.getNamespaceURI(element) === neNamespaceURI) { + const elementAttrs = this.treeAdapter.getAttrList(element); + if (elementAttrs.length === neAttrsLength) { + candidates.push({ idx: i, attrs: elementAttrs }); + } + } + } + return candidates; + } + _ensureNoahArkCondition(newElement) { + if (this.entries.length < NOAH_ARK_CAPACITY) + return; + const neAttrs = this.treeAdapter.getAttrList(newElement); + const candidates = this._getNoahArkConditionCandidates(newElement, neAttrs); + if (candidates.length < NOAH_ARK_CAPACITY) + return; + const neAttrsMap = new Map(neAttrs.map((neAttr) => [neAttr.name, neAttr.value])); + let validCandidates = 0; + for (let i = 0; i < candidates.length; i++) { + const candidate = candidates[i]; + if (candidate.attrs.every((cAttr) => neAttrsMap.get(cAttr.name) === cAttr.value)) { + validCandidates += 1; + if (validCandidates >= NOAH_ARK_CAPACITY) { + this.entries.splice(candidate.idx, 1); + } + } + } + } + //Mutations + insertMarker() { + this.entries.unshift(MARKER); + } + pushElement(element, token) { + this._ensureNoahArkCondition(element); + this.entries.unshift({ + type: EntryType.Element, + element, + token + }); + } + insertElementAfterBookmark(element, token) { + const bookmarkIdx = this.entries.indexOf(this.bookmark); + this.entries.splice(bookmarkIdx, 0, { + type: EntryType.Element, + element, + token + }); + } + removeEntry(entry) { + const entryIndex = this.entries.indexOf(entry); + if (entryIndex !== -1) { + this.entries.splice(entryIndex, 1); + } + } + /** + * Clears the list of formatting elements up to the last marker. + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#clear-the-list-of-active-formatting-elements-up-to-the-last-marker + */ + clearToLastMarker() { + const markerIdx = this.entries.indexOf(MARKER); + if (markerIdx === -1) { + this.entries.length = 0; + } else { + this.entries.splice(0, markerIdx + 1); + } + } + //Search + getElementEntryInScopeWithTagName(tagName) { + const entry = this.entries.find((entry2) => entry2.type === EntryType.Marker || this.treeAdapter.getTagName(entry2.element) === tagName); + return entry && entry.type === EntryType.Element ? entry : null; + } + getElementEntry(element) { + return this.entries.find((entry) => entry.type === EntryType.Element && entry.element === element); + } + }; + } +}); + +// node_modules/parse5/dist/tree-adapters/default.js +var defaultTreeAdapter; +var init_default = __esm({ + "node_modules/parse5/dist/tree-adapters/default.js"() { + init_html(); + defaultTreeAdapter = { + //Node construction + createDocument() { + return { + nodeName: "#document", + mode: DOCUMENT_MODE.NO_QUIRKS, + childNodes: [] + }; + }, + createDocumentFragment() { + return { + nodeName: "#document-fragment", + childNodes: [] + }; + }, + createElement(tagName, namespaceURI, attrs) { + return { + nodeName: tagName, + tagName, + attrs, + namespaceURI, + childNodes: [], + parentNode: null + }; + }, + createCommentNode(data) { + return { + nodeName: "#comment", + data, + parentNode: null + }; + }, + createTextNode(value) { + return { + nodeName: "#text", + value, + parentNode: null + }; + }, + //Tree mutation + appendChild(parentNode, newNode) { + parentNode.childNodes.push(newNode); + newNode.parentNode = parentNode; + }, + insertBefore(parentNode, newNode, referenceNode) { + const insertionIdx = parentNode.childNodes.indexOf(referenceNode); + parentNode.childNodes.splice(insertionIdx, 0, newNode); + newNode.parentNode = parentNode; + }, + setTemplateContent(templateElement, contentElement) { + templateElement.content = contentElement; + }, + getTemplateContent(templateElement) { + return templateElement.content; + }, + setDocumentType(document, name, publicId, systemId) { + const doctypeNode = document.childNodes.find((node) => node.nodeName === "#documentType"); + if (doctypeNode) { + doctypeNode.name = name; + doctypeNode.publicId = publicId; + doctypeNode.systemId = systemId; + } else { + const node = { + nodeName: "#documentType", + name, + publicId, + systemId, + parentNode: null + }; + defaultTreeAdapter.appendChild(document, node); + } + }, + setDocumentMode(document, mode) { + document.mode = mode; + }, + getDocumentMode(document) { + return document.mode; + }, + detachNode(node) { + if (node.parentNode) { + const idx = node.parentNode.childNodes.indexOf(node); + node.parentNode.childNodes.splice(idx, 1); + node.parentNode = null; + } + }, + insertText(parentNode, text) { + if (parentNode.childNodes.length > 0) { + const prevNode = parentNode.childNodes[parentNode.childNodes.length - 1]; + if (defaultTreeAdapter.isTextNode(prevNode)) { + prevNode.value += text; + return; + } + } + defaultTreeAdapter.appendChild(parentNode, defaultTreeAdapter.createTextNode(text)); + }, + insertTextBefore(parentNode, text, referenceNode) { + const prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1]; + if (prevNode && defaultTreeAdapter.isTextNode(prevNode)) { + prevNode.value += text; + } else { + defaultTreeAdapter.insertBefore(parentNode, defaultTreeAdapter.createTextNode(text), referenceNode); + } + }, + adoptAttributes(recipient, attrs) { + const recipientAttrsMap = new Set(recipient.attrs.map((attr) => attr.name)); + for (let j = 0; j < attrs.length; j++) { + if (!recipientAttrsMap.has(attrs[j].name)) { + recipient.attrs.push(attrs[j]); + } + } + }, + //Tree traversing + getFirstChild(node) { + return node.childNodes[0]; + }, + getChildNodes(node) { + return node.childNodes; + }, + getParentNode(node) { + return node.parentNode; + }, + getAttrList(element) { + return element.attrs; + }, + //Node data + getTagName(element) { + return element.tagName; + }, + getNamespaceURI(element) { + return element.namespaceURI; + }, + getTextNodeContent(textNode) { + return textNode.value; + }, + getCommentNodeContent(commentNode) { + return commentNode.data; + }, + getDocumentTypeNodeName(doctypeNode) { + return doctypeNode.name; + }, + getDocumentTypeNodePublicId(doctypeNode) { + return doctypeNode.publicId; + }, + getDocumentTypeNodeSystemId(doctypeNode) { + return doctypeNode.systemId; + }, + //Node types + isTextNode(node) { + return node.nodeName === "#text"; + }, + isCommentNode(node) { + return node.nodeName === "#comment"; + }, + isDocumentTypeNode(node) { + return node.nodeName === "#documentType"; + }, + isElementNode(node) { + return Object.prototype.hasOwnProperty.call(node, "tagName"); + }, + // Source code location + setNodeSourceCodeLocation(node, location) { + node.sourceCodeLocation = location; + }, + getNodeSourceCodeLocation(node) { + return node.sourceCodeLocation; + }, + updateNodeSourceCodeLocation(node, endLocation) { + node.sourceCodeLocation = { ...node.sourceCodeLocation, ...endLocation }; + } + }; + } +}); + +// node_modules/parse5/dist/common/doctype.js +function hasPrefix(publicId, prefixes) { + return prefixes.some((prefix) => publicId.startsWith(prefix)); +} +function isConforming(token) { + return token.name === VALID_DOCTYPE_NAME && token.publicId === null && (token.systemId === null || token.systemId === VALID_SYSTEM_ID); +} +function getDocumentMode(token) { + if (token.name !== VALID_DOCTYPE_NAME) { + return DOCUMENT_MODE.QUIRKS; + } + const { systemId } = token; + if (systemId && systemId.toLowerCase() === QUIRKS_MODE_SYSTEM_ID) { + return DOCUMENT_MODE.QUIRKS; + } + let { publicId } = token; + if (publicId !== null) { + publicId = publicId.toLowerCase(); + if (QUIRKS_MODE_PUBLIC_IDS.has(publicId)) { + return DOCUMENT_MODE.QUIRKS; + } + let prefixes = systemId === null ? QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES : QUIRKS_MODE_PUBLIC_ID_PREFIXES; + if (hasPrefix(publicId, prefixes)) { + return DOCUMENT_MODE.QUIRKS; + } + prefixes = systemId === null ? LIMITED_QUIRKS_PUBLIC_ID_PREFIXES : LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES; + if (hasPrefix(publicId, prefixes)) { + return DOCUMENT_MODE.LIMITED_QUIRKS; + } + } + return DOCUMENT_MODE.NO_QUIRKS; +} +var VALID_DOCTYPE_NAME, VALID_SYSTEM_ID, QUIRKS_MODE_SYSTEM_ID, QUIRKS_MODE_PUBLIC_ID_PREFIXES, QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES, QUIRKS_MODE_PUBLIC_IDS, LIMITED_QUIRKS_PUBLIC_ID_PREFIXES, LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES; +var init_doctype = __esm({ + "node_modules/parse5/dist/common/doctype.js"() { + init_html(); + VALID_DOCTYPE_NAME = "html"; + VALID_SYSTEM_ID = "about:legacy-compat"; + QUIRKS_MODE_SYSTEM_ID = "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"; + QUIRKS_MODE_PUBLIC_ID_PREFIXES = [ + "+//silmaril//dtd html pro v0r11 19970101//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//" + ]; + QUIRKS_MODE_NO_SYSTEM_ID_PUBLIC_ID_PREFIXES = [ + ...QUIRKS_MODE_PUBLIC_ID_PREFIXES, + "-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//" + ]; + QUIRKS_MODE_PUBLIC_IDS = /* @__PURE__ */ new Set([ + "-//w3o//dtd w3 html strict 3.0//en//", + "-/w3c/dtd html 4.0 transitional/en", + "html" + ]); + LIMITED_QUIRKS_PUBLIC_ID_PREFIXES = ["-//w3c//dtd xhtml 1.0 frameset//", "-//w3c//dtd xhtml 1.0 transitional//"]; + LIMITED_QUIRKS_WITH_SYSTEM_ID_PUBLIC_ID_PREFIXES = [ + ...LIMITED_QUIRKS_PUBLIC_ID_PREFIXES, + "-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//" + ]; + } +}); + +// node_modules/parse5/dist/common/foreign-content.js +function causesExit(startTagToken) { + const tn = startTagToken.tagID; + const isFontWithAttrs = tn === TAG_ID.FONT && startTagToken.attrs.some(({ name }) => name === ATTRS.COLOR || name === ATTRS.SIZE || name === ATTRS.FACE); + return isFontWithAttrs || EXITS_FOREIGN_CONTENT.has(tn); +} +function adjustTokenMathMLAttrs(token) { + for (let i = 0; i < token.attrs.length; i++) { + if (token.attrs[i].name === DEFINITION_URL_ATTR) { + token.attrs[i].name = ADJUSTED_DEFINITION_URL_ATTR; + break; + } + } +} +function adjustTokenSVGAttrs(token) { + for (let i = 0; i < token.attrs.length; i++) { + const adjustedAttrName = SVG_ATTRS_ADJUSTMENT_MAP.get(token.attrs[i].name); + if (adjustedAttrName != null) { + token.attrs[i].name = adjustedAttrName; + } + } +} +function adjustTokenXMLAttrs(token) { + for (let i = 0; i < token.attrs.length; i++) { + const adjustedAttrEntry = XML_ATTRS_ADJUSTMENT_MAP.get(token.attrs[i].name); + if (adjustedAttrEntry) { + token.attrs[i].prefix = adjustedAttrEntry.prefix; + token.attrs[i].name = adjustedAttrEntry.name; + token.attrs[i].namespace = adjustedAttrEntry.namespace; + } + } +} +function adjustTokenSVGTagName(token) { + const adjustedTagName = SVG_TAG_NAMES_ADJUSTMENT_MAP.get(token.tagName); + if (adjustedTagName != null) { + token.tagName = adjustedTagName; + token.tagID = getTagID(token.tagName); + } +} +function isMathMLTextIntegrationPoint(tn, ns) { + return ns === NS.MATHML && (tn === TAG_ID.MI || tn === TAG_ID.MO || tn === TAG_ID.MN || tn === TAG_ID.MS || tn === TAG_ID.MTEXT); +} +function isHtmlIntegrationPoint(tn, ns, attrs) { + if (ns === NS.MATHML && tn === TAG_ID.ANNOTATION_XML) { + for (let i = 0; i < attrs.length; i++) { + if (attrs[i].name === ATTRS.ENCODING) { + const value = attrs[i].value.toLowerCase(); + return value === MIME_TYPES.TEXT_HTML || value === MIME_TYPES.APPLICATION_XML; + } + } + } + return ns === NS.SVG && (tn === TAG_ID.FOREIGN_OBJECT || tn === TAG_ID.DESC || tn === TAG_ID.TITLE); +} +function isIntegrationPoint(tn, ns, attrs, foreignNS) { + return (!foreignNS || foreignNS === NS.HTML) && isHtmlIntegrationPoint(tn, ns, attrs) || (!foreignNS || foreignNS === NS.MATHML) && isMathMLTextIntegrationPoint(tn, ns); +} +var MIME_TYPES, DEFINITION_URL_ATTR, ADJUSTED_DEFINITION_URL_ATTR, SVG_ATTRS_ADJUSTMENT_MAP, XML_ATTRS_ADJUSTMENT_MAP, SVG_TAG_NAMES_ADJUSTMENT_MAP, EXITS_FOREIGN_CONTENT; +var init_foreign_content = __esm({ + "node_modules/parse5/dist/common/foreign-content.js"() { + init_html(); + MIME_TYPES = { + TEXT_HTML: "text/html", + APPLICATION_XML: "application/xhtml+xml" + }; + DEFINITION_URL_ATTR = "definitionurl"; + ADJUSTED_DEFINITION_URL_ATTR = "definitionURL"; + SVG_ATTRS_ADJUSTMENT_MAP = new Map([ + "attributeName", + "attributeType", + "baseFrequency", + "baseProfile", + "calcMode", + "clipPathUnits", + "diffuseConstant", + "edgeMode", + "filterUnits", + "glyphRef", + "gradientTransform", + "gradientUnits", + "kernelMatrix", + "kernelUnitLength", + "keyPoints", + "keySplines", + "keyTimes", + "lengthAdjust", + "limitingConeAngle", + "markerHeight", + "markerUnits", + "markerWidth", + "maskContentUnits", + "maskUnits", + "numOctaves", + "pathLength", + "patternContentUnits", + "patternTransform", + "patternUnits", + "pointsAtX", + "pointsAtY", + "pointsAtZ", + "preserveAlpha", + "preserveAspectRatio", + "primitiveUnits", + "refX", + "refY", + "repeatCount", + "repeatDur", + "requiredExtensions", + "requiredFeatures", + "specularConstant", + "specularExponent", + "spreadMethod", + "startOffset", + "stdDeviation", + "stitchTiles", + "surfaceScale", + "systemLanguage", + "tableValues", + "targetX", + "targetY", + "textLength", + "viewBox", + "viewTarget", + "xChannelSelector", + "yChannelSelector", + "zoomAndPan" + ].map((attr) => [attr.toLowerCase(), attr])); + XML_ATTRS_ADJUSTMENT_MAP = /* @__PURE__ */ new Map([ + ["xlink:actuate", { prefix: "xlink", name: "actuate", namespace: NS.XLINK }], + ["xlink:arcrole", { prefix: "xlink", name: "arcrole", namespace: NS.XLINK }], + ["xlink:href", { prefix: "xlink", name: "href", namespace: NS.XLINK }], + ["xlink:role", { prefix: "xlink", name: "role", namespace: NS.XLINK }], + ["xlink:show", { prefix: "xlink", name: "show", namespace: NS.XLINK }], + ["xlink:title", { prefix: "xlink", name: "title", namespace: NS.XLINK }], + ["xlink:type", { prefix: "xlink", name: "type", namespace: NS.XLINK }], + ["xml:lang", { prefix: "xml", name: "lang", namespace: NS.XML }], + ["xml:space", { prefix: "xml", name: "space", namespace: NS.XML }], + ["xmlns", { prefix: "", name: "xmlns", namespace: NS.XMLNS }], + ["xmlns:xlink", { prefix: "xmlns", name: "xlink", namespace: NS.XMLNS }] + ]); + SVG_TAG_NAMES_ADJUSTMENT_MAP = new Map([ + "altGlyph", + "altGlyphDef", + "altGlyphItem", + "animateColor", + "animateMotion", + "animateTransform", + "clipPath", + "feBlend", + "feColorMatrix", + "feComponentTransfer", + "feComposite", + "feConvolveMatrix", + "feDiffuseLighting", + "feDisplacementMap", + "feDistantLight", + "feFlood", + "feFuncA", + "feFuncB", + "feFuncG", + "feFuncR", + "feGaussianBlur", + "feImage", + "feMerge", + "feMergeNode", + "feMorphology", + "feOffset", + "fePointLight", + "feSpecularLighting", + "feSpotLight", + "feTile", + "feTurbulence", + "foreignObject", + "glyphRef", + "linearGradient", + "radialGradient", + "textPath" + ].map((tn) => [tn.toLowerCase(), tn])); + EXITS_FOREIGN_CONTENT = /* @__PURE__ */ new Set([ + TAG_ID.B, + TAG_ID.BIG, + TAG_ID.BLOCKQUOTE, + TAG_ID.BODY, + TAG_ID.BR, + TAG_ID.CENTER, + TAG_ID.CODE, + TAG_ID.DD, + TAG_ID.DIV, + TAG_ID.DL, + TAG_ID.DT, + TAG_ID.EM, + TAG_ID.EMBED, + TAG_ID.H1, + TAG_ID.H2, + TAG_ID.H3, + TAG_ID.H4, + TAG_ID.H5, + TAG_ID.H6, + TAG_ID.HEAD, + TAG_ID.HR, + TAG_ID.I, + TAG_ID.IMG, + TAG_ID.LI, + TAG_ID.LISTING, + TAG_ID.MENU, + TAG_ID.META, + TAG_ID.NOBR, + TAG_ID.OL, + TAG_ID.P, + TAG_ID.PRE, + TAG_ID.RUBY, + TAG_ID.S, + TAG_ID.SMALL, + TAG_ID.SPAN, + TAG_ID.STRONG, + TAG_ID.STRIKE, + TAG_ID.SUB, + TAG_ID.SUP, + TAG_ID.TABLE, + TAG_ID.TT, + TAG_ID.U, + TAG_ID.UL, + TAG_ID.VAR + ]); + } +}); + +// node_modules/parse5/dist/parser/index.js +function aaObtainFormattingElementEntry(p, token) { + let formattingElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName(token.tagName); + if (formattingElementEntry) { + if (!p.openElements.contains(formattingElementEntry.element)) { + p.activeFormattingElements.removeEntry(formattingElementEntry); + formattingElementEntry = null; + } else if (!p.openElements.hasInScope(token.tagID)) { + formattingElementEntry = null; + } + } else { + genericEndTagInBody(p, token); + } + return formattingElementEntry; +} +function aaObtainFurthestBlock(p, formattingElementEntry) { + let furthestBlock = null; + let idx = p.openElements.stackTop; + for (; idx >= 0; idx--) { + const element = p.openElements.items[idx]; + if (element === formattingElementEntry.element) { + break; + } + if (p._isSpecialElement(element, p.openElements.tagIDs[idx])) { + furthestBlock = element; + } + } + if (!furthestBlock) { + p.openElements.shortenToLength(Math.max(idx, 0)); + p.activeFormattingElements.removeEntry(formattingElementEntry); + } + return furthestBlock; +} +function aaInnerLoop(p, furthestBlock, formattingElement) { + let lastElement = furthestBlock; + let nextElement = p.openElements.getCommonAncestor(furthestBlock); + for (let i = 0, element = nextElement; element !== formattingElement; i++, element = nextElement) { + nextElement = p.openElements.getCommonAncestor(element); + const elementEntry = p.activeFormattingElements.getElementEntry(element); + const counterOverflow = elementEntry && i >= AA_INNER_LOOP_ITER; + const shouldRemoveFromOpenElements = !elementEntry || counterOverflow; + if (shouldRemoveFromOpenElements) { + if (counterOverflow) { + p.activeFormattingElements.removeEntry(elementEntry); + } + p.openElements.remove(element); + } else { + element = aaRecreateElementFromEntry(p, elementEntry); + if (lastElement === furthestBlock) { + p.activeFormattingElements.bookmark = elementEntry; + } + p.treeAdapter.detachNode(lastElement); + p.treeAdapter.appendChild(element, lastElement); + lastElement = element; + } + } + return lastElement; +} +function aaRecreateElementFromEntry(p, elementEntry) { + const ns = p.treeAdapter.getNamespaceURI(elementEntry.element); + const newElement = p.treeAdapter.createElement(elementEntry.token.tagName, ns, elementEntry.token.attrs); + p.openElements.replace(elementEntry.element, newElement); + elementEntry.element = newElement; + return newElement; +} +function aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement) { + const tn = p.treeAdapter.getTagName(commonAncestor); + const tid = getTagID(tn); + if (p._isElementCausesFosterParenting(tid)) { + p._fosterParentElement(lastElement); + } else { + const ns = p.treeAdapter.getNamespaceURI(commonAncestor); + if (tid === TAG_ID.TEMPLATE && ns === NS.HTML) { + commonAncestor = p.treeAdapter.getTemplateContent(commonAncestor); + } + p.treeAdapter.appendChild(commonAncestor, lastElement); + } +} +function aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry) { + const ns = p.treeAdapter.getNamespaceURI(formattingElementEntry.element); + const { token } = formattingElementEntry; + const newElement = p.treeAdapter.createElement(token.tagName, ns, token.attrs); + p._adoptNodes(furthestBlock, newElement); + p.treeAdapter.appendChild(furthestBlock, newElement); + p.activeFormattingElements.insertElementAfterBookmark(newElement, token); + p.activeFormattingElements.removeEntry(formattingElementEntry); + p.openElements.remove(formattingElementEntry.element); + p.openElements.insertAfter(furthestBlock, newElement, token.tagID); +} +function callAdoptionAgency(p, token) { + for (let i = 0; i < AA_OUTER_LOOP_ITER; i++) { + const formattingElementEntry = aaObtainFormattingElementEntry(p, token); + if (!formattingElementEntry) { + break; + } + const furthestBlock = aaObtainFurthestBlock(p, formattingElementEntry); + if (!furthestBlock) { + break; + } + p.activeFormattingElements.bookmark = formattingElementEntry; + const lastElement = aaInnerLoop(p, furthestBlock, formattingElementEntry.element); + const commonAncestor = p.openElements.getCommonAncestor(formattingElementEntry.element); + p.treeAdapter.detachNode(lastElement); + if (commonAncestor) + aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement); + aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry); + } +} +function appendComment(p, token) { + p._appendCommentNode(token, p.openElements.currentTmplContentOrNode); +} +function appendCommentToRootHtmlElement(p, token) { + p._appendCommentNode(token, p.openElements.items[0]); +} +function appendCommentToDocument(p, token) { + p._appendCommentNode(token, p.document); +} +function stopParsing(p, token) { + p.stopped = true; + if (token.location) { + const target = p.fragmentContext ? 0 : 2; + for (let i = p.openElements.stackTop; i >= target; i--) { + p._setEndLocation(p.openElements.items[i], token); + } + if (!p.fragmentContext && p.openElements.stackTop >= 0) { + const htmlElement = p.openElements.items[0]; + const htmlLocation = p.treeAdapter.getNodeSourceCodeLocation(htmlElement); + if (htmlLocation && !htmlLocation.endTag) { + p._setEndLocation(htmlElement, token); + if (p.openElements.stackTop >= 1) { + const bodyElement = p.openElements.items[1]; + const bodyLocation = p.treeAdapter.getNodeSourceCodeLocation(bodyElement); + if (bodyLocation && !bodyLocation.endTag) { + p._setEndLocation(bodyElement, token); + } + } + } + } + } +} +function doctypeInInitialMode(p, token) { + p._setDocumentType(token); + const mode = token.forceQuirks ? DOCUMENT_MODE.QUIRKS : getDocumentMode(token); + if (!isConforming(token)) { + p._err(token, ERR.nonConformingDoctype); + } + p.treeAdapter.setDocumentMode(p.document, mode); + p.insertionMode = InsertionMode.BEFORE_HTML; +} +function tokenInInitialMode(p, token) { + p._err(token, ERR.missingDoctype, true); + p.treeAdapter.setDocumentMode(p.document, DOCUMENT_MODE.QUIRKS); + p.insertionMode = InsertionMode.BEFORE_HTML; + p._processToken(token); +} +function startTagBeforeHtml(p, token) { + if (token.tagID === TAG_ID.HTML) { + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.BEFORE_HEAD; + } else { + tokenBeforeHtml(p, token); + } +} +function endTagBeforeHtml(p, token) { + const tn = token.tagID; + if (tn === TAG_ID.HTML || tn === TAG_ID.HEAD || tn === TAG_ID.BODY || tn === TAG_ID.BR) { + tokenBeforeHtml(p, token); + } +} +function tokenBeforeHtml(p, token) { + p._insertFakeRootElement(); + p.insertionMode = InsertionMode.BEFORE_HEAD; + p._processToken(token); +} +function startTagBeforeHead(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.HEAD: { + p._insertElement(token, NS.HTML); + p.headElement = p.openElements.current; + p.insertionMode = InsertionMode.IN_HEAD; + break; + } + default: { + tokenBeforeHead(p, token); + } + } +} +function endTagBeforeHead(p, token) { + const tn = token.tagID; + if (tn === TAG_ID.HEAD || tn === TAG_ID.BODY || tn === TAG_ID.HTML || tn === TAG_ID.BR) { + tokenBeforeHead(p, token); + } else { + p._err(token, ERR.endTagWithoutMatchingOpenElement); + } +} +function tokenBeforeHead(p, token) { + p._insertFakeElement(TAG_NAMES.HEAD, TAG_ID.HEAD); + p.headElement = p.openElements.current; + p.insertionMode = InsertionMode.IN_HEAD; + p._processToken(token); +} +function startTagInHead(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.BASE: + case TAG_ID.BASEFONT: + case TAG_ID.BGSOUND: + case TAG_ID.LINK: + case TAG_ID.META: { + p._appendElement(token, NS.HTML); + token.ackSelfClosing = true; + break; + } + case TAG_ID.TITLE: { + p._switchToTextParsing(token, TokenizerMode.RCDATA); + break; + } + case TAG_ID.NOSCRIPT: { + if (p.options.scriptingEnabled) { + p._switchToTextParsing(token, TokenizerMode.RAWTEXT); + } else { + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.IN_HEAD_NO_SCRIPT; + } + break; + } + case TAG_ID.NOFRAMES: + case TAG_ID.STYLE: { + p._switchToTextParsing(token, TokenizerMode.RAWTEXT); + break; + } + case TAG_ID.SCRIPT: { + p._switchToTextParsing(token, TokenizerMode.SCRIPT_DATA); + break; + } + case TAG_ID.TEMPLATE: { + p._insertTemplate(token); + p.activeFormattingElements.insertMarker(); + p.framesetOk = false; + p.insertionMode = InsertionMode.IN_TEMPLATE; + p.tmplInsertionModeStack.unshift(InsertionMode.IN_TEMPLATE); + break; + } + case TAG_ID.HEAD: { + p._err(token, ERR.misplacedStartTagForHeadElement); + break; + } + default: { + tokenInHead(p, token); + } + } +} +function endTagInHead(p, token) { + switch (token.tagID) { + case TAG_ID.HEAD: { + p.openElements.pop(); + p.insertionMode = InsertionMode.AFTER_HEAD; + break; + } + case TAG_ID.BODY: + case TAG_ID.BR: + case TAG_ID.HTML: { + tokenInHead(p, token); + break; + } + case TAG_ID.TEMPLATE: { + templateEndTagInHead(p, token); + break; + } + default: { + p._err(token, ERR.endTagWithoutMatchingOpenElement); + } + } +} +function templateEndTagInHead(p, token) { + if (p.openElements.tmplCount > 0) { + p.openElements.generateImpliedEndTagsThoroughly(); + if (p.openElements.currentTagId !== TAG_ID.TEMPLATE) { + p._err(token, ERR.closingOfElementWithOpenChildElements); + } + p.openElements.popUntilTagNamePopped(TAG_ID.TEMPLATE); + p.activeFormattingElements.clearToLastMarker(); + p.tmplInsertionModeStack.shift(); + p._resetInsertionMode(); + } else { + p._err(token, ERR.endTagWithoutMatchingOpenElement); + } +} +function tokenInHead(p, token) { + p.openElements.pop(); + p.insertionMode = InsertionMode.AFTER_HEAD; + p._processToken(token); +} +function startTagInHeadNoScript(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.BASEFONT: + case TAG_ID.BGSOUND: + case TAG_ID.HEAD: + case TAG_ID.LINK: + case TAG_ID.META: + case TAG_ID.NOFRAMES: + case TAG_ID.STYLE: { + startTagInHead(p, token); + break; + } + case TAG_ID.NOSCRIPT: { + p._err(token, ERR.nestedNoscriptInHead); + break; + } + default: { + tokenInHeadNoScript(p, token); + } + } +} +function endTagInHeadNoScript(p, token) { + switch (token.tagID) { + case TAG_ID.NOSCRIPT: { + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_HEAD; + break; + } + case TAG_ID.BR: { + tokenInHeadNoScript(p, token); + break; + } + default: { + p._err(token, ERR.endTagWithoutMatchingOpenElement); + } + } +} +function tokenInHeadNoScript(p, token) { + const errCode = token.type === TokenType.EOF ? ERR.openElementsLeftAfterEof : ERR.disallowedContentInNoscriptInHead; + p._err(token, errCode); + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_HEAD; + p._processToken(token); +} +function startTagAfterHead(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.BODY: { + p._insertElement(token, NS.HTML); + p.framesetOk = false; + p.insertionMode = InsertionMode.IN_BODY; + break; + } + case TAG_ID.FRAMESET: { + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.IN_FRAMESET; + break; + } + case TAG_ID.BASE: + case TAG_ID.BASEFONT: + case TAG_ID.BGSOUND: + case TAG_ID.LINK: + case TAG_ID.META: + case TAG_ID.NOFRAMES: + case TAG_ID.SCRIPT: + case TAG_ID.STYLE: + case TAG_ID.TEMPLATE: + case TAG_ID.TITLE: { + p._err(token, ERR.abandonedHeadElementChild); + p.openElements.push(p.headElement, TAG_ID.HEAD); + startTagInHead(p, token); + p.openElements.remove(p.headElement); + break; + } + case TAG_ID.HEAD: { + p._err(token, ERR.misplacedStartTagForHeadElement); + break; + } + default: { + tokenAfterHead(p, token); + } + } +} +function endTagAfterHead(p, token) { + switch (token.tagID) { + case TAG_ID.BODY: + case TAG_ID.HTML: + case TAG_ID.BR: { + tokenAfterHead(p, token); + break; + } + case TAG_ID.TEMPLATE: { + templateEndTagInHead(p, token); + break; + } + default: { + p._err(token, ERR.endTagWithoutMatchingOpenElement); + } + } +} +function tokenAfterHead(p, token) { + p._insertFakeElement(TAG_NAMES.BODY, TAG_ID.BODY); + p.insertionMode = InsertionMode.IN_BODY; + modeInBody(p, token); +} +function modeInBody(p, token) { + switch (token.type) { + case TokenType.CHARACTER: { + characterInBody(p, token); + break; + } + case TokenType.WHITESPACE_CHARACTER: { + whitespaceCharacterInBody(p, token); + break; + } + case TokenType.COMMENT: { + appendComment(p, token); + break; + } + case TokenType.START_TAG: { + startTagInBody(p, token); + break; + } + case TokenType.END_TAG: { + endTagInBody(p, token); + break; + } + case TokenType.EOF: { + eofInBody(p, token); + break; + } + default: + } +} +function whitespaceCharacterInBody(p, token) { + p._reconstructActiveFormattingElements(); + p._insertCharacters(token); +} +function characterInBody(p, token) { + p._reconstructActiveFormattingElements(); + p._insertCharacters(token); + p.framesetOk = false; +} +function htmlStartTagInBody(p, token) { + if (p.openElements.tmplCount === 0) { + p.treeAdapter.adoptAttributes(p.openElements.items[0], token.attrs); + } +} +function bodyStartTagInBody(p, token) { + const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement(); + if (bodyElement && p.openElements.tmplCount === 0) { + p.framesetOk = false; + p.treeAdapter.adoptAttributes(bodyElement, token.attrs); + } +} +function framesetStartTagInBody(p, token) { + const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement(); + if (p.framesetOk && bodyElement) { + p.treeAdapter.detachNode(bodyElement); + p.openElements.popAllUpToHtmlElement(); + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.IN_FRAMESET; + } +} +function addressStartTagInBody(p, token) { + if (p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + p._insertElement(token, NS.HTML); +} +function numberedHeaderStartTagInBody(p, token) { + if (p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + if (p.openElements.currentTagId !== void 0 && NUMBERED_HEADERS.has(p.openElements.currentTagId)) { + p.openElements.pop(); + } + p._insertElement(token, NS.HTML); +} +function preStartTagInBody(p, token) { + if (p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + p._insertElement(token, NS.HTML); + p.skipNextNewLine = true; + p.framesetOk = false; +} +function formStartTagInBody(p, token) { + const inTemplate = p.openElements.tmplCount > 0; + if (!p.formElement || inTemplate) { + if (p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + p._insertElement(token, NS.HTML); + if (!inTemplate) { + p.formElement = p.openElements.current; + } + } +} +function listItemStartTagInBody(p, token) { + p.framesetOk = false; + const tn = token.tagID; + for (let i = p.openElements.stackTop; i >= 0; i--) { + const elementId = p.openElements.tagIDs[i]; + if (tn === TAG_ID.LI && elementId === TAG_ID.LI || (tn === TAG_ID.DD || tn === TAG_ID.DT) && (elementId === TAG_ID.DD || elementId === TAG_ID.DT)) { + p.openElements.generateImpliedEndTagsWithExclusion(elementId); + p.openElements.popUntilTagNamePopped(elementId); + break; + } + if (elementId !== TAG_ID.ADDRESS && elementId !== TAG_ID.DIV && elementId !== TAG_ID.P && p._isSpecialElement(p.openElements.items[i], elementId)) { + break; + } + } + if (p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + p._insertElement(token, NS.HTML); +} +function plaintextStartTagInBody(p, token) { + if (p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + p._insertElement(token, NS.HTML); + p.tokenizer.state = TokenizerMode.PLAINTEXT; +} +function buttonStartTagInBody(p, token) { + if (p.openElements.hasInScope(TAG_ID.BUTTON)) { + p.openElements.generateImpliedEndTags(); + p.openElements.popUntilTagNamePopped(TAG_ID.BUTTON); + } + p._reconstructActiveFormattingElements(); + p._insertElement(token, NS.HTML); + p.framesetOk = false; +} +function aStartTagInBody(p, token) { + const activeElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName(TAG_NAMES.A); + if (activeElementEntry) { + callAdoptionAgency(p, token); + p.openElements.remove(activeElementEntry.element); + p.activeFormattingElements.removeEntry(activeElementEntry); + } + p._reconstructActiveFormattingElements(); + p._insertElement(token, NS.HTML); + p.activeFormattingElements.pushElement(p.openElements.current, token); +} +function bStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + p._insertElement(token, NS.HTML); + p.activeFormattingElements.pushElement(p.openElements.current, token); +} +function nobrStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + if (p.openElements.hasInScope(TAG_ID.NOBR)) { + callAdoptionAgency(p, token); + p._reconstructActiveFormattingElements(); + } + p._insertElement(token, NS.HTML); + p.activeFormattingElements.pushElement(p.openElements.current, token); +} +function appletStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + p._insertElement(token, NS.HTML); + p.activeFormattingElements.insertMarker(); + p.framesetOk = false; +} +function tableStartTagInBody(p, token) { + if (p.treeAdapter.getDocumentMode(p.document) !== DOCUMENT_MODE.QUIRKS && p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + p._insertElement(token, NS.HTML); + p.framesetOk = false; + p.insertionMode = InsertionMode.IN_TABLE; +} +function areaStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + p._appendElement(token, NS.HTML); + p.framesetOk = false; + token.ackSelfClosing = true; +} +function isHiddenInput(token) { + const inputType = getTokenAttr(token, ATTRS.TYPE); + return inputType != null && inputType.toLowerCase() === HIDDEN_INPUT_TYPE; +} +function inputStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + p._appendElement(token, NS.HTML); + if (!isHiddenInput(token)) { + p.framesetOk = false; + } + token.ackSelfClosing = true; +} +function paramStartTagInBody(p, token) { + p._appendElement(token, NS.HTML); + token.ackSelfClosing = true; +} +function hrStartTagInBody(p, token) { + if (p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + p._appendElement(token, NS.HTML); + p.framesetOk = false; + token.ackSelfClosing = true; +} +function imageStartTagInBody(p, token) { + token.tagName = TAG_NAMES.IMG; + token.tagID = TAG_ID.IMG; + areaStartTagInBody(p, token); +} +function textareaStartTagInBody(p, token) { + p._insertElement(token, NS.HTML); + p.skipNextNewLine = true; + p.tokenizer.state = TokenizerMode.RCDATA; + p.originalInsertionMode = p.insertionMode; + p.framesetOk = false; + p.insertionMode = InsertionMode.TEXT; +} +function xmpStartTagInBody(p, token) { + if (p.openElements.hasInButtonScope(TAG_ID.P)) { + p._closePElement(); + } + p._reconstructActiveFormattingElements(); + p.framesetOk = false; + p._switchToTextParsing(token, TokenizerMode.RAWTEXT); +} +function iframeStartTagInBody(p, token) { + p.framesetOk = false; + p._switchToTextParsing(token, TokenizerMode.RAWTEXT); +} +function rawTextStartTagInBody(p, token) { + p._switchToTextParsing(token, TokenizerMode.RAWTEXT); +} +function selectStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + p._insertElement(token, NS.HTML); + p.framesetOk = false; + p.insertionMode = p.insertionMode === InsertionMode.IN_TABLE || p.insertionMode === InsertionMode.IN_CAPTION || p.insertionMode === InsertionMode.IN_TABLE_BODY || p.insertionMode === InsertionMode.IN_ROW || p.insertionMode === InsertionMode.IN_CELL ? InsertionMode.IN_SELECT_IN_TABLE : InsertionMode.IN_SELECT; +} +function optgroupStartTagInBody(p, token) { + if (p.openElements.currentTagId === TAG_ID.OPTION) { + p.openElements.pop(); + } + p._reconstructActiveFormattingElements(); + p._insertElement(token, NS.HTML); +} +function rbStartTagInBody(p, token) { + if (p.openElements.hasInScope(TAG_ID.RUBY)) { + p.openElements.generateImpliedEndTags(); + } + p._insertElement(token, NS.HTML); +} +function rtStartTagInBody(p, token) { + if (p.openElements.hasInScope(TAG_ID.RUBY)) { + p.openElements.generateImpliedEndTagsWithExclusion(TAG_ID.RTC); + } + p._insertElement(token, NS.HTML); +} +function mathStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + adjustTokenMathMLAttrs(token); + adjustTokenXMLAttrs(token); + if (token.selfClosing) { + p._appendElement(token, NS.MATHML); + } else { + p._insertElement(token, NS.MATHML); + } + token.ackSelfClosing = true; +} +function svgStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + adjustTokenSVGAttrs(token); + adjustTokenXMLAttrs(token); + if (token.selfClosing) { + p._appendElement(token, NS.SVG); + } else { + p._insertElement(token, NS.SVG); + } + token.ackSelfClosing = true; +} +function genericStartTagInBody(p, token) { + p._reconstructActiveFormattingElements(); + p._insertElement(token, NS.HTML); +} +function startTagInBody(p, token) { + switch (token.tagID) { + case TAG_ID.I: + case TAG_ID.S: + case TAG_ID.B: + case TAG_ID.U: + case TAG_ID.EM: + case TAG_ID.TT: + case TAG_ID.BIG: + case TAG_ID.CODE: + case TAG_ID.FONT: + case TAG_ID.SMALL: + case TAG_ID.STRIKE: + case TAG_ID.STRONG: { + bStartTagInBody(p, token); + break; + } + case TAG_ID.A: { + aStartTagInBody(p, token); + break; + } + case TAG_ID.H1: + case TAG_ID.H2: + case TAG_ID.H3: + case TAG_ID.H4: + case TAG_ID.H5: + case TAG_ID.H6: { + numberedHeaderStartTagInBody(p, token); + break; + } + case TAG_ID.P: + case TAG_ID.DL: + case TAG_ID.OL: + case TAG_ID.UL: + case TAG_ID.DIV: + case TAG_ID.DIR: + case TAG_ID.NAV: + case TAG_ID.MAIN: + case TAG_ID.MENU: + case TAG_ID.ASIDE: + case TAG_ID.CENTER: + case TAG_ID.FIGURE: + case TAG_ID.FOOTER: + case TAG_ID.HEADER: + case TAG_ID.HGROUP: + case TAG_ID.DIALOG: + case TAG_ID.DETAILS: + case TAG_ID.ADDRESS: + case TAG_ID.ARTICLE: + case TAG_ID.SEARCH: + case TAG_ID.SECTION: + case TAG_ID.SUMMARY: + case TAG_ID.FIELDSET: + case TAG_ID.BLOCKQUOTE: + case TAG_ID.FIGCAPTION: { + addressStartTagInBody(p, token); + break; + } + case TAG_ID.LI: + case TAG_ID.DD: + case TAG_ID.DT: { + listItemStartTagInBody(p, token); + break; + } + case TAG_ID.BR: + case TAG_ID.IMG: + case TAG_ID.WBR: + case TAG_ID.AREA: + case TAG_ID.EMBED: + case TAG_ID.KEYGEN: { + areaStartTagInBody(p, token); + break; + } + case TAG_ID.HR: { + hrStartTagInBody(p, token); + break; + } + case TAG_ID.RB: + case TAG_ID.RTC: { + rbStartTagInBody(p, token); + break; + } + case TAG_ID.RT: + case TAG_ID.RP: { + rtStartTagInBody(p, token); + break; + } + case TAG_ID.PRE: + case TAG_ID.LISTING: { + preStartTagInBody(p, token); + break; + } + case TAG_ID.XMP: { + xmpStartTagInBody(p, token); + break; + } + case TAG_ID.SVG: { + svgStartTagInBody(p, token); + break; + } + case TAG_ID.HTML: { + htmlStartTagInBody(p, token); + break; + } + case TAG_ID.BASE: + case TAG_ID.LINK: + case TAG_ID.META: + case TAG_ID.STYLE: + case TAG_ID.TITLE: + case TAG_ID.SCRIPT: + case TAG_ID.BGSOUND: + case TAG_ID.BASEFONT: + case TAG_ID.TEMPLATE: { + startTagInHead(p, token); + break; + } + case TAG_ID.BODY: { + bodyStartTagInBody(p, token); + break; + } + case TAG_ID.FORM: { + formStartTagInBody(p, token); + break; + } + case TAG_ID.NOBR: { + nobrStartTagInBody(p, token); + break; + } + case TAG_ID.MATH: { + mathStartTagInBody(p, token); + break; + } + case TAG_ID.TABLE: { + tableStartTagInBody(p, token); + break; + } + case TAG_ID.INPUT: { + inputStartTagInBody(p, token); + break; + } + case TAG_ID.PARAM: + case TAG_ID.TRACK: + case TAG_ID.SOURCE: { + paramStartTagInBody(p, token); + break; + } + case TAG_ID.IMAGE: { + imageStartTagInBody(p, token); + break; + } + case TAG_ID.BUTTON: { + buttonStartTagInBody(p, token); + break; + } + case TAG_ID.APPLET: + case TAG_ID.OBJECT: + case TAG_ID.MARQUEE: { + appletStartTagInBody(p, token); + break; + } + case TAG_ID.IFRAME: { + iframeStartTagInBody(p, token); + break; + } + case TAG_ID.SELECT: { + selectStartTagInBody(p, token); + break; + } + case TAG_ID.OPTION: + case TAG_ID.OPTGROUP: { + optgroupStartTagInBody(p, token); + break; + } + case TAG_ID.NOEMBED: + case TAG_ID.NOFRAMES: { + rawTextStartTagInBody(p, token); + break; + } + case TAG_ID.FRAMESET: { + framesetStartTagInBody(p, token); + break; + } + case TAG_ID.TEXTAREA: { + textareaStartTagInBody(p, token); + break; + } + case TAG_ID.NOSCRIPT: { + if (p.options.scriptingEnabled) { + rawTextStartTagInBody(p, token); + } else { + genericStartTagInBody(p, token); + } + break; + } + case TAG_ID.PLAINTEXT: { + plaintextStartTagInBody(p, token); + break; + } + case TAG_ID.COL: + case TAG_ID.TH: + case TAG_ID.TD: + case TAG_ID.TR: + case TAG_ID.HEAD: + case TAG_ID.FRAME: + case TAG_ID.TBODY: + case TAG_ID.TFOOT: + case TAG_ID.THEAD: + case TAG_ID.CAPTION: + case TAG_ID.COLGROUP: { + break; + } + default: { + genericStartTagInBody(p, token); + } + } +} +function bodyEndTagInBody(p, token) { + if (p.openElements.hasInScope(TAG_ID.BODY)) { + p.insertionMode = InsertionMode.AFTER_BODY; + if (p.options.sourceCodeLocationInfo) { + const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement(); + if (bodyElement) { + p._setEndLocation(bodyElement, token); + } + } + } +} +function htmlEndTagInBody(p, token) { + if (p.openElements.hasInScope(TAG_ID.BODY)) { + p.insertionMode = InsertionMode.AFTER_BODY; + endTagAfterBody(p, token); + } +} +function addressEndTagInBody(p, token) { + const tn = token.tagID; + if (p.openElements.hasInScope(tn)) { + p.openElements.generateImpliedEndTags(); + p.openElements.popUntilTagNamePopped(tn); + } +} +function formEndTagInBody(p) { + const inTemplate = p.openElements.tmplCount > 0; + const { formElement } = p; + if (!inTemplate) { + p.formElement = null; + } + if ((formElement || inTemplate) && p.openElements.hasInScope(TAG_ID.FORM)) { + p.openElements.generateImpliedEndTags(); + if (inTemplate) { + p.openElements.popUntilTagNamePopped(TAG_ID.FORM); + } else if (formElement) { + p.openElements.remove(formElement); + } + } +} +function pEndTagInBody(p) { + if (!p.openElements.hasInButtonScope(TAG_ID.P)) { + p._insertFakeElement(TAG_NAMES.P, TAG_ID.P); + } + p._closePElement(); +} +function liEndTagInBody(p) { + if (p.openElements.hasInListItemScope(TAG_ID.LI)) { + p.openElements.generateImpliedEndTagsWithExclusion(TAG_ID.LI); + p.openElements.popUntilTagNamePopped(TAG_ID.LI); + } +} +function ddEndTagInBody(p, token) { + const tn = token.tagID; + if (p.openElements.hasInScope(tn)) { + p.openElements.generateImpliedEndTagsWithExclusion(tn); + p.openElements.popUntilTagNamePopped(tn); + } +} +function numberedHeaderEndTagInBody(p) { + if (p.openElements.hasNumberedHeaderInScope()) { + p.openElements.generateImpliedEndTags(); + p.openElements.popUntilNumberedHeaderPopped(); + } +} +function appletEndTagInBody(p, token) { + const tn = token.tagID; + if (p.openElements.hasInScope(tn)) { + p.openElements.generateImpliedEndTags(); + p.openElements.popUntilTagNamePopped(tn); + p.activeFormattingElements.clearToLastMarker(); + } +} +function brEndTagInBody(p) { + p._reconstructActiveFormattingElements(); + p._insertFakeElement(TAG_NAMES.BR, TAG_ID.BR); + p.openElements.pop(); + p.framesetOk = false; +} +function genericEndTagInBody(p, token) { + const tn = token.tagName; + const tid = token.tagID; + for (let i = p.openElements.stackTop; i > 0; i--) { + const element = p.openElements.items[i]; + const elementId = p.openElements.tagIDs[i]; + if (tid === elementId && (tid !== TAG_ID.UNKNOWN || p.treeAdapter.getTagName(element) === tn)) { + p.openElements.generateImpliedEndTagsWithExclusion(tid); + if (p.openElements.stackTop >= i) + p.openElements.shortenToLength(i); + break; + } + if (p._isSpecialElement(element, elementId)) { + break; + } + } +} +function endTagInBody(p, token) { + switch (token.tagID) { + case TAG_ID.A: + case TAG_ID.B: + case TAG_ID.I: + case TAG_ID.S: + case TAG_ID.U: + case TAG_ID.EM: + case TAG_ID.TT: + case TAG_ID.BIG: + case TAG_ID.CODE: + case TAG_ID.FONT: + case TAG_ID.NOBR: + case TAG_ID.SMALL: + case TAG_ID.STRIKE: + case TAG_ID.STRONG: { + callAdoptionAgency(p, token); + break; + } + case TAG_ID.P: { + pEndTagInBody(p); + break; + } + case TAG_ID.DL: + case TAG_ID.UL: + case TAG_ID.OL: + case TAG_ID.DIR: + case TAG_ID.DIV: + case TAG_ID.NAV: + case TAG_ID.PRE: + case TAG_ID.MAIN: + case TAG_ID.MENU: + case TAG_ID.ASIDE: + case TAG_ID.BUTTON: + case TAG_ID.CENTER: + case TAG_ID.FIGURE: + case TAG_ID.FOOTER: + case TAG_ID.HEADER: + case TAG_ID.HGROUP: + case TAG_ID.DIALOG: + case TAG_ID.ADDRESS: + case TAG_ID.ARTICLE: + case TAG_ID.DETAILS: + case TAG_ID.SEARCH: + case TAG_ID.SECTION: + case TAG_ID.SUMMARY: + case TAG_ID.LISTING: + case TAG_ID.FIELDSET: + case TAG_ID.BLOCKQUOTE: + case TAG_ID.FIGCAPTION: { + addressEndTagInBody(p, token); + break; + } + case TAG_ID.LI: { + liEndTagInBody(p); + break; + } + case TAG_ID.DD: + case TAG_ID.DT: { + ddEndTagInBody(p, token); + break; + } + case TAG_ID.H1: + case TAG_ID.H2: + case TAG_ID.H3: + case TAG_ID.H4: + case TAG_ID.H5: + case TAG_ID.H6: { + numberedHeaderEndTagInBody(p); + break; + } + case TAG_ID.BR: { + brEndTagInBody(p); + break; + } + case TAG_ID.BODY: { + bodyEndTagInBody(p, token); + break; + } + case TAG_ID.HTML: { + htmlEndTagInBody(p, token); + break; + } + case TAG_ID.FORM: { + formEndTagInBody(p); + break; + } + case TAG_ID.APPLET: + case TAG_ID.OBJECT: + case TAG_ID.MARQUEE: { + appletEndTagInBody(p, token); + break; + } + case TAG_ID.TEMPLATE: { + templateEndTagInHead(p, token); + break; + } + default: { + genericEndTagInBody(p, token); + } + } +} +function eofInBody(p, token) { + if (p.tmplInsertionModeStack.length > 0) { + eofInTemplate(p, token); + } else { + stopParsing(p, token); + } +} +function endTagInText(p, token) { + var _a2; + if (token.tagID === TAG_ID.SCRIPT) { + (_a2 = p.scriptHandler) === null || _a2 === void 0 ? void 0 : _a2.call(p, p.openElements.current); + } + p.openElements.pop(); + p.insertionMode = p.originalInsertionMode; +} +function eofInText(p, token) { + p._err(token, ERR.eofInElementThatCanContainOnlyText); + p.openElements.pop(); + p.insertionMode = p.originalInsertionMode; + p.onEof(token); +} +function characterInTable(p, token) { + if (p.openElements.currentTagId !== void 0 && TABLE_STRUCTURE_TAGS.has(p.openElements.currentTagId)) { + p.pendingCharacterTokens.length = 0; + p.hasNonWhitespacePendingCharacterToken = false; + p.originalInsertionMode = p.insertionMode; + p.insertionMode = InsertionMode.IN_TABLE_TEXT; + switch (token.type) { + case TokenType.CHARACTER: { + characterInTableText(p, token); + break; + } + case TokenType.WHITESPACE_CHARACTER: { + whitespaceCharacterInTableText(p, token); + break; + } + } + } else { + tokenInTable(p, token); + } +} +function captionStartTagInTable(p, token) { + p.openElements.clearBackToTableContext(); + p.activeFormattingElements.insertMarker(); + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.IN_CAPTION; +} +function colgroupStartTagInTable(p, token) { + p.openElements.clearBackToTableContext(); + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.IN_COLUMN_GROUP; +} +function colStartTagInTable(p, token) { + p.openElements.clearBackToTableContext(); + p._insertFakeElement(TAG_NAMES.COLGROUP, TAG_ID.COLGROUP); + p.insertionMode = InsertionMode.IN_COLUMN_GROUP; + startTagInColumnGroup(p, token); +} +function tbodyStartTagInTable(p, token) { + p.openElements.clearBackToTableContext(); + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.IN_TABLE_BODY; +} +function tdStartTagInTable(p, token) { + p.openElements.clearBackToTableContext(); + p._insertFakeElement(TAG_NAMES.TBODY, TAG_ID.TBODY); + p.insertionMode = InsertionMode.IN_TABLE_BODY; + startTagInTableBody(p, token); +} +function tableStartTagInTable(p, token) { + if (p.openElements.hasInTableScope(TAG_ID.TABLE)) { + p.openElements.popUntilTagNamePopped(TAG_ID.TABLE); + p._resetInsertionMode(); + p._processStartTag(token); + } +} +function inputStartTagInTable(p, token) { + if (isHiddenInput(token)) { + p._appendElement(token, NS.HTML); + } else { + tokenInTable(p, token); + } + token.ackSelfClosing = true; +} +function formStartTagInTable(p, token) { + if (!p.formElement && p.openElements.tmplCount === 0) { + p._insertElement(token, NS.HTML); + p.formElement = p.openElements.current; + p.openElements.pop(); + } +} +function startTagInTable(p, token) { + switch (token.tagID) { + case TAG_ID.TD: + case TAG_ID.TH: + case TAG_ID.TR: { + tdStartTagInTable(p, token); + break; + } + case TAG_ID.STYLE: + case TAG_ID.SCRIPT: + case TAG_ID.TEMPLATE: { + startTagInHead(p, token); + break; + } + case TAG_ID.COL: { + colStartTagInTable(p, token); + break; + } + case TAG_ID.FORM: { + formStartTagInTable(p, token); + break; + } + case TAG_ID.TABLE: { + tableStartTagInTable(p, token); + break; + } + case TAG_ID.TBODY: + case TAG_ID.TFOOT: + case TAG_ID.THEAD: { + tbodyStartTagInTable(p, token); + break; + } + case TAG_ID.INPUT: { + inputStartTagInTable(p, token); + break; + } + case TAG_ID.CAPTION: { + captionStartTagInTable(p, token); + break; + } + case TAG_ID.COLGROUP: { + colgroupStartTagInTable(p, token); + break; + } + default: { + tokenInTable(p, token); + } + } +} +function endTagInTable(p, token) { + switch (token.tagID) { + case TAG_ID.TABLE: { + if (p.openElements.hasInTableScope(TAG_ID.TABLE)) { + p.openElements.popUntilTagNamePopped(TAG_ID.TABLE); + p._resetInsertionMode(); + } + break; + } + case TAG_ID.TEMPLATE: { + templateEndTagInHead(p, token); + break; + } + case TAG_ID.BODY: + case TAG_ID.CAPTION: + case TAG_ID.COL: + case TAG_ID.COLGROUP: + case TAG_ID.HTML: + case TAG_ID.TBODY: + case TAG_ID.TD: + case TAG_ID.TFOOT: + case TAG_ID.TH: + case TAG_ID.THEAD: + case TAG_ID.TR: { + break; + } + default: { + tokenInTable(p, token); + } + } +} +function tokenInTable(p, token) { + const savedFosterParentingState = p.fosterParentingEnabled; + p.fosterParentingEnabled = true; + modeInBody(p, token); + p.fosterParentingEnabled = savedFosterParentingState; +} +function whitespaceCharacterInTableText(p, token) { + p.pendingCharacterTokens.push(token); +} +function characterInTableText(p, token) { + p.pendingCharacterTokens.push(token); + p.hasNonWhitespacePendingCharacterToken = true; +} +function tokenInTableText(p, token) { + let i = 0; + if (p.hasNonWhitespacePendingCharacterToken) { + for (; i < p.pendingCharacterTokens.length; i++) { + tokenInTable(p, p.pendingCharacterTokens[i]); + } + } else { + for (; i < p.pendingCharacterTokens.length; i++) { + p._insertCharacters(p.pendingCharacterTokens[i]); + } + } + p.insertionMode = p.originalInsertionMode; + p._processToken(token); +} +function startTagInCaption(p, token) { + const tn = token.tagID; + if (TABLE_VOID_ELEMENTS.has(tn)) { + if (p.openElements.hasInTableScope(TAG_ID.CAPTION)) { + p.openElements.generateImpliedEndTags(); + p.openElements.popUntilTagNamePopped(TAG_ID.CAPTION); + p.activeFormattingElements.clearToLastMarker(); + p.insertionMode = InsertionMode.IN_TABLE; + startTagInTable(p, token); + } + } else { + startTagInBody(p, token); + } +} +function endTagInCaption(p, token) { + const tn = token.tagID; + switch (tn) { + case TAG_ID.CAPTION: + case TAG_ID.TABLE: { + if (p.openElements.hasInTableScope(TAG_ID.CAPTION)) { + p.openElements.generateImpliedEndTags(); + p.openElements.popUntilTagNamePopped(TAG_ID.CAPTION); + p.activeFormattingElements.clearToLastMarker(); + p.insertionMode = InsertionMode.IN_TABLE; + if (tn === TAG_ID.TABLE) { + endTagInTable(p, token); + } + } + break; + } + case TAG_ID.BODY: + case TAG_ID.COL: + case TAG_ID.COLGROUP: + case TAG_ID.HTML: + case TAG_ID.TBODY: + case TAG_ID.TD: + case TAG_ID.TFOOT: + case TAG_ID.TH: + case TAG_ID.THEAD: + case TAG_ID.TR: { + break; + } + default: { + endTagInBody(p, token); + } + } +} +function startTagInColumnGroup(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.COL: { + p._appendElement(token, NS.HTML); + token.ackSelfClosing = true; + break; + } + case TAG_ID.TEMPLATE: { + startTagInHead(p, token); + break; + } + default: { + tokenInColumnGroup(p, token); + } + } +} +function endTagInColumnGroup(p, token) { + switch (token.tagID) { + case TAG_ID.COLGROUP: { + if (p.openElements.currentTagId === TAG_ID.COLGROUP) { + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE; + } + break; + } + case TAG_ID.TEMPLATE: { + templateEndTagInHead(p, token); + break; + } + case TAG_ID.COL: { + break; + } + default: { + tokenInColumnGroup(p, token); + } + } +} +function tokenInColumnGroup(p, token) { + if (p.openElements.currentTagId === TAG_ID.COLGROUP) { + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE; + p._processToken(token); + } +} +function startTagInTableBody(p, token) { + switch (token.tagID) { + case TAG_ID.TR: { + p.openElements.clearBackToTableBodyContext(); + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.IN_ROW; + break; + } + case TAG_ID.TH: + case TAG_ID.TD: { + p.openElements.clearBackToTableBodyContext(); + p._insertFakeElement(TAG_NAMES.TR, TAG_ID.TR); + p.insertionMode = InsertionMode.IN_ROW; + startTagInRow(p, token); + break; + } + case TAG_ID.CAPTION: + case TAG_ID.COL: + case TAG_ID.COLGROUP: + case TAG_ID.TBODY: + case TAG_ID.TFOOT: + case TAG_ID.THEAD: { + if (p.openElements.hasTableBodyContextInTableScope()) { + p.openElements.clearBackToTableBodyContext(); + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE; + startTagInTable(p, token); + } + break; + } + default: { + startTagInTable(p, token); + } + } +} +function endTagInTableBody(p, token) { + const tn = token.tagID; + switch (token.tagID) { + case TAG_ID.TBODY: + case TAG_ID.TFOOT: + case TAG_ID.THEAD: { + if (p.openElements.hasInTableScope(tn)) { + p.openElements.clearBackToTableBodyContext(); + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE; + } + break; + } + case TAG_ID.TABLE: { + if (p.openElements.hasTableBodyContextInTableScope()) { + p.openElements.clearBackToTableBodyContext(); + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE; + endTagInTable(p, token); + } + break; + } + case TAG_ID.BODY: + case TAG_ID.CAPTION: + case TAG_ID.COL: + case TAG_ID.COLGROUP: + case TAG_ID.HTML: + case TAG_ID.TD: + case TAG_ID.TH: + case TAG_ID.TR: { + break; + } + default: { + endTagInTable(p, token); + } + } +} +function startTagInRow(p, token) { + switch (token.tagID) { + case TAG_ID.TH: + case TAG_ID.TD: { + p.openElements.clearBackToTableRowContext(); + p._insertElement(token, NS.HTML); + p.insertionMode = InsertionMode.IN_CELL; + p.activeFormattingElements.insertMarker(); + break; + } + case TAG_ID.CAPTION: + case TAG_ID.COL: + case TAG_ID.COLGROUP: + case TAG_ID.TBODY: + case TAG_ID.TFOOT: + case TAG_ID.THEAD: + case TAG_ID.TR: { + if (p.openElements.hasInTableScope(TAG_ID.TR)) { + p.openElements.clearBackToTableRowContext(); + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE_BODY; + startTagInTableBody(p, token); + } + break; + } + default: { + startTagInTable(p, token); + } + } +} +function endTagInRow(p, token) { + switch (token.tagID) { + case TAG_ID.TR: { + if (p.openElements.hasInTableScope(TAG_ID.TR)) { + p.openElements.clearBackToTableRowContext(); + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE_BODY; + } + break; + } + case TAG_ID.TABLE: { + if (p.openElements.hasInTableScope(TAG_ID.TR)) { + p.openElements.clearBackToTableRowContext(); + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE_BODY; + endTagInTableBody(p, token); + } + break; + } + case TAG_ID.TBODY: + case TAG_ID.TFOOT: + case TAG_ID.THEAD: { + if (p.openElements.hasInTableScope(token.tagID) || p.openElements.hasInTableScope(TAG_ID.TR)) { + p.openElements.clearBackToTableRowContext(); + p.openElements.pop(); + p.insertionMode = InsertionMode.IN_TABLE_BODY; + endTagInTableBody(p, token); + } + break; + } + case TAG_ID.BODY: + case TAG_ID.CAPTION: + case TAG_ID.COL: + case TAG_ID.COLGROUP: + case TAG_ID.HTML: + case TAG_ID.TD: + case TAG_ID.TH: { + break; + } + default: { + endTagInTable(p, token); + } + } +} +function startTagInCell(p, token) { + const tn = token.tagID; + if (TABLE_VOID_ELEMENTS.has(tn)) { + if (p.openElements.hasInTableScope(TAG_ID.TD) || p.openElements.hasInTableScope(TAG_ID.TH)) { + p._closeTableCell(); + startTagInRow(p, token); + } + } else { + startTagInBody(p, token); + } +} +function endTagInCell(p, token) { + const tn = token.tagID; + switch (tn) { + case TAG_ID.TD: + case TAG_ID.TH: { + if (p.openElements.hasInTableScope(tn)) { + p.openElements.generateImpliedEndTags(); + p.openElements.popUntilTagNamePopped(tn); + p.activeFormattingElements.clearToLastMarker(); + p.insertionMode = InsertionMode.IN_ROW; + } + break; + } + case TAG_ID.TABLE: + case TAG_ID.TBODY: + case TAG_ID.TFOOT: + case TAG_ID.THEAD: + case TAG_ID.TR: { + if (p.openElements.hasInTableScope(tn)) { + p._closeTableCell(); + endTagInRow(p, token); + } + break; + } + case TAG_ID.BODY: + case TAG_ID.CAPTION: + case TAG_ID.COL: + case TAG_ID.COLGROUP: + case TAG_ID.HTML: { + break; + } + default: { + endTagInBody(p, token); + } + } +} +function startTagInSelect(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.OPTION: { + if (p.openElements.currentTagId === TAG_ID.OPTION) { + p.openElements.pop(); + } + p._insertElement(token, NS.HTML); + break; + } + case TAG_ID.OPTGROUP: { + if (p.openElements.currentTagId === TAG_ID.OPTION) { + p.openElements.pop(); + } + if (p.openElements.currentTagId === TAG_ID.OPTGROUP) { + p.openElements.pop(); + } + p._insertElement(token, NS.HTML); + break; + } + case TAG_ID.HR: { + if (p.openElements.currentTagId === TAG_ID.OPTION) { + p.openElements.pop(); + } + if (p.openElements.currentTagId === TAG_ID.OPTGROUP) { + p.openElements.pop(); + } + p._appendElement(token, NS.HTML); + token.ackSelfClosing = true; + break; + } + case TAG_ID.INPUT: + case TAG_ID.KEYGEN: + case TAG_ID.TEXTAREA: + case TAG_ID.SELECT: { + if (p.openElements.hasInSelectScope(TAG_ID.SELECT)) { + p.openElements.popUntilTagNamePopped(TAG_ID.SELECT); + p._resetInsertionMode(); + if (token.tagID !== TAG_ID.SELECT) { + p._processStartTag(token); + } + } + break; + } + case TAG_ID.SCRIPT: + case TAG_ID.TEMPLATE: { + startTagInHead(p, token); + break; + } + default: + } +} +function endTagInSelect(p, token) { + switch (token.tagID) { + case TAG_ID.OPTGROUP: { + if (p.openElements.stackTop > 0 && p.openElements.currentTagId === TAG_ID.OPTION && p.openElements.tagIDs[p.openElements.stackTop - 1] === TAG_ID.OPTGROUP) { + p.openElements.pop(); + } + if (p.openElements.currentTagId === TAG_ID.OPTGROUP) { + p.openElements.pop(); + } + break; + } + case TAG_ID.OPTION: { + if (p.openElements.currentTagId === TAG_ID.OPTION) { + p.openElements.pop(); + } + break; + } + case TAG_ID.SELECT: { + if (p.openElements.hasInSelectScope(TAG_ID.SELECT)) { + p.openElements.popUntilTagNamePopped(TAG_ID.SELECT); + p._resetInsertionMode(); + } + break; + } + case TAG_ID.TEMPLATE: { + templateEndTagInHead(p, token); + break; + } + default: + } +} +function startTagInSelectInTable(p, token) { + const tn = token.tagID; + if (tn === TAG_ID.CAPTION || tn === TAG_ID.TABLE || tn === TAG_ID.TBODY || tn === TAG_ID.TFOOT || tn === TAG_ID.THEAD || tn === TAG_ID.TR || tn === TAG_ID.TD || tn === TAG_ID.TH) { + p.openElements.popUntilTagNamePopped(TAG_ID.SELECT); + p._resetInsertionMode(); + p._processStartTag(token); + } else { + startTagInSelect(p, token); + } +} +function endTagInSelectInTable(p, token) { + const tn = token.tagID; + if (tn === TAG_ID.CAPTION || tn === TAG_ID.TABLE || tn === TAG_ID.TBODY || tn === TAG_ID.TFOOT || tn === TAG_ID.THEAD || tn === TAG_ID.TR || tn === TAG_ID.TD || tn === TAG_ID.TH) { + if (p.openElements.hasInTableScope(tn)) { + p.openElements.popUntilTagNamePopped(TAG_ID.SELECT); + p._resetInsertionMode(); + p.onEndTag(token); + } + } else { + endTagInSelect(p, token); + } +} +function startTagInTemplate(p, token) { + switch (token.tagID) { + // First, handle tags that can start without a mode change + case TAG_ID.BASE: + case TAG_ID.BASEFONT: + case TAG_ID.BGSOUND: + case TAG_ID.LINK: + case TAG_ID.META: + case TAG_ID.NOFRAMES: + case TAG_ID.SCRIPT: + case TAG_ID.STYLE: + case TAG_ID.TEMPLATE: + case TAG_ID.TITLE: { + startTagInHead(p, token); + break; + } + // Re-process the token in the appropriate mode + case TAG_ID.CAPTION: + case TAG_ID.COLGROUP: + case TAG_ID.TBODY: + case TAG_ID.TFOOT: + case TAG_ID.THEAD: { + p.tmplInsertionModeStack[0] = InsertionMode.IN_TABLE; + p.insertionMode = InsertionMode.IN_TABLE; + startTagInTable(p, token); + break; + } + case TAG_ID.COL: { + p.tmplInsertionModeStack[0] = InsertionMode.IN_COLUMN_GROUP; + p.insertionMode = InsertionMode.IN_COLUMN_GROUP; + startTagInColumnGroup(p, token); + break; + } + case TAG_ID.TR: { + p.tmplInsertionModeStack[0] = InsertionMode.IN_TABLE_BODY; + p.insertionMode = InsertionMode.IN_TABLE_BODY; + startTagInTableBody(p, token); + break; + } + case TAG_ID.TD: + case TAG_ID.TH: { + p.tmplInsertionModeStack[0] = InsertionMode.IN_ROW; + p.insertionMode = InsertionMode.IN_ROW; + startTagInRow(p, token); + break; + } + default: { + p.tmplInsertionModeStack[0] = InsertionMode.IN_BODY; + p.insertionMode = InsertionMode.IN_BODY; + startTagInBody(p, token); + } + } +} +function endTagInTemplate(p, token) { + if (token.tagID === TAG_ID.TEMPLATE) { + templateEndTagInHead(p, token); + } +} +function eofInTemplate(p, token) { + if (p.openElements.tmplCount > 0) { + p.openElements.popUntilTagNamePopped(TAG_ID.TEMPLATE); + p.activeFormattingElements.clearToLastMarker(); + p.tmplInsertionModeStack.shift(); + p._resetInsertionMode(); + p.onEof(token); + } else { + stopParsing(p, token); + } +} +function startTagAfterBody(p, token) { + if (token.tagID === TAG_ID.HTML) { + startTagInBody(p, token); + } else { + tokenAfterBody(p, token); + } +} +function endTagAfterBody(p, token) { + var _a2; + if (token.tagID === TAG_ID.HTML) { + if (!p.fragmentContext) { + p.insertionMode = InsertionMode.AFTER_AFTER_BODY; + } + if (p.options.sourceCodeLocationInfo && p.openElements.tagIDs[0] === TAG_ID.HTML) { + p._setEndLocation(p.openElements.items[0], token); + const bodyElement = p.openElements.items[1]; + if (bodyElement && !((_a2 = p.treeAdapter.getNodeSourceCodeLocation(bodyElement)) === null || _a2 === void 0 ? void 0 : _a2.endTag)) { + p._setEndLocation(bodyElement, token); + } + } + } else { + tokenAfterBody(p, token); + } +} +function tokenAfterBody(p, token) { + p.insertionMode = InsertionMode.IN_BODY; + modeInBody(p, token); +} +function startTagInFrameset(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.FRAMESET: { + p._insertElement(token, NS.HTML); + break; + } + case TAG_ID.FRAME: { + p._appendElement(token, NS.HTML); + token.ackSelfClosing = true; + break; + } + case TAG_ID.NOFRAMES: { + startTagInHead(p, token); + break; + } + default: + } +} +function endTagInFrameset(p, token) { + if (token.tagID === TAG_ID.FRAMESET && !p.openElements.isRootHtmlElementCurrent()) { + p.openElements.pop(); + if (!p.fragmentContext && p.openElements.currentTagId !== TAG_ID.FRAMESET) { + p.insertionMode = InsertionMode.AFTER_FRAMESET; + } + } +} +function startTagAfterFrameset(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.NOFRAMES: { + startTagInHead(p, token); + break; + } + default: + } +} +function endTagAfterFrameset(p, token) { + if (token.tagID === TAG_ID.HTML) { + p.insertionMode = InsertionMode.AFTER_AFTER_FRAMESET; + } +} +function startTagAfterAfterBody(p, token) { + if (token.tagID === TAG_ID.HTML) { + startTagInBody(p, token); + } else { + tokenAfterAfterBody(p, token); + } +} +function tokenAfterAfterBody(p, token) { + p.insertionMode = InsertionMode.IN_BODY; + modeInBody(p, token); +} +function startTagAfterAfterFrameset(p, token) { + switch (token.tagID) { + case TAG_ID.HTML: { + startTagInBody(p, token); + break; + } + case TAG_ID.NOFRAMES: { + startTagInHead(p, token); + break; + } + default: + } +} +function nullCharacterInForeignContent(p, token) { + token.chars = REPLACEMENT_CHARACTER; + p._insertCharacters(token); +} +function characterInForeignContent(p, token) { + p._insertCharacters(token); + p.framesetOk = false; +} +function popUntilHtmlOrIntegrationPoint(p) { + while (p.treeAdapter.getNamespaceURI(p.openElements.current) !== NS.HTML && p.openElements.currentTagId !== void 0 && !p._isIntegrationPoint(p.openElements.currentTagId, p.openElements.current)) { + p.openElements.pop(); + } +} +function startTagInForeignContent(p, token) { + if (causesExit(token)) { + popUntilHtmlOrIntegrationPoint(p); + p._startTagOutsideForeignContent(token); + } else { + const current = p._getAdjustedCurrentElement(); + const currentNs = p.treeAdapter.getNamespaceURI(current); + if (currentNs === NS.MATHML) { + adjustTokenMathMLAttrs(token); + } else if (currentNs === NS.SVG) { + adjustTokenSVGTagName(token); + adjustTokenSVGAttrs(token); + } + adjustTokenXMLAttrs(token); + if (token.selfClosing) { + p._appendElement(token, currentNs); + } else { + p._insertElement(token, currentNs); + } + token.ackSelfClosing = true; + } +} +function endTagInForeignContent(p, token) { + if (token.tagID === TAG_ID.P || token.tagID === TAG_ID.BR) { + popUntilHtmlOrIntegrationPoint(p); + p._endTagOutsideForeignContent(token); + return; + } + for (let i = p.openElements.stackTop; i > 0; i--) { + const element = p.openElements.items[i]; + if (p.treeAdapter.getNamespaceURI(element) === NS.HTML) { + p._endTagOutsideForeignContent(token); + break; + } + const tagName = p.treeAdapter.getTagName(element); + if (tagName.toLowerCase() === token.tagName) { + token.tagName = tagName; + p.openElements.shortenToLength(i); + break; + } + } +} +var HIDDEN_INPUT_TYPE, AA_OUTER_LOOP_ITER, AA_INNER_LOOP_ITER, InsertionMode, BASE_LOC, TABLE_STRUCTURE_TAGS, defaultParserOptions, Parser, TABLE_VOID_ELEMENTS; +var init_parser = __esm({ + "node_modules/parse5/dist/parser/index.js"() { + init_tokenizer(); + init_open_element_stack(); + init_formatting_element_list(); + init_default(); + init_doctype(); + init_foreign_content(); + init_error_codes(); + init_unicode(); + init_html(); + init_token(); + HIDDEN_INPUT_TYPE = "hidden"; + AA_OUTER_LOOP_ITER = 8; + AA_INNER_LOOP_ITER = 3; + (function(InsertionMode2) { + InsertionMode2[InsertionMode2["INITIAL"] = 0] = "INITIAL"; + InsertionMode2[InsertionMode2["BEFORE_HTML"] = 1] = "BEFORE_HTML"; + InsertionMode2[InsertionMode2["BEFORE_HEAD"] = 2] = "BEFORE_HEAD"; + InsertionMode2[InsertionMode2["IN_HEAD"] = 3] = "IN_HEAD"; + InsertionMode2[InsertionMode2["IN_HEAD_NO_SCRIPT"] = 4] = "IN_HEAD_NO_SCRIPT"; + InsertionMode2[InsertionMode2["AFTER_HEAD"] = 5] = "AFTER_HEAD"; + InsertionMode2[InsertionMode2["IN_BODY"] = 6] = "IN_BODY"; + InsertionMode2[InsertionMode2["TEXT"] = 7] = "TEXT"; + InsertionMode2[InsertionMode2["IN_TABLE"] = 8] = "IN_TABLE"; + InsertionMode2[InsertionMode2["IN_TABLE_TEXT"] = 9] = "IN_TABLE_TEXT"; + InsertionMode2[InsertionMode2["IN_CAPTION"] = 10] = "IN_CAPTION"; + InsertionMode2[InsertionMode2["IN_COLUMN_GROUP"] = 11] = "IN_COLUMN_GROUP"; + InsertionMode2[InsertionMode2["IN_TABLE_BODY"] = 12] = "IN_TABLE_BODY"; + InsertionMode2[InsertionMode2["IN_ROW"] = 13] = "IN_ROW"; + InsertionMode2[InsertionMode2["IN_CELL"] = 14] = "IN_CELL"; + InsertionMode2[InsertionMode2["IN_SELECT"] = 15] = "IN_SELECT"; + InsertionMode2[InsertionMode2["IN_SELECT_IN_TABLE"] = 16] = "IN_SELECT_IN_TABLE"; + InsertionMode2[InsertionMode2["IN_TEMPLATE"] = 17] = "IN_TEMPLATE"; + InsertionMode2[InsertionMode2["AFTER_BODY"] = 18] = "AFTER_BODY"; + InsertionMode2[InsertionMode2["IN_FRAMESET"] = 19] = "IN_FRAMESET"; + InsertionMode2[InsertionMode2["AFTER_FRAMESET"] = 20] = "AFTER_FRAMESET"; + InsertionMode2[InsertionMode2["AFTER_AFTER_BODY"] = 21] = "AFTER_AFTER_BODY"; + InsertionMode2[InsertionMode2["AFTER_AFTER_FRAMESET"] = 22] = "AFTER_AFTER_FRAMESET"; + })(InsertionMode || (InsertionMode = {})); + BASE_LOC = { + startLine: -1, + startCol: -1, + startOffset: -1, + endLine: -1, + endCol: -1, + endOffset: -1 + }; + TABLE_STRUCTURE_TAGS = /* @__PURE__ */ new Set([TAG_ID.TABLE, TAG_ID.TBODY, TAG_ID.TFOOT, TAG_ID.THEAD, TAG_ID.TR]); + defaultParserOptions = { + scriptingEnabled: true, + sourceCodeLocationInfo: false, + treeAdapter: defaultTreeAdapter, + onParseError: null + }; + Parser = class { + constructor(options, document, fragmentContext = null, scriptHandler = null) { + this.fragmentContext = fragmentContext; + this.scriptHandler = scriptHandler; + this.currentToken = null; + this.stopped = false; + this.insertionMode = InsertionMode.INITIAL; + this.originalInsertionMode = InsertionMode.INITIAL; + this.headElement = null; + this.formElement = null; + this.currentNotInHTML = false; + this.tmplInsertionModeStack = []; + this.pendingCharacterTokens = []; + this.hasNonWhitespacePendingCharacterToken = false; + this.framesetOk = true; + this.skipNextNewLine = false; + this.fosterParentingEnabled = false; + this.options = { + ...defaultParserOptions, + ...options + }; + this.treeAdapter = this.options.treeAdapter; + this.onParseError = this.options.onParseError; + if (this.onParseError) { + this.options.sourceCodeLocationInfo = true; + } + this.document = document !== null && document !== void 0 ? document : this.treeAdapter.createDocument(); + this.tokenizer = new Tokenizer(this.options, this); + this.activeFormattingElements = new FormattingElementList(this.treeAdapter); + this.fragmentContextID = fragmentContext ? getTagID(this.treeAdapter.getTagName(fragmentContext)) : TAG_ID.UNKNOWN; + this._setContextModes(fragmentContext !== null && fragmentContext !== void 0 ? fragmentContext : this.document, this.fragmentContextID); + this.openElements = new OpenElementStack(this.document, this.treeAdapter, this); + } + // API + static parse(html, options) { + const parser = new this(options); + parser.tokenizer.write(html, true); + return parser.document; + } + static getFragmentParser(fragmentContext, options) { + const opts = { + ...defaultParserOptions, + ...options + }; + fragmentContext !== null && fragmentContext !== void 0 ? fragmentContext : fragmentContext = opts.treeAdapter.createElement(TAG_NAMES.TEMPLATE, NS.HTML, []); + const documentMock = opts.treeAdapter.createElement("documentmock", NS.HTML, []); + const parser = new this(opts, documentMock, fragmentContext); + if (parser.fragmentContextID === TAG_ID.TEMPLATE) { + parser.tmplInsertionModeStack.unshift(InsertionMode.IN_TEMPLATE); + } + parser._initTokenizerForFragmentParsing(); + parser._insertFakeRootElement(); + parser._resetInsertionMode(); + parser._findFormInFragmentContext(); + return parser; + } + getFragment() { + const rootElement = this.treeAdapter.getFirstChild(this.document); + const fragment = this.treeAdapter.createDocumentFragment(); + this._adoptNodes(rootElement, fragment); + return fragment; + } + //Errors + /** @internal */ + _err(token, code, beforeToken) { + var _a2; + if (!this.onParseError) + return; + const loc = (_a2 = token.location) !== null && _a2 !== void 0 ? _a2 : BASE_LOC; + const err = { + code, + startLine: loc.startLine, + startCol: loc.startCol, + startOffset: loc.startOffset, + endLine: beforeToken ? loc.startLine : loc.endLine, + endCol: beforeToken ? loc.startCol : loc.endCol, + endOffset: beforeToken ? loc.startOffset : loc.endOffset + }; + this.onParseError(err); + } + //Stack events + /** @internal */ + onItemPush(node, tid, isTop) { + var _a2, _b; + (_b = (_a2 = this.treeAdapter).onItemPush) === null || _b === void 0 ? void 0 : _b.call(_a2, node); + if (isTop && this.openElements.stackTop > 0) + this._setContextModes(node, tid); + } + /** @internal */ + onItemPop(node, isTop) { + var _a2, _b; + if (this.options.sourceCodeLocationInfo) { + this._setEndLocation(node, this.currentToken); + } + (_b = (_a2 = this.treeAdapter).onItemPop) === null || _b === void 0 ? void 0 : _b.call(_a2, node, this.openElements.current); + if (isTop) { + let current; + let currentTagId; + if (this.openElements.stackTop === 0 && this.fragmentContext) { + current = this.fragmentContext; + currentTagId = this.fragmentContextID; + } else { + ({ current, currentTagId } = this.openElements); + } + this._setContextModes(current, currentTagId); + } + } + _setContextModes(current, tid) { + const isHTML = current === this.document || current && this.treeAdapter.getNamespaceURI(current) === NS.HTML; + this.currentNotInHTML = !isHTML; + this.tokenizer.inForeignNode = !isHTML && current !== void 0 && tid !== void 0 && !this._isIntegrationPoint(tid, current); + } + /** @protected */ + _switchToTextParsing(currentToken, nextTokenizerState) { + this._insertElement(currentToken, NS.HTML); + this.tokenizer.state = nextTokenizerState; + this.originalInsertionMode = this.insertionMode; + this.insertionMode = InsertionMode.TEXT; + } + switchToPlaintextParsing() { + this.insertionMode = InsertionMode.TEXT; + this.originalInsertionMode = InsertionMode.IN_BODY; + this.tokenizer.state = TokenizerMode.PLAINTEXT; + } + //Fragment parsing + /** @protected */ + _getAdjustedCurrentElement() { + return this.openElements.stackTop === 0 && this.fragmentContext ? this.fragmentContext : this.openElements.current; + } + /** @protected */ + _findFormInFragmentContext() { + let node = this.fragmentContext; + while (node) { + if (this.treeAdapter.getTagName(node) === TAG_NAMES.FORM) { + this.formElement = node; + break; + } + node = this.treeAdapter.getParentNode(node); + } + } + _initTokenizerForFragmentParsing() { + if (!this.fragmentContext || this.treeAdapter.getNamespaceURI(this.fragmentContext) !== NS.HTML) { + return; + } + switch (this.fragmentContextID) { + case TAG_ID.TITLE: + case TAG_ID.TEXTAREA: { + this.tokenizer.state = TokenizerMode.RCDATA; + break; + } + case TAG_ID.STYLE: + case TAG_ID.XMP: + case TAG_ID.IFRAME: + case TAG_ID.NOEMBED: + case TAG_ID.NOFRAMES: + case TAG_ID.NOSCRIPT: { + this.tokenizer.state = TokenizerMode.RAWTEXT; + break; + } + case TAG_ID.SCRIPT: { + this.tokenizer.state = TokenizerMode.SCRIPT_DATA; + break; + } + case TAG_ID.PLAINTEXT: { + this.tokenizer.state = TokenizerMode.PLAINTEXT; + break; + } + default: + } + } + //Tree mutation + /** @protected */ + _setDocumentType(token) { + const name = token.name || ""; + const publicId = token.publicId || ""; + const systemId = token.systemId || ""; + this.treeAdapter.setDocumentType(this.document, name, publicId, systemId); + if (token.location) { + const documentChildren = this.treeAdapter.getChildNodes(this.document); + const docTypeNode = documentChildren.find((node) => this.treeAdapter.isDocumentTypeNode(node)); + if (docTypeNode) { + this.treeAdapter.setNodeSourceCodeLocation(docTypeNode, token.location); + } + } + } + /** @protected */ + _attachElementToTree(element, location) { + if (this.options.sourceCodeLocationInfo) { + const loc = location && { + ...location, + startTag: location + }; + this.treeAdapter.setNodeSourceCodeLocation(element, loc); + } + if (this._shouldFosterParentOnInsertion()) { + this._fosterParentElement(element); + } else { + const parent = this.openElements.currentTmplContentOrNode; + this.treeAdapter.appendChild(parent !== null && parent !== void 0 ? parent : this.document, element); + } + } + /** + * For self-closing tags. Add an element to the tree, but skip adding it + * to the stack. + */ + /** @protected */ + _appendElement(token, namespaceURI) { + const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs); + this._attachElementToTree(element, token.location); + } + /** @protected */ + _insertElement(token, namespaceURI) { + const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs); + this._attachElementToTree(element, token.location); + this.openElements.push(element, token.tagID); + } + /** @protected */ + _insertFakeElement(tagName, tagID) { + const element = this.treeAdapter.createElement(tagName, NS.HTML, []); + this._attachElementToTree(element, null); + this.openElements.push(element, tagID); + } + /** @protected */ + _insertTemplate(token) { + const tmpl = this.treeAdapter.createElement(token.tagName, NS.HTML, token.attrs); + const content = this.treeAdapter.createDocumentFragment(); + this.treeAdapter.setTemplateContent(tmpl, content); + this._attachElementToTree(tmpl, token.location); + this.openElements.push(tmpl, token.tagID); + if (this.options.sourceCodeLocationInfo) + this.treeAdapter.setNodeSourceCodeLocation(content, null); + } + /** @protected */ + _insertFakeRootElement() { + const element = this.treeAdapter.createElement(TAG_NAMES.HTML, NS.HTML, []); + if (this.options.sourceCodeLocationInfo) + this.treeAdapter.setNodeSourceCodeLocation(element, null); + this.treeAdapter.appendChild(this.openElements.current, element); + this.openElements.push(element, TAG_ID.HTML); + } + /** @protected */ + _appendCommentNode(token, parent) { + const commentNode = this.treeAdapter.createCommentNode(token.data); + this.treeAdapter.appendChild(parent, commentNode); + if (this.options.sourceCodeLocationInfo) { + this.treeAdapter.setNodeSourceCodeLocation(commentNode, token.location); + } + } + /** @protected */ + _insertCharacters(token) { + let parent; + let beforeElement; + if (this._shouldFosterParentOnInsertion()) { + ({ parent, beforeElement } = this._findFosterParentingLocation()); + if (beforeElement) { + this.treeAdapter.insertTextBefore(parent, token.chars, beforeElement); + } else { + this.treeAdapter.insertText(parent, token.chars); + } + } else { + parent = this.openElements.currentTmplContentOrNode; + this.treeAdapter.insertText(parent, token.chars); + } + if (!token.location) + return; + const siblings = this.treeAdapter.getChildNodes(parent); + const textNodeIdx = beforeElement ? siblings.lastIndexOf(beforeElement) : siblings.length; + const textNode = siblings[textNodeIdx - 1]; + const tnLoc = this.treeAdapter.getNodeSourceCodeLocation(textNode); + if (tnLoc) { + const { endLine, endCol, endOffset } = token.location; + this.treeAdapter.updateNodeSourceCodeLocation(textNode, { endLine, endCol, endOffset }); + } else if (this.options.sourceCodeLocationInfo) { + this.treeAdapter.setNodeSourceCodeLocation(textNode, token.location); + } + } + /** @protected */ + _adoptNodes(donor, recipient) { + for (let child = this.treeAdapter.getFirstChild(donor); child; child = this.treeAdapter.getFirstChild(donor)) { + this.treeAdapter.detachNode(child); + this.treeAdapter.appendChild(recipient, child); + } + } + /** @protected */ + _setEndLocation(element, closingToken) { + if (this.treeAdapter.getNodeSourceCodeLocation(element) && closingToken.location) { + const ctLoc = closingToken.location; + const tn = this.treeAdapter.getTagName(element); + const endLoc = ( + // NOTE: For cases like

    - First 'p' closes without a closing + // tag and for cases like

    - 'p' closes without a closing tag. + closingToken.type === TokenType.END_TAG && tn === closingToken.tagName ? { + endTag: { ...ctLoc }, + endLine: ctLoc.endLine, + endCol: ctLoc.endCol, + endOffset: ctLoc.endOffset + } : { + endLine: ctLoc.startLine, + endCol: ctLoc.startCol, + endOffset: ctLoc.startOffset + } + ); + this.treeAdapter.updateNodeSourceCodeLocation(element, endLoc); + } + } + //Token processing + shouldProcessStartTagTokenInForeignContent(token) { + if (!this.currentNotInHTML) + return false; + let current; + let currentTagId; + if (this.openElements.stackTop === 0 && this.fragmentContext) { + current = this.fragmentContext; + currentTagId = this.fragmentContextID; + } else { + ({ current, currentTagId } = this.openElements); + } + if (token.tagID === TAG_ID.SVG && this.treeAdapter.getTagName(current) === TAG_NAMES.ANNOTATION_XML && this.treeAdapter.getNamespaceURI(current) === NS.MATHML) { + return false; + } + return ( + // Check that `current` is not an integration point for HTML or MathML elements. + this.tokenizer.inForeignNode || // If it _is_ an integration point, then we might have to check that it is not an HTML + // integration point. + (token.tagID === TAG_ID.MGLYPH || token.tagID === TAG_ID.MALIGNMARK) && currentTagId !== void 0 && !this._isIntegrationPoint(currentTagId, current, NS.HTML) + ); + } + /** @protected */ + _processToken(token) { + switch (token.type) { + case TokenType.CHARACTER: { + this.onCharacter(token); + break; + } + case TokenType.NULL_CHARACTER: { + this.onNullCharacter(token); + break; + } + case TokenType.COMMENT: { + this.onComment(token); + break; + } + case TokenType.DOCTYPE: { + this.onDoctype(token); + break; + } + case TokenType.START_TAG: { + this._processStartTag(token); + break; + } + case TokenType.END_TAG: { + this.onEndTag(token); + break; + } + case TokenType.EOF: { + this.onEof(token); + break; + } + case TokenType.WHITESPACE_CHARACTER: { + this.onWhitespaceCharacter(token); + break; + } + } + } + //Integration points + /** @protected */ + _isIntegrationPoint(tid, element, foreignNS) { + const ns = this.treeAdapter.getNamespaceURI(element); + const attrs = this.treeAdapter.getAttrList(element); + return isIntegrationPoint(tid, ns, attrs, foreignNS); + } + //Active formatting elements reconstruction + /** @protected */ + _reconstructActiveFormattingElements() { + const listLength = this.activeFormattingElements.entries.length; + if (listLength) { + const endIndex = this.activeFormattingElements.entries.findIndex((entry) => entry.type === EntryType.Marker || this.openElements.contains(entry.element)); + const unopenIdx = endIndex === -1 ? listLength - 1 : endIndex - 1; + for (let i = unopenIdx; i >= 0; i--) { + const entry = this.activeFormattingElements.entries[i]; + this._insertElement(entry.token, this.treeAdapter.getNamespaceURI(entry.element)); + entry.element = this.openElements.current; + } + } + } + //Close elements + /** @protected */ + _closeTableCell() { + this.openElements.generateImpliedEndTags(); + this.openElements.popUntilTableCellPopped(); + this.activeFormattingElements.clearToLastMarker(); + this.insertionMode = InsertionMode.IN_ROW; + } + /** @protected */ + _closePElement() { + this.openElements.generateImpliedEndTagsWithExclusion(TAG_ID.P); + this.openElements.popUntilTagNamePopped(TAG_ID.P); + } + //Insertion modes + /** @protected */ + _resetInsertionMode() { + for (let i = this.openElements.stackTop; i >= 0; i--) { + switch (i === 0 && this.fragmentContext ? this.fragmentContextID : this.openElements.tagIDs[i]) { + case TAG_ID.TR: { + this.insertionMode = InsertionMode.IN_ROW; + return; + } + case TAG_ID.TBODY: + case TAG_ID.THEAD: + case TAG_ID.TFOOT: { + this.insertionMode = InsertionMode.IN_TABLE_BODY; + return; + } + case TAG_ID.CAPTION: { + this.insertionMode = InsertionMode.IN_CAPTION; + return; + } + case TAG_ID.COLGROUP: { + this.insertionMode = InsertionMode.IN_COLUMN_GROUP; + return; + } + case TAG_ID.TABLE: { + this.insertionMode = InsertionMode.IN_TABLE; + return; + } + case TAG_ID.BODY: { + this.insertionMode = InsertionMode.IN_BODY; + return; + } + case TAG_ID.FRAMESET: { + this.insertionMode = InsertionMode.IN_FRAMESET; + return; + } + case TAG_ID.SELECT: { + this._resetInsertionModeForSelect(i); + return; + } + case TAG_ID.TEMPLATE: { + this.insertionMode = this.tmplInsertionModeStack[0]; + return; + } + case TAG_ID.HTML: { + this.insertionMode = this.headElement ? InsertionMode.AFTER_HEAD : InsertionMode.BEFORE_HEAD; + return; + } + case TAG_ID.TD: + case TAG_ID.TH: { + if (i > 0) { + this.insertionMode = InsertionMode.IN_CELL; + return; + } + break; + } + case TAG_ID.HEAD: { + if (i > 0) { + this.insertionMode = InsertionMode.IN_HEAD; + return; + } + break; + } + } + } + this.insertionMode = InsertionMode.IN_BODY; + } + /** @protected */ + _resetInsertionModeForSelect(selectIdx) { + if (selectIdx > 0) { + for (let i = selectIdx - 1; i > 0; i--) { + const tn = this.openElements.tagIDs[i]; + if (tn === TAG_ID.TEMPLATE) { + break; + } else if (tn === TAG_ID.TABLE) { + this.insertionMode = InsertionMode.IN_SELECT_IN_TABLE; + return; + } + } + } + this.insertionMode = InsertionMode.IN_SELECT; + } + //Foster parenting + /** @protected */ + _isElementCausesFosterParenting(tn) { + return TABLE_STRUCTURE_TAGS.has(tn); + } + /** @protected */ + _shouldFosterParentOnInsertion() { + return this.fosterParentingEnabled && this.openElements.currentTagId !== void 0 && this._isElementCausesFosterParenting(this.openElements.currentTagId); + } + /** @protected */ + _findFosterParentingLocation() { + for (let i = this.openElements.stackTop; i >= 0; i--) { + const openElement = this.openElements.items[i]; + switch (this.openElements.tagIDs[i]) { + case TAG_ID.TEMPLATE: { + if (this.treeAdapter.getNamespaceURI(openElement) === NS.HTML) { + return { parent: this.treeAdapter.getTemplateContent(openElement), beforeElement: null }; + } + break; + } + case TAG_ID.TABLE: { + const parent = this.treeAdapter.getParentNode(openElement); + if (parent) { + return { parent, beforeElement: openElement }; + } + return { parent: this.openElements.items[i - 1], beforeElement: null }; + } + default: + } + } + return { parent: this.openElements.items[0], beforeElement: null }; + } + /** @protected */ + _fosterParentElement(element) { + const location = this._findFosterParentingLocation(); + if (location.beforeElement) { + this.treeAdapter.insertBefore(location.parent, element, location.beforeElement); + } else { + this.treeAdapter.appendChild(location.parent, element); + } + } + //Special elements + /** @protected */ + _isSpecialElement(element, id) { + const ns = this.treeAdapter.getNamespaceURI(element); + return SPECIAL_ELEMENTS[ns].has(id); + } + /** @internal */ + onCharacter(token) { + this.skipNextNewLine = false; + if (this.tokenizer.inForeignNode) { + characterInForeignContent(this, token); + return; + } + switch (this.insertionMode) { + case InsertionMode.INITIAL: { + tokenInInitialMode(this, token); + break; + } + case InsertionMode.BEFORE_HTML: { + tokenBeforeHtml(this, token); + break; + } + case InsertionMode.BEFORE_HEAD: { + tokenBeforeHead(this, token); + break; + } + case InsertionMode.IN_HEAD: { + tokenInHead(this, token); + break; + } + case InsertionMode.IN_HEAD_NO_SCRIPT: { + tokenInHeadNoScript(this, token); + break; + } + case InsertionMode.AFTER_HEAD: { + tokenAfterHead(this, token); + break; + } + case InsertionMode.IN_BODY: + case InsertionMode.IN_CAPTION: + case InsertionMode.IN_CELL: + case InsertionMode.IN_TEMPLATE: { + characterInBody(this, token); + break; + } + case InsertionMode.TEXT: + case InsertionMode.IN_SELECT: + case InsertionMode.IN_SELECT_IN_TABLE: { + this._insertCharacters(token); + break; + } + case InsertionMode.IN_TABLE: + case InsertionMode.IN_TABLE_BODY: + case InsertionMode.IN_ROW: { + characterInTable(this, token); + break; + } + case InsertionMode.IN_TABLE_TEXT: { + characterInTableText(this, token); + break; + } + case InsertionMode.IN_COLUMN_GROUP: { + tokenInColumnGroup(this, token); + break; + } + case InsertionMode.AFTER_BODY: { + tokenAfterBody(this, token); + break; + } + case InsertionMode.AFTER_AFTER_BODY: { + tokenAfterAfterBody(this, token); + break; + } + default: + } + } + /** @internal */ + onNullCharacter(token) { + this.skipNextNewLine = false; + if (this.tokenizer.inForeignNode) { + nullCharacterInForeignContent(this, token); + return; + } + switch (this.insertionMode) { + case InsertionMode.INITIAL: { + tokenInInitialMode(this, token); + break; + } + case InsertionMode.BEFORE_HTML: { + tokenBeforeHtml(this, token); + break; + } + case InsertionMode.BEFORE_HEAD: { + tokenBeforeHead(this, token); + break; + } + case InsertionMode.IN_HEAD: { + tokenInHead(this, token); + break; + } + case InsertionMode.IN_HEAD_NO_SCRIPT: { + tokenInHeadNoScript(this, token); + break; + } + case InsertionMode.AFTER_HEAD: { + tokenAfterHead(this, token); + break; + } + case InsertionMode.TEXT: { + this._insertCharacters(token); + break; + } + case InsertionMode.IN_TABLE: + case InsertionMode.IN_TABLE_BODY: + case InsertionMode.IN_ROW: { + characterInTable(this, token); + break; + } + case InsertionMode.IN_COLUMN_GROUP: { + tokenInColumnGroup(this, token); + break; + } + case InsertionMode.AFTER_BODY: { + tokenAfterBody(this, token); + break; + } + case InsertionMode.AFTER_AFTER_BODY: { + tokenAfterAfterBody(this, token); + break; + } + default: + } + } + /** @internal */ + onComment(token) { + this.skipNextNewLine = false; + if (this.currentNotInHTML) { + appendComment(this, token); + return; + } + switch (this.insertionMode) { + case InsertionMode.INITIAL: + case InsertionMode.BEFORE_HTML: + case InsertionMode.BEFORE_HEAD: + case InsertionMode.IN_HEAD: + case InsertionMode.IN_HEAD_NO_SCRIPT: + case InsertionMode.AFTER_HEAD: + case InsertionMode.IN_BODY: + case InsertionMode.IN_TABLE: + case InsertionMode.IN_CAPTION: + case InsertionMode.IN_COLUMN_GROUP: + case InsertionMode.IN_TABLE_BODY: + case InsertionMode.IN_ROW: + case InsertionMode.IN_CELL: + case InsertionMode.IN_SELECT: + case InsertionMode.IN_SELECT_IN_TABLE: + case InsertionMode.IN_TEMPLATE: + case InsertionMode.IN_FRAMESET: + case InsertionMode.AFTER_FRAMESET: { + appendComment(this, token); + break; + } + case InsertionMode.IN_TABLE_TEXT: { + tokenInTableText(this, token); + break; + } + case InsertionMode.AFTER_BODY: { + appendCommentToRootHtmlElement(this, token); + break; + } + case InsertionMode.AFTER_AFTER_BODY: + case InsertionMode.AFTER_AFTER_FRAMESET: { + appendCommentToDocument(this, token); + break; + } + default: + } + } + /** @internal */ + onDoctype(token) { + this.skipNextNewLine = false; + switch (this.insertionMode) { + case InsertionMode.INITIAL: { + doctypeInInitialMode(this, token); + break; + } + case InsertionMode.BEFORE_HEAD: + case InsertionMode.IN_HEAD: + case InsertionMode.IN_HEAD_NO_SCRIPT: + case InsertionMode.AFTER_HEAD: { + this._err(token, ERR.misplacedDoctype); + break; + } + case InsertionMode.IN_TABLE_TEXT: { + tokenInTableText(this, token); + break; + } + default: + } + } + /** @internal */ + onStartTag(token) { + this.skipNextNewLine = false; + this.currentToken = token; + this._processStartTag(token); + if (token.selfClosing && !token.ackSelfClosing) { + this._err(token, ERR.nonVoidHtmlElementStartTagWithTrailingSolidus); + } + } + /** + * Processes a given start tag. + * + * `onStartTag` checks if a self-closing tag was recognized. When a token + * is moved inbetween multiple insertion modes, this check for self-closing + * could lead to false positives. To avoid this, `_processStartTag` is used + * for nested calls. + * + * @param token The token to process. + * @protected + */ + _processStartTag(token) { + if (this.shouldProcessStartTagTokenInForeignContent(token)) { + startTagInForeignContent(this, token); + } else { + this._startTagOutsideForeignContent(token); + } + } + /** @protected */ + _startTagOutsideForeignContent(token) { + switch (this.insertionMode) { + case InsertionMode.INITIAL: { + tokenInInitialMode(this, token); + break; + } + case InsertionMode.BEFORE_HTML: { + startTagBeforeHtml(this, token); + break; + } + case InsertionMode.BEFORE_HEAD: { + startTagBeforeHead(this, token); + break; + } + case InsertionMode.IN_HEAD: { + startTagInHead(this, token); + break; + } + case InsertionMode.IN_HEAD_NO_SCRIPT: { + startTagInHeadNoScript(this, token); + break; + } + case InsertionMode.AFTER_HEAD: { + startTagAfterHead(this, token); + break; + } + case InsertionMode.IN_BODY: { + startTagInBody(this, token); + break; + } + case InsertionMode.IN_TABLE: { + startTagInTable(this, token); + break; + } + case InsertionMode.IN_TABLE_TEXT: { + tokenInTableText(this, token); + break; + } + case InsertionMode.IN_CAPTION: { + startTagInCaption(this, token); + break; + } + case InsertionMode.IN_COLUMN_GROUP: { + startTagInColumnGroup(this, token); + break; + } + case InsertionMode.IN_TABLE_BODY: { + startTagInTableBody(this, token); + break; + } + case InsertionMode.IN_ROW: { + startTagInRow(this, token); + break; + } + case InsertionMode.IN_CELL: { + startTagInCell(this, token); + break; + } + case InsertionMode.IN_SELECT: { + startTagInSelect(this, token); + break; + } + case InsertionMode.IN_SELECT_IN_TABLE: { + startTagInSelectInTable(this, token); + break; + } + case InsertionMode.IN_TEMPLATE: { + startTagInTemplate(this, token); + break; + } + case InsertionMode.AFTER_BODY: { + startTagAfterBody(this, token); + break; + } + case InsertionMode.IN_FRAMESET: { + startTagInFrameset(this, token); + break; + } + case InsertionMode.AFTER_FRAMESET: { + startTagAfterFrameset(this, token); + break; + } + case InsertionMode.AFTER_AFTER_BODY: { + startTagAfterAfterBody(this, token); + break; + } + case InsertionMode.AFTER_AFTER_FRAMESET: { + startTagAfterAfterFrameset(this, token); + break; + } + default: + } + } + /** @internal */ + onEndTag(token) { + this.skipNextNewLine = false; + this.currentToken = token; + if (this.currentNotInHTML) { + endTagInForeignContent(this, token); + } else { + this._endTagOutsideForeignContent(token); + } + } + /** @protected */ + _endTagOutsideForeignContent(token) { + switch (this.insertionMode) { + case InsertionMode.INITIAL: { + tokenInInitialMode(this, token); + break; + } + case InsertionMode.BEFORE_HTML: { + endTagBeforeHtml(this, token); + break; + } + case InsertionMode.BEFORE_HEAD: { + endTagBeforeHead(this, token); + break; + } + case InsertionMode.IN_HEAD: { + endTagInHead(this, token); + break; + } + case InsertionMode.IN_HEAD_NO_SCRIPT: { + endTagInHeadNoScript(this, token); + break; + } + case InsertionMode.AFTER_HEAD: { + endTagAfterHead(this, token); + break; + } + case InsertionMode.IN_BODY: { + endTagInBody(this, token); + break; + } + case InsertionMode.TEXT: { + endTagInText(this, token); + break; + } + case InsertionMode.IN_TABLE: { + endTagInTable(this, token); + break; + } + case InsertionMode.IN_TABLE_TEXT: { + tokenInTableText(this, token); + break; + } + case InsertionMode.IN_CAPTION: { + endTagInCaption(this, token); + break; + } + case InsertionMode.IN_COLUMN_GROUP: { + endTagInColumnGroup(this, token); + break; + } + case InsertionMode.IN_TABLE_BODY: { + endTagInTableBody(this, token); + break; + } + case InsertionMode.IN_ROW: { + endTagInRow(this, token); + break; + } + case InsertionMode.IN_CELL: { + endTagInCell(this, token); + break; + } + case InsertionMode.IN_SELECT: { + endTagInSelect(this, token); + break; + } + case InsertionMode.IN_SELECT_IN_TABLE: { + endTagInSelectInTable(this, token); + break; + } + case InsertionMode.IN_TEMPLATE: { + endTagInTemplate(this, token); + break; + } + case InsertionMode.AFTER_BODY: { + endTagAfterBody(this, token); + break; + } + case InsertionMode.IN_FRAMESET: { + endTagInFrameset(this, token); + break; + } + case InsertionMode.AFTER_FRAMESET: { + endTagAfterFrameset(this, token); + break; + } + case InsertionMode.AFTER_AFTER_BODY: { + tokenAfterAfterBody(this, token); + break; + } + default: + } + } + /** @internal */ + onEof(token) { + switch (this.insertionMode) { + case InsertionMode.INITIAL: { + tokenInInitialMode(this, token); + break; + } + case InsertionMode.BEFORE_HTML: { + tokenBeforeHtml(this, token); + break; + } + case InsertionMode.BEFORE_HEAD: { + tokenBeforeHead(this, token); + break; + } + case InsertionMode.IN_HEAD: { + tokenInHead(this, token); + break; + } + case InsertionMode.IN_HEAD_NO_SCRIPT: { + tokenInHeadNoScript(this, token); + break; + } + case InsertionMode.AFTER_HEAD: { + tokenAfterHead(this, token); + break; + } + case InsertionMode.IN_BODY: + case InsertionMode.IN_TABLE: + case InsertionMode.IN_CAPTION: + case InsertionMode.IN_COLUMN_GROUP: + case InsertionMode.IN_TABLE_BODY: + case InsertionMode.IN_ROW: + case InsertionMode.IN_CELL: + case InsertionMode.IN_SELECT: + case InsertionMode.IN_SELECT_IN_TABLE: { + eofInBody(this, token); + break; + } + case InsertionMode.TEXT: { + eofInText(this, token); + break; + } + case InsertionMode.IN_TABLE_TEXT: { + tokenInTableText(this, token); + break; + } + case InsertionMode.IN_TEMPLATE: { + eofInTemplate(this, token); + break; + } + case InsertionMode.AFTER_BODY: + case InsertionMode.IN_FRAMESET: + case InsertionMode.AFTER_FRAMESET: + case InsertionMode.AFTER_AFTER_BODY: + case InsertionMode.AFTER_AFTER_FRAMESET: { + stopParsing(this, token); + break; + } + default: + } + } + /** @internal */ + onWhitespaceCharacter(token) { + if (this.skipNextNewLine) { + this.skipNextNewLine = false; + if (token.chars.charCodeAt(0) === CODE_POINTS.LINE_FEED) { + if (token.chars.length === 1) { + return; + } + token.chars = token.chars.substr(1); + } + } + if (this.tokenizer.inForeignNode) { + this._insertCharacters(token); + return; + } + switch (this.insertionMode) { + case InsertionMode.IN_HEAD: + case InsertionMode.IN_HEAD_NO_SCRIPT: + case InsertionMode.AFTER_HEAD: + case InsertionMode.TEXT: + case InsertionMode.IN_COLUMN_GROUP: + case InsertionMode.IN_SELECT: + case InsertionMode.IN_SELECT_IN_TABLE: + case InsertionMode.IN_FRAMESET: + case InsertionMode.AFTER_FRAMESET: { + this._insertCharacters(token); + break; + } + case InsertionMode.IN_BODY: + case InsertionMode.IN_CAPTION: + case InsertionMode.IN_CELL: + case InsertionMode.IN_TEMPLATE: + case InsertionMode.AFTER_BODY: + case InsertionMode.AFTER_AFTER_BODY: + case InsertionMode.AFTER_AFTER_FRAMESET: { + whitespaceCharacterInBody(this, token); + break; + } + case InsertionMode.IN_TABLE: + case InsertionMode.IN_TABLE_BODY: + case InsertionMode.IN_ROW: { + characterInTable(this, token); + break; + } + case InsertionMode.IN_TABLE_TEXT: { + whitespaceCharacterInTableText(this, token); + break; + } + default: + } + } + }; + TABLE_VOID_ELEMENTS = /* @__PURE__ */ new Set([TAG_ID.CAPTION, TAG_ID.COL, TAG_ID.COLGROUP, TAG_ID.TBODY, TAG_ID.TD, TAG_ID.TFOOT, TAG_ID.TH, TAG_ID.THEAD, TAG_ID.TR]); + } +}); + +// node_modules/entities/dist/esm/escape.js +function getEscaper(regex, map) { + return function escape(data) { + let match; + let lastIndex = 0; + let result = ""; + while (match = regex.exec(data)) { + if (lastIndex !== match.index) { + result += data.substring(lastIndex, match.index); + } + result += map.get(match[0].charCodeAt(0)); + lastIndex = match.index + 1; + } + return result + data.substring(lastIndex); + }; +} +var getCodePoint, escapeAttribute, escapeText3; +var init_escape = __esm({ + "node_modules/entities/dist/esm/escape.js"() { + getCodePoint = // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + String.prototype.codePointAt == null ? (c, index2) => (c.charCodeAt(index2) & 64512) === 55296 ? (c.charCodeAt(index2) - 55296) * 1024 + c.charCodeAt(index2 + 1) - 56320 + 65536 : c.charCodeAt(index2) : ( + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + (input, index2) => input.codePointAt(index2) + ); + escapeAttribute = /* @__PURE__ */ getEscaper(/["&\u00A0]/g, /* @__PURE__ */ new Map([ + [34, """], + [38, "&"], + [160, " "] + ])); + escapeText3 = /* @__PURE__ */ getEscaper(/[&<>\u00A0]/g, /* @__PURE__ */ new Map([ + [38, "&"], + [60, "<"], + [62, ">"], + [160, " "] + ])); + } +}); + +// node_modules/parse5/dist/serializer/index.js +function isVoidElement(node, options) { + return options.treeAdapter.isElementNode(node) && options.treeAdapter.getNamespaceURI(node) === NS.HTML && VOID_ELEMENTS.has(options.treeAdapter.getTagName(node)); +} +function serializeOuter(node, options) { + const opts = { ...defaultOpts, ...options }; + return serializeNode(node, opts); +} +function serializeChildNodes(parentNode, options) { + let html = ""; + const container = options.treeAdapter.isElementNode(parentNode) && options.treeAdapter.getTagName(parentNode) === TAG_NAMES.TEMPLATE && options.treeAdapter.getNamespaceURI(parentNode) === NS.HTML ? options.treeAdapter.getTemplateContent(parentNode) : parentNode; + const childNodes = options.treeAdapter.getChildNodes(container); + if (childNodes) { + for (const currentNode of childNodes) { + html += serializeNode(currentNode, options); + } + } + return html; +} +function serializeNode(node, options) { + if (options.treeAdapter.isElementNode(node)) { + return serializeElement(node, options); + } + if (options.treeAdapter.isTextNode(node)) { + return serializeTextNode(node, options); + } + if (options.treeAdapter.isCommentNode(node)) { + return serializeCommentNode(node, options); + } + if (options.treeAdapter.isDocumentTypeNode(node)) { + return serializeDocumentTypeNode(node, options); + } + return ""; +} +function serializeElement(node, options) { + const tn = options.treeAdapter.getTagName(node); + return `<${tn}${serializeAttributes(node, options)}>${isVoidElement(node, options) ? "" : `${serializeChildNodes(node, options)}`}`; +} +function serializeAttributes(node, { treeAdapter }) { + let html = ""; + for (const attr of treeAdapter.getAttrList(node)) { + html += " "; + if (attr.namespace) { + switch (attr.namespace) { + case NS.XML: { + html += `xml:${attr.name}`; + break; + } + case NS.XMLNS: { + if (attr.name !== "xmlns") { + html += "xmlns:"; + } + html += attr.name; + break; + } + case NS.XLINK: { + html += `xlink:${attr.name}`; + break; + } + default: { + html += `${attr.prefix}:${attr.name}`; + } + } + } else { + html += attr.name; + } + html += `="${escapeAttribute(attr.value)}"`; + } + return html; +} +function serializeTextNode(node, options) { + const { treeAdapter } = options; + const content = treeAdapter.getTextNodeContent(node); + const parent = treeAdapter.getParentNode(node); + const parentTn = parent && treeAdapter.isElementNode(parent) && treeAdapter.getTagName(parent); + return parentTn && treeAdapter.getNamespaceURI(parent) === NS.HTML && hasUnescapedText(parentTn, options.scriptingEnabled) ? content : escapeText3(content); +} +function serializeCommentNode(node, { treeAdapter }) { + return ``; +} +function serializeDocumentTypeNode(node, { treeAdapter }) { + return ``; +} +var VOID_ELEMENTS, defaultOpts; +var init_serializer = __esm({ + "node_modules/parse5/dist/serializer/index.js"() { + init_html(); + init_escape(); + init_default(); + VOID_ELEMENTS = /* @__PURE__ */ new Set([ + TAG_NAMES.AREA, + TAG_NAMES.BASE, + TAG_NAMES.BASEFONT, + TAG_NAMES.BGSOUND, + TAG_NAMES.BR, + TAG_NAMES.COL, + TAG_NAMES.EMBED, + TAG_NAMES.FRAME, + TAG_NAMES.HR, + TAG_NAMES.IMG, + TAG_NAMES.INPUT, + TAG_NAMES.KEYGEN, + TAG_NAMES.LINK, + TAG_NAMES.META, + TAG_NAMES.PARAM, + TAG_NAMES.SOURCE, + TAG_NAMES.TRACK, + TAG_NAMES.WBR + ]); + defaultOpts = { treeAdapter: defaultTreeAdapter, scriptingEnabled: true }; + } +}); + +// node_modules/parse5/dist/index.js +function parseFragment(fragmentContext, html, options) { + if (typeof fragmentContext === "string") { + options = html; + html = fragmentContext; + fragmentContext = null; + } + const parser = Parser.getFragmentParser(fragmentContext, options); + parser.tokenizer.write(html, true); + return parser.getFragment(); +} +var init_dist = __esm({ + "node_modules/parse5/dist/index.js"() { + init_parser(); + init_default(); + init_parser(); + init_serializer(); + init_error_codes(); + init_foreign_content(); + init_html(); + init_token(); + init_tokenizer(); + } +}); + +// node_modules/@markup-carve/carve/dist/html-import.js +function isFlattenedBlock(node) { + const tag = node.tagName; + if (!tag) + return false; + return BLOCK.has(tag) || FLATTENED_BLOCK_EXTRA.has(tag); +} +function needsSeparator(before, after) { + const last = before.at(-1); + const first = after[0]; + if (last === void 0 || first === void 0) + return false; + if (last.type === "hard_break" || first.type === "hard_break") + return false; + if (last.type === "text" && /\s$/.test(last.value)) + return false; + if (first.type === "text" && /^\s/.test(first.value)) + return false; + return true; +} +function launderableScheme(value) { + for (const token of value.split(/[\s,]+/).slice(1)) { + const colon = token.indexOf(":"); + if (colon === -1) + continue; + const scheme = token.slice(0, colon).replace(SCHEME_PROBE_STRIP_RE, "").toLowerCase(); + if (DENIED_SCHEMES.has(scheme)) + return scheme; + } + return void 0; +} +function htmlToAst(html, options = {}) { + const importer = new Importer(options); + const value = importer.import(html); + return { value, report: { mode: importer.mode, adapter: importer.adapter, diagnostics: importer.diagnostics } }; +} +function htmlToCarve(html, options = {}) { + const importer = new Importer(options); + const value = importer.import(html); + importer.reportSerializationLosses(); + return { value: renderCarve(value), report: { mode: importer.mode, adapter: importer.adapter, diagnostics: importer.diagnostics } }; +} +var HtmlImportLimitError, ACTIVE, BLOCK, FLATTENED_BLOCK_EXTRA, ADAPTERS, FOOTNOTE_SHAPED_ADAPTERS, FOOTNOTE_DEFINITION_BLOCKS, FOOTNOTE_WRAPPER_BLOCKS, RE_DOWNLEVEL_CONDITIONAL, SEMANTIC_SPAN_TAGS, SEMANTIC_SPAN_VALUE_SOURCE, TEX_ANNOTATION_ENCODINGS, ROUND_TRIP_MARKER_ATTRIBUTES, DENIED_SCHEMES, Importer; +var init_html_import = __esm({ + "node_modules/@markup-carve/carve/dist/html-import.js"() { + init_dist(); + init_render_carve(); + init_render_html(); + init_own_property(); + HtmlImportLimitError = class extends Error { + limit; + constructor(limit) { + super(`HTML import ${limit} limit exceeded`); + this.limit = limit; + this.name = "HtmlImportLimitError"; + } + }; + ACTIVE = /* @__PURE__ */ new Set(["script", "style", "template", "noscript"]); + BLOCK = /* @__PURE__ */ new Set([ + "address", + "article", + "aside", + "blockquote", + "details", + "div", + "dl", + "fieldset", + "figure", + "footer", + "form", + "header", + "hgroup", + "main", + "nav", + "ol", + "p", + "pre", + "section", + "table", + "ul", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "hr" + ]); + FLATTENED_BLOCK_EXTRA = /* @__PURE__ */ new Set(["li", "dt", "dd", "td", "th", "tr", "caption", "figcaption"]); + ADAPTERS = /* @__PURE__ */ new Set([ + "generic", + "tiptap", + "prosemirror", + "ckeditor", + "tinymce", + "word", + "google-docs" + ]); + FOOTNOTE_SHAPED_ADAPTERS = /* @__PURE__ */ new Set(["word", "google-docs"]); + FOOTNOTE_DEFINITION_BLOCKS = /* @__PURE__ */ new Set(["li", "div", "section", "aside", "p", "td", "blockquote"]); + FOOTNOTE_WRAPPER_BLOCKS = /* @__PURE__ */ new Set(["div", "li", "section", "aside"]); + RE_DOWNLEVEL_CONDITIONAL = /^(|)+$/i; + SEMANTIC_SPAN_TAGS = /* @__PURE__ */ new Set(["abbr", "time", "samp", "var", "kbd", "cite", "dfn"]); + SEMANTIC_SPAN_VALUE_SOURCE = /* @__PURE__ */ new Map([["abbr", "title"], ["dfn", "title"], ["time", "datetime"]]); + TEX_ANNOTATION_ENCODINGS = /* @__PURE__ */ new Set(["application/x-tex", "text/x-tex", "latex"]); + ROUND_TRIP_MARKER_ATTRIBUTES = /* @__PURE__ */ new Set(["data-djot-src", "data-carve-src"]); + DENIED_SCHEMES = new Set(DANGEROUS_URL_SCHEMES.map((scheme) => scheme.toLowerCase())); + Importer = class { + mode; + adapter; + diagnostics = []; + /** Where the import built a structure only a serializer loses (§16). */ + unspellable = []; + nodes = 0; + /** How many `` elements enclose the one being read, for the mark pair. */ + quoteDepth = 0; + maxDepth; + maxNodes; + maxDiagnostics; + constructor(options) { + this.mode = options.mode ?? "safe"; + this.adapter = options.adapter ?? "generic"; + if (!ADAPTERS.has(this.adapter)) + throw new TypeError(`Unknown HTML import adapter: ${this.adapter}`); + this.maxDepth = options.maxDepth ?? 128; + this.maxNodes = options.maxNodes ?? 1e6; + this.maxDiagnostics = options.maxDiagnostics ?? 1e3; + } + import(html) { + const fragment = parseFragment(html, { sourceCodeLocationInfo: true }); + const footnoteDefs = this.adapterFootnotes(fragment, FOOTNOTE_SHAPED_ADAPTERS.has(this.adapter)); + const children = this.blocks(fragment.childNodes ?? [], "", 0); + const doc = { type: "document", children }; + if (footnoteDefs && Object.keys(footnoteDefs).length > 0) + doc.footnoteDefs = footnoteDefs; + return doc; + } + enter(depth) { + if (depth > this.maxDepth) + throw new HtmlImportLimitError("depth"); + if (++this.nodes > this.maxNodes) + throw new HtmlImportLimitError("nodes"); + } + add(code, message, severity, path8) { + if (this.diagnostics.length >= this.maxDiagnostics) + throw new HtmlImportLimitError("diagnostics"); + this.diagnostics.push({ code, message, severity, path: path8 }); + } + /** + * An element's attributes, as the Carve attributes that carry them. + * + * THE POLICY IS A REFUSAL LIST, NOT A KEEP LIST. An attribute is dropped only + * where there is a reason to drop it - it is an injection sink (§25), it is + * CSS the language has no slot for, or its name is not spellable as a Carve + * attribute identifier. Everything else is kept, because Carve's attribute + * syntax can hold it and dropping what fits is a silent loss applied in bulk + * to exactly the documents an importer runs on: `aria-label` on an imported + * quote is an accessibility regression the format never required + * (markup-carve/carve-js#1156, matching carve-php). + * + * The refusal is DERIVED, not enumerated: `isDangerousAttrName` is the + * renderer's own §25 name filter, so the importer cannot admit a sink the + * renderer knows to strip, and `isAttrIdentifier` is the Carve writer's own + * name rule, so the importer cannot keep a name the writer would rewrite into + * a different one. + */ + attrs(node, path8) { + const attrs = {}; + const classes = []; + const keyValues = {}; + for (const attr of node.attrs ?? []) { + const name = attr.name.toLowerCase(); + if (isDangerousAttrName(name)) { + const kind2 = name.startsWith("on") ? "event-handler" : "injection-sink"; + this.add("attribute-dropped", `Dropped ${kind2} attribute ${name} on <${node.tagName}>`, "warning", path8); + } else if (name === "style") { + this.styles(attr.value, keyValues, path8); + } else if (name === "id") { + attrs.id = attr.value; + } else if (name === "class") { + classes.push(...attr.value.split(/\s+/).filter(Boolean)); + } else if (ROUND_TRIP_MARKER_ATTRIBUTES.has(name)) { + this.add("attribute-dropped", `Dropped round-trip marker ${name} on <${node.tagName}>`, "info", path8); + } else if (this.isConsumedHtmlAttribute(node.tagName ?? "", name)) { + } else if (!isAttrIdentifier(name)) { + this.add("attribute-dropped", `Dropped unsupported attribute ${name} on <${node.tagName}>: not spellable as a Carve attribute name`, "info", path8); + } else if (/[\r\n]/.test(attr.value)) { + this.add("attribute-dropped", `Dropped ${name} on <${node.tagName}>: its value spans a line break, which a Carve attribute value cannot`, "warning", path8); + } else { + if (hasOwnKey(keyValues, name)) { + this.add("attribute-dropped", `Dropped ${name} on <${node.tagName}>: a mapped CSS declaration already sets it`, "info", path8); + } else { + const laundered = launderableScheme(attr.value); + if (laundered !== void 0) { + this.add("attribute-dropped", `Dropped ${name} on <${node.tagName}>: its value carries a ${laundered} URL the renderer does not reach`, "warning", path8); + } else { + setOwn(keyValues, name, attr.value); + } + } + } + } + if (classes.length) + attrs.classes = classes; + if (Object.keys(keyValues).length) + attrs.keyValues = keyValues; + return attrs.id || attrs.classes || attrs.keyValues ? attrs : void 0; + } + /** + * Whether the importer already READ this attribute somewhere else - as the + * node's own content, or as an instruction about what node to build. + * + * These are neither kept by `attrs()` nor reported: a `` reaches the + * link's destination and a `` reaches the cell's span, so keeping + * the name as well would give one source two spellings, and reporting it + * would name a loss that does not happen. + */ + isConsumedHtmlAttribute(tag, name) { + if (tag === "a") + return name === "href" || name === "title"; + if (tag === "img") + return name === "src" || name === "alt" || name === "title"; + if (tag === "ol") + return name === "start" || name === "type"; + if (tag === "input") + return name === "type" || name === "checked"; + if (tag === "td" || tag === "th") + return name === "colspan" || name === "rowspan"; + if (tag === "time") + return name === "datetime"; + if (tag === "math") + return name === "alttext" || name === "display" || name === "xmlns"; + return false; + } + styles(value, keyValues, path8) { + for (const declaration of value.split(";")) { + const split = declaration.indexOf(":"); + if (split < 0) + continue; + const property = declaration.slice(0, split).trim().toLowerCase(); + const val = declaration.slice(split + 1).trim().toLowerCase(); + if (!property) + continue; + if (this.mode !== "safe" && property === "text-align" && ["left", "right", "center"].includes(val)) { + keyValues.align = val; + } else { + this.add("style-unmapped", `CSS declaration ${property} was not mapped`, "info", path8); + } + } + } + attr(node, name) { + return node.attrs?.find((a) => a.name.toLowerCase() === name)?.value; + } + childPath(parent, node, index2) { + const name = node.tagName ?? (node.nodeName === "#text" ? "text()" : node.nodeName); + return `${parent}/${name}[${index2 + 1}]`; + } + /** + * `paths` overrides the path a node is reported under, index-parallel to + * `nodes`. One caller needs it: a `

    ` collects the children that are + * neither a term nor a definition and converts them AFTER the list, and + * rebuilding their paths from the filtered array would renumber them - a + * `

    ` reported as `/dl[1]/p[3]` on its way out would report its own + * attribute losses under `/dl[1]/p[1]`, so one element spoke under two names. + */ + blocks(nodes, parentPath, depth, paths) { + const out = []; + let inlineBuffer = []; + const flush = () => { + const children = this.inlines(inlineBuffer, parentPath, depth + 1); + inlineBuffer = []; + if (this.visible(children)) + out.push({ type: "paragraph", children }); + }; + nodes.forEach((node, index2) => { + const path8 = paths?.[index2] ?? this.childPath(parentPath, node, index2); + if (node.nodeName === "#text" && !(node.value ?? "").trim()) { + if (inlineBuffer.length) + inlineBuffer.push(node); + return; + } + if (!node.tagName || !BLOCK.has(node.tagName)) { + inlineBuffer.push(node); + return; + } + flush(); + out.push(...this.block(node, path8, depth + 1)); + }); + flush(); + return out; + } + block(node, path8, depth) { + this.enter(depth); + const tag = node.tagName; + if (ACTIVE.has(tag)) { + this.add("element-dropped", `Dropped active <${tag}> element`, "warning", path8); + return []; + } + const attrs = this.attrs(node, path8); + if (/^h[1-6]$/.test(tag)) + return [{ type: "heading", level: Number(tag[1]), children: this.inlines(node.childNodes ?? [], path8, depth + 1), ...attrs ? { attrs } : {} }]; + if (tag === "p") + return [{ type: "paragraph", children: this.inlines(node.childNodes ?? [], path8, depth + 1), ...attrs ? { attrs } : {} }]; + if (tag === "blockquote") + return [{ type: "block_quote", children: this.blocks(node.childNodes ?? [], path8, depth + 1), ...attrs ? { attrs } : {} }]; + if (tag === "ul" || tag === "ol") + return [this.list(node, path8, depth, tag === "ol", attrs)]; + if (tag === "dl") + return this.definitionList(node, path8, depth, attrs); + if (tag === "pre") { + const code = node.childNodes?.find((n) => n.tagName === "code"); + const source = code ?? node; + const className = this.attr(source, "class") ?? ""; + const lang = className.split(/\s+/).find((c) => c.startsWith("language-"))?.slice(9); + return [{ type: "code_block", content: this.text(source), ...lang ? { lang } : {}, ...attrs ? { attrs } : {} }]; + } + if (tag === "hr") + return [{ type: "thematic_break", ...attrs ? { attrs } : {} }]; + if (tag === "table") + return [this.table(node, path8, depth, attrs)]; + if (tag === "figure") + return this.figure(node, path8, depth, attrs); + if (tag === "details") + return [this.disclosure(node, path8, depth, attrs)]; + if (tag === "div" || ["article", "aside", "footer", "header", "main", "nav", "section"].includes(tag)) { + if (tag !== "div") { + this.add("element-unwrapped", `Unwrapped unsupported <${tag}> element`, "info", path8); + this.reportUnwrappedAttributes(attrs, tag, path8); + } + const children = this.blocks(node.childNodes ?? [], path8, depth + 1); + return tag === "div" && attrs ? [{ type: "div", children, attrs }] : children; + } + if (this.mode === "roundtrip") { + this.add("raw-preserved", `Preserved unsupported <${tag}> element as raw HTML`, "warning", path8); + return [{ type: "raw_block", format: "html", content: serializeOuter(node) }]; + } + this.add("element-unwrapped", `Unwrapped unsupported <${tag}> element`, "info", path8); + this.reportUnwrappedAttributes(attrs, tag, path8); + return this.blocks(node.childNodes ?? [], path8, depth + 1); + } + list(node, path8, depth, ordered, attrs) { + const listItems = (node.childNodes ?? []).filter((n) => n.tagName === "li"); + const items = listItems.map((li, i) => { + const liPath = `${path8}/li[${i + 1}]`; + const input = li.childNodes?.find((n) => n.tagName === "input" && this.attr(n, "type") === "checkbox"); + const liAttrs = this.attrs(li, liPath); + return { + type: "list_item", + ...input ? { checked: this.attr(input, "checked") !== void 0 } : {}, + children: this.blocks((li.childNodes ?? []).filter((n) => n !== input), liPath, depth + 1), + ...liAttrs ? { attrs: liAttrs } : {} + }; + }); + const tight = !listItems.some((li) => (li.childNodes ?? []).some((child) => child.tagName === "p")); + const start = this.listStart(node, path8, ordered); + return { type: "list", ordered, tight, items, ...start !== void 0 && start !== 1 ? { start } : {}, ...this.olType(node, path8, ordered, items.length, start ?? 1), ...attrs ? { attrs } : {} }; + } + /** + * `

    ` -> `definition_list` (PART 9 §4.5). + * + * Without this branch the tag fell through to the unwrap arm, and `dt`/`dd` + * are not block tags, so every term and every definition landed in the SAME + * inline buffer: `
    Term
    Definition
    ` imported as the single + * paragraph `TermDefinition`. Not a degraded list - no list at all, and not + * even a space between the two texts. + * + * A run of `
    ` opens an entry and the `
    ` run after it belongs to that + * entry, so `
    a
    b
    c` is one entry with two terms, exactly the shape + * `:: a` / `:: b` / `: c` parses to. The HTML5 `
    ` wrapper (allowed + * around a name-value group since HTML 5.2, and what several editors emit) + * carries no meaning of its own and is walked through transparently. + * + * Anything else directly inside the `
    ` has no slot in the model. It is + * kept, as blocks AFTER the list rather than dropped, and reported: moving it + * changes the document order, which is a smaller loss than deleting it. + * + * Three shapes are valid HTML that Carve SOURCE cannot spell, so they are + * built into the AST and reported by whoever writes (§16): a `
    ` with no + * `
    ` before it, an EMPTY `
    ` and an EMPTY `
    `. Each one writes a + * line the parser reads as something else, and the tests assert what it + * reads as rather than only that a diagnostic appeared. + * + * `block()` has already counted this node against `maxNodes`, so this walk + * counts only the elements it visits itself. + */ + definitionList(node, path8, depth, attrs) { + const items = []; + const trailing = []; + const trailingPaths = []; + let current; + const openEntry = () => { + const entry = { terms: [], definitions: [] }; + items.push(entry); + return entry; + }; + const visit4 = (children, parentPath, level) => { + children.forEach((child, index2) => { + const childPath = this.childPath(parentPath, child, index2); + if (child.nodeName === "#text" && !(child.value ?? "").trim()) + return; + if (child.tagName === "div") { + this.enter(level); + this.entryAttributes(child, childPath, "div"); + current = void 0; + visit4(child.childNodes ?? [], childPath, level + 1); + current = void 0; + return; + } + if (child.tagName === "dt") { + this.enter(level); + if (current === void 0 || current.definitions.length > 0) + current = openEntry(); + this.entryAttributes(child, childPath, "dt"); + const term = this.inlines(child.childNodes ?? [], childPath, level + 1); + if (!this.visible(term)) { + this.unspellable.push({ + path: childPath, + message: "An empty
    has no Carve spelling; the bare `::` line re-reads as a paragraph" + }); + } + current.terms.push(term); + return; + } + if (child.tagName === "dd") { + this.enter(level); + if (current === void 0) { + current = openEntry(); + this.unspellable.push({ + path: childPath, + message: "A
    with no
    before it has no Carve spelling; the definition line re-reads as a paragraph" + }); + } + this.entryAttributes(child, childPath, "dd"); + const definition = this.blocks(child.childNodes ?? [], childPath, level + 1); + if (this.writesNothing(definition)) { + this.unspellable.push({ + path: childPath, + message: "A
    that writes nothing has no Carve spelling; the bare `:` line is read as more of the term above it" + }); + } + current.definitions.push(definition); + return; + } + this.add("element-unwrapped", `Moved <${child.tagName ?? child.nodeName}> content out of the
    : only
    and
    have a place in a definition list`, "warning", childPath); + trailing.push(child); + trailingPaths.push(childPath); + }); + }; + visit4(node.childNodes ?? [], path8, depth + 1); + const list = { type: "definition_list", items, ...attrs ? { attrs } : {} }; + return [...items.length ? [list] : [], ...this.blocks(trailing, path8, depth + 1, trailingPaths)]; + } + /** + * A `
    `, `
    ` or group `
    ` carries attributes and the model has + * nowhere to put them: PART 12 gives `definition_list` an `attrs` slot and + * its ENTRIES none, so an `id` an anchor points at, a class a stylesheet + * selects on and a `data-` pair an editor round-trips all end here. An + * ordinary `
    ` keeps its attributes by becoming a `div` node; the wrapper + * inside a `
    ` cannot, because it is walked through. + * + * `attrs()` is still called for its diagnostics: it is where an event-handler + * attribute is reported, and skipping the call made these three the only + * places in the importer where active markup was dropped in silence. + */ + entryAttributes(node, path8, tag, noun) { + const attrs = this.attrs(node, path8); + if (attrs === void 0) + return; + const slot = noun ?? `a definition ${tag === "dt" ? "term" : tag === "dd" ? "description" : "group"}`; + this.add("attribute-dropped", `Dropped ${this.attrNames(attrs).join(", ")} on <${tag}>: ${slot} has no attribute slot`, "warning", path8); + } + attrNames(attrs) { + return [ + ...attrs.id ? ["id"] : [], + ...attrs.classes ? ["class"] : [], + ...Object.keys(attrs.keyValues ?? {}) + ]; + } + /** + * The attributes an UNWRAPPED element takes with it. + * + * `attrs()` reports the ones it cannot represent, and keeps the rest - an id + * an anchor points at, a class a stylesheet selects on, a `data-` pair an + * editor round-trips. When the element itself is then unwrapped there is + * nothing left to hang them on, and they went in silence: a + * `
    `); + } + return parts.join("\n"); +} +function withBaseClass(attrs, base) { + const a = attrs ? { ...attrs } : {}; + a.classes = [base, ...a.classes ?? []]; + return a; +} +function renderDef(def, ctx) { + if (def.length === 1 && def[0].type === "paragraph") + return ctx.renderInlines(def[0].children); + return ` +${ctx.renderChildren(def, ctx.level + 2)} +${ctx.indent(ctx.level + 1)}`; +} +function walkBlocks2(node, fn) { + if (!node || typeof node !== "object") + return; + if (typeof node.type === "string") + fn(node); + for (const key2 of Object.keys(node)) { + if (key2 === "pos") + continue; + const v = node[key2]; + if (Array.isArray(v)) + for (const el of v) + walkBlocks2(el, fn); + else if (v && typeof v === "object") + walkBlocks2(v, fn); + } +} +var termSlug; +var init_glossary = __esm({ + "node_modules/@markup-carve/carve/dist/glossary.js"() { + init_heading_ids(); + termSlug = (term) => slugify(inlineText(term), { lowercase: true }); + } +}); + +// node_modules/@markup-carve/carve/dist/heading-numbers.js +function headingNumbers(opts = {}) { + const minLevel = opts.minLevel ?? 1; + const label = opts.label ?? "Section"; + const crossref = opts.crossref ?? "number-title"; + const processed = /* @__PURE__ */ new WeakSet(); + return { + name: "headingNumbers", + beforeRender(doc) { + if (processed.has(doc)) + return doc; + processed.add(doc); + const levels = []; + const numbers = []; + const byId = /* @__PURE__ */ new Map(); + const seenIds = /* @__PURE__ */ new Set(); + walkHeadings(doc.children, false, (h, inBlockquote) => { + const id = h.attrs?.id; + const taken = id !== void 0 && seenIds.has(id); + if (id !== void 0) + seenIds.add(id); + if (inBlockquote || hasClass2(h, "unnumbered") || h.level < minLevel) + return; + const lvl = h.level; + while (levels.length && levels[levels.length - 1] > lvl) { + levels.pop(); + numbers.pop(); + } + if (levels.length && levels[levels.length - 1] === lvl) + numbers[numbers.length - 1]++; + else { + levels.push(lvl); + numbers.push(1); + } + const number = numbers.join("."); + const title = deepCloneInlines(h.children); + if (id !== void 0 && !taken) + byId.set(id, { number, title }); + const span2 = { + type: "span", + attrs: { classes: ["section-number"] }, + children: [{ type: "text", value: number }] + }; + h.children = [span2, { type: "text", value: " " }, ...h.children]; + }); + if (crossref !== "title") + walkCrossrefs(doc, (ref) => { + if (!ref.href?.startsWith("#")) + return; + const entry = byId.get(ref.href.slice(1)); + if (!entry) + return; + const prefix = crossref === "number" ? `${label} ${entry.number}` : `${label} ${entry.number} - `; + ref.resolvedText = crossref === "number" ? [{ type: "text", value: prefix }] : [ + { type: "text", value: prefix }, + ...deriveDisplayNodes(entry.title, true) + ]; + }); + return doc; + } + }; +} +function hasClass2(h, cls) { + return !!h.attrs?.classes?.includes(cls); +} +function walkHeadings(nodes, inBlockquote, fn) { + const descend2 = (kids, bq) => { + if (Array.isArray(kids)) + walkHeadings(kids, bq, fn); + }; + for (const b of nodes) { + switch (b.type) { + case "heading": + fn(b, inBlockquote); + break; + case "block_quote": + descend2(b.children, true); + break; + case "list": { + for (const item2 of b.items ?? []) + descend2(item2.children, inBlockquote); + break; + } + case "div": + case "admonition": + case "figure_group": + descend2(b.children, inBlockquote); + break; + case "definition_list": { + for (const item2 of b.items ?? []) + for (const def of item2.definitions ?? []) + descend2(def, inBlockquote); + break; + } + case "figure": { + const target = b.target; + if (target?.type === "block_quote") + descend2(target.children, true); + break; + } + } + } +} +function walkCrossrefs(node, fn) { + if (!node || typeof node !== "object") + return; + if (node.type === "heading_ref") + fn(node); + for (const key2 of Object.keys(node)) { + if (key2 === "pos") + continue; + const v = node[key2]; + if (Array.isArray(v)) + for (const el of v) + walkCrossrefs(el, fn); + else if (v && typeof v === "object") + walkCrossrefs(v, fn); + } +} +var init_heading_numbers = __esm({ + "node_modules/@markup-carve/carve/dist/heading-numbers.js"() { + init_heading_ids(); + } +}); + +// node_modules/@markup-carve/carve/dist/code-callouts.js +function codeCallouts() { + const calloutLists = /* @__PURE__ */ new WeakSet(); + return { + name: "codeCallouts", + afterParse(doc) { + bindBlocks(doc.children, calloutLists); + return doc; + }, + blockRenderers: { + "code_block": (node, ctx) => renderCode3(node, ctx), + paragraph: (node, ctx) => calloutLists.has(node) ? renderCalloutList(node, ctx) : void 0 + } + }; +} +function bindBlocks(blocks, calloutLists) { + for (let i = 0; i < blocks.length; i++) { + const b = blocks[i]; + descend(b, calloutLists); + if (b.type !== "code_block" || !hasMarkers(b.content)) + continue; + const next = blocks[i + 1]; + if (next && next.type === "paragraph" && isCalloutCandidate(next)) { + calloutLists.add(next); + } + } +} +function descend(b, calloutLists) { + const anyB = b; + if (Array.isArray(anyB.children)) + bindBlocks(anyB.children, calloutLists); + if (Array.isArray(anyB.items)) + for (const it of anyB.items) { + if (Array.isArray(it.children)) + bindBlocks(it.children, calloutLists); + if (Array.isArray(it.definitions)) + for (const def of it.definitions) + bindBlocks(def, calloutLists); + } +} +function hasMarkers(content) { + return content.split("\n").some((l) => MARKER_RE.test(l)); +} +function isCalloutCandidate(p) { + const lines = splitLines(p.children); + return lines.length > 0 && lines.every((line2) => firstText(line2)?.match(ITEM_RE2) != null); +} +function renderCode3(node, ctx) { + const lines = node.content.split("\n"); + if (!lines.some((l) => MARKER_RE.test(l))) + return void 0; + const pad = ctx.indent(ctx.level); + const langAttr = node.lang ? ` class="language-${node.lang}"` : ""; + const body = lines.map((line2) => { + const m = MARKER_RE.exec(line2); + if (!m) + return ctx.escapeHtml(line2); + const [, prefix, ws, n] = m; + return `${ctx.escapeHtml(prefix)}${ws}${n}`; + }).join("\n"); + return `${pad}${body} +`; +} +function renderCalloutList(p, ctx) { + const pad = ctx.indent(ctx.level); + const inner = ctx.indent(ctx.level + 1); + const items = splitLines(p.children).map((line2) => { + const head = firstText(line2); + const n = ITEM_RE2.exec(head)[1]; + const rest = [ + { type: "text", value: head.replace(ITEM_RE2, "") }, + ...line2.slice(1) + ]; + return `${inner}
  • ${ctx.renderInlines(rest)}
  • `; + }); + return `${pad} +${items.join("\n")} +${pad}`; +} +function listAttrs(attrs) { + const a = attrs ? { ...attrs } : {}; + a.classes = ["callouts", ...a.classes ?? []]; + return a; +} +function splitLines(nodes) { + const lines = [[]]; + for (const n of nodes) { + if (n.type === "soft_break") + lines.push([]); + else + lines[lines.length - 1].push(n); + } + return lines.filter((l) => l.length > 0); +} +function firstText(line2) { + const first = line2[0]; + return first?.type === "text" ? first.value : void 0; +} +var MARKER_RE, ITEM_RE2; +var init_code_callouts = __esm({ + "node_modules/@markup-carve/carve/dist/code-callouts.js"() { + MARKER_RE = /^(.*?)(\s*)<(\d+)>[ \t]*$/; + ITEM_RE2 = /^<(\d+)> /; + } +}); + +// node_modules/@markup-carve/carve/dist/smart-quotes.js +function smartQuoteLocales() { + return Object.keys(SMART_QUOTE_LOCALES); +} +function isSmartQuoteLocaleSupported(locale) { + return localeKeys(locale).some((key2) => key2 in SMART_QUOTE_LOCALES); +} +function smartQuotes(options = {}) { + const resolved = resolveLocale(options.locale ?? "en"); + const quotes = [ + options.openDoubleQuote ?? resolved[0], + options.closeDoubleQuote ?? resolved[1], + options.openSingleQuote ?? resolved[2], + options.closeSingleQuote ?? resolved[3] + ]; + return { + name: "smartQuotes", + quoteCharacters: quotes + }; +} +function resolveLocale(locale) { + const [exact, language] = localeKeys(locale); + return SMART_QUOTE_LOCALES[exact] ?? SMART_QUOTE_LOCALES[language] ?? SMART_QUOTE_LOCALES.en; +} +function localeKeys(locale) { + const normalized = locale.replaceAll("_", "-").toLowerCase(); + const exact = Object.keys(SMART_QUOTE_LOCALES).find((key2) => key2.toLowerCase() === normalized) ?? normalized; + return [exact, normalized.split("-")[0]]; +} +var SMART_QUOTE_LOCALES; +var init_smart_quotes = __esm({ + "node_modules/@markup-carve/carve/dist/smart-quotes.js"() { + SMART_QUOTE_LOCALES = Object.freeze({ + en: ["\u201C", "\u201D", "\u2018", "\u2019"], + de: ["\u201E", "\u201C", "\u201A", "\u2018"], + "de-CH": ["\xAB", "\xBB", "\u2039", "\u203A"], + fr: ["\xAB\xA0", "\xA0\xBB", "\u2039\xA0", "\xA0\u203A"], + pl: ["\u201E", "\u201D", "\u201A", "\u2019"], + ru: ["\xAB", "\xBB", "\u201E", "\u201C"], + ja: ["\u300C", "\u300D", "\u300E", "\u300F"], + zh: ["\u300C", "\u300D", "\u300E", "\u300F"], + sv: ["\u201D", "\u201D", "\u2019", "\u2019"], + da: ["\u201E", "\u201C", "\u201A", "\u2018"], + fi: ["\u201D", "\u201D", "\u2019", "\u2019"], + cs: ["\u201E", "\u201C", "\u201A", "\u2018"], + hu: ["\u201E", "\u201D", "\u201A", "\u2019"], + it: ["\xAB", "\xBB", "\u201C", "\u201D"], + es: ["\xAB", "\xBB", "\u201C", "\u201D"], + pt: ["\xAB", "\xBB", "\u201C", "\u201D"], + nl: ["\u201C", "\u201D", "\u2018", "\u2019"], + nb: ["\xAB", "\xBB", "\u2018", "\u2019"], + nn: ["\xAB", "\xBB", "\u2018", "\u2019"], + uk: ["\xAB", "\xBB", "\u201E", "\u201C"] + }); + } +}); + +// node_modules/@markup-carve/carve/dist/index-terms.js +function index() { + const occ = /* @__PURE__ */ new WeakMap(); + const counts = /* @__PURE__ */ new Map(); + const display = /* @__PURE__ */ new Map(); + const containers = /* @__PURE__ */ new WeakSet(); + let budget = new AbbrBudget(void 0); + return { + name: "index", + beforeRender(doc) { + counts.clear(); + display.clear(); + budget = budgetForDocument(doc); + for (const block of doc.children) + walkExtensions(block, "index", (ext) => { + const slug = termSlug2(ext.content); + const n = (counts.get(slug) ?? 0) + 1; + counts.set(slug, n); + occ.set(ext, n); + if (!display.has(slug)) + display.set(slug, deriveDisplayNodes(ext.content, false)); + }); + walkBlocks3(doc, (b) => { + if (isIndex(b)) + containers.add(b); + }); + return doc; + }, + renderers: { + index: (node, ctx) => renderMarker(node, ctx, occ) + }, + blockRenderers: { + admonition: (node, ctx) => containers.has(node) && counts.size > 0 ? renderIndexList(node, ctx, counts, display, budget) : void 0 + } + }; +} +function isIndex(b) { + return b.type === "admonition" && b.kind === "index"; +} +function renderMarker(node, ctx, occ) { + const n = occ.get(node); + if (n === void 0) + return ``; + const slug = termSlug2(node.content); + return ``; +} +function renderIndexList(node, ctx, counts, display, budget) { + const pad = ctx.indent(ctx.level); + const inner = ctx.indent(ctx.level + 1); + const slugs = [...counts.keys()].sort(byCodepoint); + const items = []; + for (const slug of slugs) { + const li = `${inner}
  • ${ctx.renderInlines(display.get(slug))} `; + if (!budget.charge(utf8ByteLength(li))) + break; + const links = []; + let truncated = false; + for (let m = 1; m <= counts.get(slug); m++) { + const link = `\u21A9`; + if (!budget.charge(utf8ByteLength(link))) { + truncated = true; + break; + } + links.push(link); + } + items.push(`${li}${links.join(" ")}
  • `); + if (truncated) + break; + } + const ul = `${pad} +${items.join("\n")} +${pad}`; + if (node.children.length === 0) + return ul; + return `${ctx.renderChildren(node.children, ctx.level)} +${ul}`; +} +function withBaseClass2(attrs, base) { + const a = attrs ? { ...attrs } : {}; + a.classes = [base, ...a.classes ?? []]; + return a; +} +function byCodepoint(a, b) { + let i = 0; + let j = 0; + const la = a.length; + const lb = b.length; + while (i < la && j < lb) { + const ca = a.codePointAt(i); + const cb = b.codePointAt(j); + if (ca !== cb) + return ca - cb; + i += ca > 65535 ? 2 : 1; + j += cb > 65535 ? 2 : 1; + } + return la - i - (lb - j); +} +function walkBlocks3(node, fn) { + if (!node || typeof node !== "object") + return; + if (typeof node.type === "string") + fn(node); + for (const key2 of Object.keys(node)) { + if (key2 === "pos") + continue; + const v = node[key2]; + if (Array.isArray(v)) + for (const el of v) + walkBlocks3(el, fn); + else if (v && typeof v === "object") + walkBlocks3(v, fn); + } +} +function walkExtensions(node, name, fn) { + if (!node || typeof node !== "object") + return; + if (node.type === "inline_extension" && node.name === name) { + fn(node); + return; + } + for (const key2 of Object.keys(node)) { + if (key2 === "pos") + continue; + const v = node[key2]; + if (Array.isArray(v)) + for (const el of v) + walkExtensions(el, name, fn); + else if (v && typeof v === "object") + walkExtensions(v, name, fn); + } +} +var termSlug2; +var init_index_terms = __esm({ + "node_modules/@markup-carve/carve/dist/index-terms.js"() { + init_abbr_budget(); + init_heading_ids(); + termSlug2 = (term) => slugify(inlineText(term), { lowercase: true }); + } +}); + +// node_modules/@markup-carve/carve/dist/fenced-render.js +function escapeText4(s) { + return s.replace(/&/g, "&").replace(/ word !== ""); + if (languages.length === 0) { + throw new Error("fencedRender requires at least one non-empty language word"); + } + const mode = opts.contentMode ?? "text"; + const cssClass = opts.cssClass ?? languages[0]; + const tag = opts.tag ?? (mode === "json" ? "div" : "pre"); + const figureClass = opts.figureClass ?? `${cssClass}-figure`; + return { + name: "fenced-render", + blockRenderers: { + "code_block": (node, ctx) => { + const code = node; + if (!languages.includes(code.lang ?? "")) + return void 0; + const attrs = { ...code.attrs, classes: [cssClass, ...code.attrs?.classes ?? []] }; + const open = `<${tag}${ctx.renderAttrs(attrs)}>`; + const body = mode === "json" ? `` : escapeText4(code.content); + const element = `${open}${body}`; + if (opts.wrapInFigure) { + const pad = ctx.indent(ctx.level); + return `${pad}
    +${pad}${element} +${pad}
    `; + } + return `${ctx.indent(ctx.level)}${element}`; + } + }, + staticBlockRenderers: { + // Static render: the diagram is a client-script visual, so the engine + // cannot draw it. The renderers map is open and keyed by css class, so if + // a build-time renderer is supplied for this fence's class (`mermaid`, + // `chart`, a custom word, …) emit its output wrapped in the attributed + // element so author attrs survive; otherwise degrade to the source as a + // `
    ` block - never blank, and re-renderable
    +      // by a host that loads the client library.
    +      "code_block": (node, ctx) => {
    +        const code = node;
    +        if (!languages.includes(code.lang ?? ""))
    +          return void 0;
    +        const pad = ctx.indent(ctx.level);
    +        const attrs = { ...code.attrs, classes: [cssClass, ...code.attrs?.classes ?? []] };
    +        const build2 = ctx.renderers[cssClass];
    +        if (build2) {
    +          const element = `${build2(code.content)}
    `; + if (opts.wrapInFigure) { + return `${pad}
    +${pad}${element} +${pad}
    `; + } + return `${pad}${element}`; + } + const langAttr = code.lang ? ` class="language-${ctx.escapeAttr(code.lang)}"` : ""; + return `${pad}${ctx.escapeHtml(code.content)} +
    `; + } + } + }; +} +var d2, graphviz, wavedrom, abc, plantuml, vegaLite, chart, mermaid, presets; +var init_fenced_render = __esm({ + "node_modules/@markup-carve/carve/dist/fenced-render.js"() { + d2 = () => fencedRender({ language: "d2" }); + graphviz = () => fencedRender({ language: ["dot", "graphviz"], cssClass: "graphviz" }); + wavedrom = () => fencedRender({ language: "wavedrom" }); + abc = () => fencedRender({ language: "abc" }); + plantuml = () => fencedRender({ language: ["plantuml", "puml"], cssClass: "plantuml" }); + vegaLite = () => fencedRender({ language: "vega-lite", contentMode: "json" }); + chart = () => fencedRender({ language: "chart", contentMode: "json" }); + mermaid = (opts = {}) => fencedRender({ language: "mermaid", ...opts }); + presets = () => [ + mermaid(), + d2(), + graphviz(), + wavedrom(), + abc(), + plantuml(), + vegaLite(), + chart() + ]; + } +}); + +// node_modules/@markup-carve/carve/dist/svg-sanitize.js +function schemeIsSafe(url) { + const probe = url.replace(SCHEME_STRIP_RE, ""); + const m = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(probe); + if (!m) + return true; + return !DANGEROUS_URL_SCHEMES2.has(m[1].toLowerCase()); +} +function decodeCssEscapes2(value) { + return value.replace(/\\([0-9a-f]{1,6}\s?|[\s\S])/gi, (_m, esc) => { + if (/^[0-9a-f]/i.test(esc)) { + const cp = Number.parseInt(esc.trim(), 16); + return Number.isFinite(cp) && cp <= 1114111 ? String.fromCodePoint(cp) : ""; + } + return esc; + }); +} +function decodeEntities(value) { + return value.replace(/&(#\d+|#x[0-9a-f]+|[a-z][a-z0-9]*);/gi, (m, body) => { + if (body[0] === "#") { + const cp = body[1]?.toLowerCase() === "x" ? Number.parseInt(body.slice(2), 16) : Number.parseInt(body.slice(1), 10); + return Number.isFinite(cp) && cp >= 0 && cp <= 1114111 ? String.fromCodePoint(cp) : m; + } + const named = ownValue(NAMED_REFS, body.toLowerCase()); + return named ?? m; + }); +} +function normalizeForCheck(value) { + return decodeCssEscapes2(decodeEntities(value)); +} +function styleIsDangerous(value) { + const compact = normalizeForCheck(value.replace(/\/\*[\s\S]*?\*\//g, "")).toLowerCase().replace(/\s+/g, ""); + return compact.includes("expression(") || compact.includes("url(") || compact.includes("@import") || compact.includes("behavior:") || compact.includes("-moz-binding") || compact.includes("javascript:"); +} +function refAttrUnsafe(value) { + const decoded = normalizeForCheck(value); + for (const seg of decoded.split(";")) { + const s = seg.trim(); + if (NONLOCAL_URL_RE.test(s)) + return true; + const probe = s.replace(SCHEME_STRIP_RE, ""); + if (ABSOLUTE_SCHEME_RE.test(probe)) + return true; + if (probe.startsWith("/")) + return true; + } + return false; +} +function valueHasExternalRef(value) { + const decoded = normalizeForCheck(value); + if (NONLOCAL_URL_RE.test(decoded)) + return true; + return !schemeIsSafe(decoded); +} +function escapeAmp(s) { + return s.replace(/&(?!#\d+;|#x[0-9a-fA-F]+;|(?:amp|lt|gt|quot|apos);)/g, "&"); +} +function escapeText5(s) { + return escapeAmp(s).replace(//g, ">"); +} +function escapeAttr2(s) { + return escapeAmp(s).replace(/"/g, """).replace(//g, ">"); +} +function tagAllowed(name, opts) { + const n = name.toLowerCase(); + if (ALLOWED_TAGS.has(name) || ALLOWED_TAGS.has(n)) + return true; + if (opts.allowLinks && LINK_TAGS.has(n)) + return true; + if (opts.allowAnimation && ANIMATION_TAGS.has(n)) + return true; + if (opts.allowExternalImages && EXTERNAL_IMAGE_TAGS.has(n)) + return true; + return false; +} +function parseAttrs2(raw) { + const out = []; + let m; + ATTR_RE2.lastIndex = 0; + while ((m = ATTR_RE2.exec(raw)) !== null) { + const value = m[3] ?? m[4] ?? (m[2] !== void 0 ? m[2] : null); + out.push({ name: m[1], value }); + } + return out; +} +function sanitizeAttrs(raw, opts, tag) { + const t = tag.toLowerCase(); + const allowExternalHref = opts.allowLinks === true && t === "a" || opts.allowExternalImages === true && t === "image"; + let out = ""; + const seen = /* @__PURE__ */ new Set(); + for (const { name, value } of parseAttrs2(raw)) { + if (seen.has(name)) + continue; + seen.add(name); + const n = name.toLowerCase(); + if (n.startsWith("on")) + continue; + if (URL_ATTRS.has(n)) { + if (value === null) + continue; + const decoded = normalizeForCheck(value); + const local = decoded.startsWith("#"); + if (!local && !allowExternalHref) + continue; + if (!schemeIsSafe(decoded)) + continue; + out += ` ${name}="${escapeAttr2(value)}"`; + continue; + } + if (n === "style") { + if (!opts.allowStyle || value === null) + continue; + if (styleIsDangerous(value)) + continue; + out += ` ${name}="${escapeAttr2(value)}"`; + continue; + } + if (n.startsWith("aria-") || n.startsWith("data-") || ALLOWED_ATTRS.has(n)) { + if (value !== null && (REF_VALUE_ATTRS.has(n) ? refAttrUnsafe(value) : valueHasExternalRef(value))) + continue; + out += value === null ? ` ${name}` : ` ${name}="${escapeAttr2(value)}"`; + } + } + return out; +} +function sanitizeSvg(source, opts = {}) { + const src = source.trim(); + let out = ""; + let lastIndex = 0; + const dropStack = []; + const kept = []; + let sawSvgRoot = false; + let rootSelfClosed = false; + let m; + TOKEN_RE.lastIndex = 0; + while ((m = TOKEN_RE.exec(src)) !== null) { + if (m.index > lastIndex) { + const between = src.slice(lastIndex, m.index); + if (!sawSvgRoot) { + if (between.trim() !== "") + return { svg: "", ok: false }; + } else if (dropStack.length === 0) { + out += escapeText5(between); + } + } + lastIndex = TOKEN_RE.lastIndex; + const endName = m[1]; + const startName = m[2]; + if (endName !== void 0) { + if (dropStack.length > 0) { + const d = dropStack.pop(); + if (d !== endName) { + return { svg: "", ok: false }; + } + } else { + const open = kept.pop(); + if (open === void 0 || open !== endName) { + return { svg: "", ok: false }; + } + out += ``; + } + continue; + } + if (startName === void 0) { + continue; + } + const selfClose = m[4] === "/"; + const allowed = tagAllowed(startName, opts); + const isRoot = kept.length === 0 && dropStack.length === 0 && !sawSvgRoot; + if (isRoot && startName !== "svg") { + return { svg: "", ok: false }; + } + if (!isRoot && kept.length === 0 && dropStack.length === 0 && sawSvgRoot) { + return { svg: "", ok: false }; + } + if (dropStack.length > 0) { + if (!selfClose) + dropStack.push(startName); + continue; + } + if (!allowed) { + if (!selfClose) + dropStack.push(startName); + continue; + } + if (isRoot) { + sawSvgRoot = true; + rootSelfClosed = selfClose; + } + let attrs = sanitizeAttrs(m[3] ?? "", opts, startName); + if (isRoot) { + attrs = ` xmlns="${SVG_NS}"` + attrs.replace(/\s+xmlns\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, ""); + } + out += `<${startName}${attrs}${selfClose ? "/>" : ">"}`; + if (!selfClose) + kept.push(startName); + } + if (lastIndex < src.length && sawSvgRoot && dropStack.length === 0) { + out += escapeText5(src.slice(lastIndex)); + } + if (!sawSvgRoot || kept.length !== 0 || dropStack.length !== 0) { + return { svg: "", ok: false }; + } + const tailOk = rootSelfClosed ? /\/>\s*$/.test(out) : /<\/svg>\s*$/i.test(out); + if (!/^]/i.test(out) || !tailOk) { + return { svg: "", ok: false }; + } + return { svg: out, ok: true }; +} +var SVG_NS, ALLOWED_TAGS, LINK_TAGS, ANIMATION_TAGS, EXTERNAL_IMAGE_TAGS, ALLOWED_ATTRS, URL_ATTRS, DANGEROUS_URL_SCHEMES2, SCHEME_STRIP_RE, NAMED_REFS, NONLOCAL_URL_RE, ABSOLUTE_SCHEME_RE, REF_VALUE_ATTRS, ATTR_RE2, TOKEN_RE; +var init_svg_sanitize = __esm({ + "node_modules/@markup-carve/carve/dist/svg-sanitize.js"() { + init_own_property(); + SVG_NS = "http://www.w3.org/2000/svg"; + ALLOWED_TAGS = /* @__PURE__ */ new Set([ + "svg", + "g", + "defs", + "symbol", + "use", + "title", + "desc", + "switch", + "path", + "rect", + "circle", + "ellipse", + "line", + "polyline", + "polygon", + "text", + "tspan", + "textPath", + "marker", + "linearGradient", + "radialGradient", + "stop", + "clipPath", + "mask", + "pattern", + "filter", + "feGaussianBlur", + "feOffset", + "feBlend", + "feColorMatrix", + "feComponentTransfer", + "feFuncA", + "feFuncR", + "feFuncG", + "feFuncB", + "feComposite", + "feFlood", + "feMerge", + "feMergeNode", + "feMorphology", + "feTile", + "feTurbulence", + "feDropShadow", + "feImage", + "feDisplacementMap" + ]); + LINK_TAGS = /* @__PURE__ */ new Set(["a"]); + ANIMATION_TAGS = /* @__PURE__ */ new Set(["animate", "animateTransform", "animateMotion", "set", "mpath"]); + EXTERNAL_IMAGE_TAGS = /* @__PURE__ */ new Set(["image"]); + ALLOWED_ATTRS = /* @__PURE__ */ new Set([ + "d", + "x", + "y", + "x1", + "y1", + "x2", + "y2", + "cx", + "cy", + "r", + "rx", + "ry", + "width", + "height", + "viewbox", + "points", + "transform", + "pathlength", + "fill", + "fill-opacity", + "fill-rule", + "stroke", + "stroke-width", + "stroke-linecap", + "stroke-linejoin", + "stroke-miterlimit", + "stroke-dasharray", + "stroke-dashoffset", + "stroke-opacity", + "opacity", + "color", + "offset", + "stop-color", + "stop-opacity", + "gradientunits", + "gradienttransform", + "spreadmethod", + "patternunits", + "patterntransform", + "patterncontentunits", + "clippathunits", + "maskunits", + "maskcontentunits", + "markerwidth", + "markerheight", + "markerunits", + "orient", + "refx", + "refy", + "preserveaspectratio", + "font-family", + "font-size", + "font-weight", + "font-style", + "text-anchor", + "dominant-baseline", + "letter-spacing", + "word-spacing", + "clip-path", + "clip-rule", + "mask", + "marker-start", + "marker-mid", + "marker-end", + "stddeviation", + "in", + "in2", + "result", + "mode", + "operator", + "values", + "type", + "flood-color", + "flood-opacity", + "attributename", + "begin", + "dur", + "from", + "to", + "repeatcount", + "keytimes", + "keysplines", + "calcmode", + "additive", + "accumulate", + "class", + "id", + "role", + "xmlns", + "xmlns:xlink", + "xml:space", + "version" + ]); + URL_ATTRS = /* @__PURE__ */ new Set(["href", "xlink:href"]); + DANGEROUS_URL_SCHEMES2 = /* @__PURE__ */ new Set([ + "javascript", + "vbscript", + "data", + "file", + "ms-msdt", + "ms-office", + "ms-word", + "ms-excel", + "ms-powerpoint", + "ms-access", + "ms-visio", + "ms-project", + "ms-publisher", + "ms-infopath", + "ms-spd", + "ms-search", + "search-ms", + "ms-cxh", + "ms-cxh-full", + "shell", + "vscode", + "vscode-insiders", + "jar" + ]); + SCHEME_STRIP_RE = /[\x00-\x20\u007f-\u009f\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/g; + NAMED_REFS = { + colon: ":", + semi: ";", + sol: "/", + tab: " ", + newline: "\n", + lpar: "(", + rpar: ")", + amp: "&", + quot: '"', + apos: "'", + nbsp: "\xA0" + }; + NONLOCAL_URL_RE = /url\(\s*['"]?\s*(?!#)/i; + ABSOLUTE_SCHEME_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:/; + REF_VALUE_ATTRS = /* @__PURE__ */ new Set([ + "fill", + "stroke", + "filter", + "clip-path", + "mask", + "marker-start", + "marker-mid", + "marker-end", + "color", + "stop-color", + "flood-color", + "values", + "from", + "to", + "by" + ]); + ATTR_RE2 = /([A-Za-z_:][\w:.-]*)(?:\s*=\s*("([^"]*)"|'([^']*)'|[^\s"'>]+))?/g; + TOKEN_RE = /||]*>|<\?[\s\S]*?\?>|<\/([A-Za-z][\w:.-]*)\s*>|<([A-Za-z][\w:.-]*)((?:"[^"]*"|'[^']*'|[^>"'])*?)(\/?)>/g; + } +}); + +// node_modules/@markup-carve/carve/dist/svg-fence.js +function consumedValue(attrs, key2) { + const kv = attrs?.keyValues; + if (!kv) + return void 0; + for (const [k, v] of Object.entries(kv)) { + if (k.toLowerCase() === key2) + return v; + } + return void 0; +} +function authorAttrs(attrs) { + if (!attrs?.keyValues) + return attrs; + const keyValues = {}; + for (const [k, v] of Object.entries(attrs.keyValues)) { + if (!CONSUMED_KEYS.has(k.toLowerCase())) + keyValues[k] = v; + } + const cleaned = { ...attrs, keyValues }; + if (attrs.order) + cleaned.order = attrs.order.filter((o) => !CONSUMED_KEYS.has(o.toLowerCase())); + return cleaned; +} +function stripKeys(attrs, keys) { + if (!attrs?.keyValues) + return attrs; + const drop = new Set(keys.map((k) => k.toLowerCase())); + const keyValues = {}; + for (const [k, v] of Object.entries(attrs.keyValues)) { + if (!drop.has(k.toLowerCase())) + keyValues[k] = v; + } + const cleaned = { ...attrs, keyValues }; + if (attrs.order) + cleaned.order = attrs.order.filter((o) => !drop.has(o.toLowerCase())); + return cleaned; +} +function mergeIntoRoot(svg, attrStr) { + if (attrStr === "") + return svg; + const fenceNames = [...attrStr.matchAll(/\s([A-Za-z_:][\w:.-]*)\s*=/g)].map((mm) => mm[1].toLowerCase()); + return svg.replace(/^])*?)(\/?)>/i, (_full, rootAttrs, slash) => { + let cleaned = rootAttrs; + for (const name of fenceNames) { + const esc = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + cleaned = cleaned.replace(new RegExp(`\\s${esc}\\s*=\\s*("[^"]*"|'[^']*'|[^\\s>]+)`, "i"), ""); + } + return ``; + }); +} +function svgTitle(svg) { + const m = /]*>([\s\S]*?)<\/title>/i.exec(svg); + if (!m) + return void 0; + const text = m[1].replace(/<[^>]*>/g, "").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/[49];/g, "'").replace(/&/g, "&").trim(); + return text === "" ? void 0 : text; +} +function sourceFallback(code, ctx) { + const pad = ctx.indent(ctx.level); + const langAttr = code.lang ? ` class="language-${code.lang}"` : ""; + return `${pad}
    ${ctx.escapeHtml(code.content)}
    +
    `; +} +function imgFence(opts = {}) { + const languages = (Array.isArray(opts.language) ? opts.language : opts.language ? [opts.language] : ["img", "image"]).filter((w) => w !== ""); + if (languages.length === 0) { + throw new Error("imgFence requires at least one non-empty language word"); + } + const render = { + "code_block": (node, ctx) => { + const code = node; + if (!languages.includes(code.lang ?? "")) + return void 0; + const { svg, ok } = sanitizeSvg(code.content, opts); + if (!ok) + return sourceFallback(code, ctx); + const pad = ctx.indent(ctx.level); + const cleanAttrs = authorAttrs(code.attrs); + const inline = opts.allowInline === true && consumedValue(code.attrs, "inline") !== void 0; + if (!inline) { + const alt = consumedValue(code.attrs, "alt") ?? svgTitle(svg) ?? ""; + const src = `data:image/svg+xml,${encodeURIComponent(svg)}`; + const imgAttrs = stripKeys(cleanAttrs, ["src", "srcset"]); + return `${pad}${ctx.escapeAttr(alt)}`; + } + const fenceAttrs = ctx.renderAttrs(cleanAttrs); + if (fenceAttrs === "") + return `${pad}${svg}`; + const merged = sanitizeSvg(mergeIntoRoot(svg, fenceAttrs), opts); + return merged.ok ? `${pad}${merged.svg}` : sourceFallback(code, ctx); + } + }; + return { + name: "img-fence", + blockRenderers: render, + // Inline SVG needs no client script — the interactive output is already + // static, so the static render is byte-identical. + staticBlockRenderers: render + }; +} +var CONSUMED_KEYS; +var init_svg_fence = __esm({ + "node_modules/@markup-carve/carve/dist/svg-fence.js"() { + init_svg_sanitize(); + CONSUMED_KEYS = /* @__PURE__ */ new Set(["inline", "alt", "sandbox"]); + } +}); + +// node_modules/@markup-carve/carve/dist/math-block.js +function escapeMath(s) { + return s.replace(/[&<>]/g, (c) => c === "&" ? "&" : c === "<" ? "<" : ">"); +} +function mathBlock(opts = {}) { + const language = opts.language ?? "math"; + const mathAttrs = (code) => { + const attrs = { ...code.attrs ?? {} }; + attrs.classes = ["math display", ...attrs.classes ?? []]; + if (attrs.order && !attrs.order.includes(".class")) { + attrs.order = [".class", ...attrs.order]; + } + return attrs; + }; + return { + name: "math-block", + blockRenderers: { + "code_block": (node, ctx) => { + const code = node; + if (code.lang !== language) + return void 0; + return `${ctx.indent(ctx.level)}\\[${escapeMath(code.content)}\\]
    `; + } + }, + // Static render: math needs a client script (KaTeX / MathJax) to draw. If a + // build-time `renderers.math` is supplied, emit its server-side output + // (MathML / HTML) inside the `math display` div so the page is + // self-contained; otherwise keep the `\[…\]` source - never blank. + staticBlockRenderers: { + "code_block": (node, ctx) => { + const code = node; + if (code.lang !== language) + return void 0; + const open = `${ctx.indent(ctx.level)}`; + const build2 = ctx.renderers.math; + const body = build2 ? build2(code.content, true) : `\\[${escapeMath(code.content)}\\]`; + return `${open}${body}
    `; + } + } + }; +} +var init_math_block = __esm({ + "node_modules/@markup-carve/carve/dist/math-block.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/spoiler.js +function spoiler() { + return { + name: "spoiler", + renderers: { + spoiler: (node, ctx) => { + const ext = node; + const attrs = withBaseClass3(ext.attrs, "spoiler"); + return `${ctx.renderInlines(ext.content)}`; + } + }, + blockRenderers: { + admonition: (node, ctx) => { + const adm = node; + if (adm.kind !== "spoiler") + return void 0; + const pad = ctx.indent(ctx.level); + const innerPad = ctx.indent(ctx.level + 1); + const rendered = adm.title ? ctx.renderInlines(adm.title).trim() : ""; + const summary = rendered !== "" ? rendered : "Spoiler"; + const attrs = withBaseClass3(adm.attrs, "spoiler"); + const open = ``; + const body = ctx.renderChildren(adm.children, ctx.level + 1); + return `${pad}${open} +${innerPad}${summary} +${body} +${pad}`; + } + }, + // Static render: hiding is meaningless offline, so the content is revealed. + // Inline: drop the blur, render the content plainly inside a revealed span. + // Block: the disclosure is expanded into a flat `
    ` with the title + // as a heading. + staticInlineRenderers: { + inline_extension: (node, ctx) => { + const ext = node; + if (ext.name !== "spoiler") + return void 0; + const attrs = withBaseClass3(ext.attrs, "spoiler spoiler-revealed"); + return `${ctx.renderInlines(ext.content)}`; + } + }, + staticBlockRenderers: { + admonition: (node, ctx) => { + const adm = node; + if (adm.kind !== "spoiler") + return void 0; + const pad = ctx.indent(ctx.level); + const innerPad = ctx.indent(ctx.level + 1); + const rendered = adm.title ? ctx.renderInlines(adm.title).trim() : ""; + const summary = rendered !== "" ? rendered : "Spoiler"; + const attrs = withBaseClass3(adm.attrs, "spoiler spoiler-revealed"); + const open = ``; + const body = ctx.renderChildren(adm.children, ctx.level + 1); + const labelLine = adm.label ? `${innerPad}

    ${ctx.escapeHtml(adm.label)}

    +` : ""; + return `${pad}${open} +${innerPad}

    ${summary}

    +` + labelLine + `${body} +${pad}
    `; + } + } + }; +} +function withBaseClass3(attrs, base) { + const a = attrs ? { ...attrs } : {}; + a.classes = [base, ...a.classes ?? []]; + return a; +} +var init_spoiler = __esm({ + "node_modules/@markup-carve/carve/dist/spoiler.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/color-swatch.js +function colorSwatch(options = {}) { + const position = options.position ?? "before"; + const shape = options.shape ?? "square"; + const tint = options.tint ?? false; + const reveal = options.reveal ?? false; + if (!POSITIONS.includes(position)) { + throw new Error(`Invalid ColorSwatch position "${position}"; expected one of: ${POSITIONS.join(", ")}.`); + } + if (!SHAPES.includes(shape)) { + throw new Error(`Invalid ColorSwatch shape "${shape}"; expected one of: ${SHAPES.join(", ")}.`); + } + return { + name: "color", + renderers: { + color: (node, ctx) => { + const value = safeColor(inlineText2(node.content)); + const contrast = hasKeyValue(node.attrs, "contrast"); + const attrs = contrast ? stripKeyValue2(node.attrs, "contrast") : node.attrs; + if (value === null) { + return contrast ? renderGenericColor(node, attrs, ctx) : void 0; + } + const text = contrastText(value); + if (contrast && text !== null) + return renderContrastLabel(attrs, ctx, value, text); + return renderSwatch(attrs, ctx, value, position, shape, tint, reveal); + } + } + }; +} +function renderContrastLabel(nodeAttrs, ctx, value, text) { + const attrs = withBaseClass4(nodeAttrs, "swatch-label"); + const style2 = hasKeyValue(nodeAttrs, "style") ? "" : ` style="${ctx.escapeAttr(`background:${value};color:${text}`)}"`; + return `${ctx.escapeHtml(value)}`; +} +function renderGenericColor(node, attrs, ctx) { + return `${ctx.renderInlines(node.content)}`; +} +function renderSwatch(nodeAttrs, ctx, value, position, shape, tint, reveal) { + const label = ctx.escapeHtml(value); + const chipClass = shape === "square" ? "swatch-chip" : `swatch-chip swatch-chip-${shape}`; + const chipStyle = shape === "ring" ? `border-color:${value}` : `background-color:${value}`; + const chip = ``; + let attrs = withBaseClass4(nodeAttrs, "swatch"); + if (tint) { + attrs = addClass(attrs, "swatch-tint"); + attrs = withDefaultKeyValue(attrs, "style", `background-color:color-mix(in srgb, ${value} 12%, transparent)`); + } + let inner; + if (position === "none") { + attrs = addClass(attrs, "swatch-chip-only"); + attrs = withDefaultKeyValue(attrs, "title", value); + inner = chip; + } else { + let valueHtml = label; + if (reveal) { + attrs = addClass(attrs, "swatch-reveal"); + attrs = withDefaultKeyValue(attrs, "tabindex", "0"); + valueHtml = `${label}`; + } + inner = position === "after" ? `${valueHtml} ${chip}` : `${chip} ${valueHtml}`; + } + return `${inner}`; +} +function safeColor(s) { + const value = s.trim(); + if (/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value)) { + return value; + } + if (/^(rgb|rgba|hsl|hsla)\([0-9.,%\s/]*[0-9][0-9.,%\s/]*\)$/.test(value)) { + return value; + } + if (/^[a-zA-Z]+$/.test(value) && NAMED_COLORS.has(value.toLowerCase())) { + return value; + } + return null; +} +function contrastText(value) { + if (isFullyTransparentHex(value)) + return null; + const rgb = parseIntegerRgb(value); + if (rgb === null) + return null; + const brightness = Math.floor((rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1e3); + return brightness >= 128 ? "#000" : "#fff"; +} +function isFullyTransparentHex(value) { + const hex = /^#([0-9a-fA-F]{4}|[0-9a-fA-F]{8})$/.exec(value); + if (!hex) + return false; + const alpha = hex[1].length === 4 ? hex[1][3] : hex[1].slice(6, 8); + return /^0+$/.test(alpha); +} +function parseIntegerRgb(value) { + const hex = /^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.exec(value); + if (hex) { + const h = hex[1]; + if (h.length === 3 || h.length === 4) { + return [parseInt(h[0] + h[0], 16), parseInt(h[1] + h[1], 16), parseInt(h[2] + h[2], 16)]; + } + return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)]; + } + const rgb = /^rgba?\((.*)\)$/.exec(value); + if (!rgb) + return null; + const tokens = rgb[1].trim().split(/[\s,/]+/).filter(Boolean); + if (tokens.length < 3) + return null; + const channels = tokens.slice(0, 3); + if (!channels.every((t) => /^[+-]?\d+$/.test(t))) + return null; + return channels.map((t) => clampByte(Number.parseInt(t, 10))); +} +function clampByte(n) { + return Math.min(255, Math.max(0, n)); +} +function withBaseClass4(attrs, base) { + const a = attrs ? { ...attrs } : {}; + a.classes = [base, ...a.classes ?? []]; + return a; +} +function addClass(attrs, cls) { + const classes = attrs.classes ?? []; + if (classes.includes(cls)) + return attrs; + return { ...attrs, classes: [...classes, cls] }; +} +function withDefaultKeyValue(attrs, key2, value) { + const keyValues = attrs.keyValues ?? {}; + if (key2 in keyValues) + return attrs; + return { ...attrs, keyValues: { ...keyValues, [key2]: value } }; +} +function hasKeyValue(attrs, key2) { + return attrs?.keyValues?.[key2] !== void 0; +} +function stripKeyValue2(attrs, key2) { + if (!attrs?.keyValues || attrs.keyValues[key2] === void 0) + return attrs; + const keyValues = { ...attrs.keyValues }; + delete keyValues[key2]; + const out = { ...attrs }; + if (Object.keys(keyValues).length > 0) { + out.keyValues = keyValues; + } else { + delete out.keyValues; + } + if (out.order) + out.order = out.order.filter((slot) => slot !== key2); + return out; +} +function inlineText2(nodes) { + let s = ""; + for (const node of nodes) { + const n = node; + if (typeof n.value === "string") + s += n.value; + if (n.type === "literal_inline" && typeof n.content === "string") + s += n.content; + if (typeof n.name === "string" && n.type === "tag") + s += `#${n.name}`; + const kids = n.children ?? n.content; + if (Array.isArray(kids)) + s += inlineText2(kids); + } + return s; +} +var POSITIONS, SHAPES, NAMED_COLORS; +var init_color_swatch = __esm({ + "node_modules/@markup-carve/carve/dist/color-swatch.js"() { + POSITIONS = ["before", "after", "none"]; + SHAPES = ["square", "round", "ring"]; + NAMED_COLORS = new Set("transparent currentcolor aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen".split(" ")); + } +}); + +// node_modules/@markup-carve/carve/dist/wikilinks.js +function defaultSlug(page) { + return page.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9\-_/]/g, "").replace(/-+/g, "-"); +} +function wikilinks(opts = {}) { + const cssClass = opts.cssClass ?? "wikilink"; + const urlGenerator = opts.urlGenerator ?? defaultSlug; + return { + name: "wikilinks", + matchInline(text, pos) { + if (text[pos] !== "[" || text[pos + 1] !== "[") + return null; + const close = text.indexOf("]]", pos + 2); + if (close < 0) + return null; + const body = text.slice(pos + 2, close); + const bar = body.indexOf("|"); + const rawPage = bar >= 0 ? body.slice(0, bar) : body; + if (rawPage.includes("]")) + return null; + let display = bar >= 0 ? body.slice(bar + 1).trim() : null; + let page = rawPage.trim(); + let anchor = ""; + const hash = page.indexOf("#"); + if (hash >= 0) { + anchor = "#" + page.slice(hash + 1); + page = page.slice(0, hash); + } + if (page === "" && anchor === "") + return null; + const href = urlGenerator(page) + anchor; + if (display === null) + display = page || anchor; + const classes = cssClass.split(" ").filter((c) => c !== ""); + const keyValues = { "data-wikilink": page }; + if (opts.newWindow) { + keyValues.target = "_blank"; + keyValues.rel = "noopener"; + } + const attrs = { classes, keyValues }; + return { + node: { type: "link", href, attrs, children: [{ type: "text", value: display }] }, + end: close + 2 + }; + } + }; +} +var init_wikilinks = __esm({ + "node_modules/@markup-carve/carve/dist/wikilinks.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/autolink.js +function autolink(opts = {}) { + const schemes = opts.allowedSchemes ?? ["https", "http", "mailto"]; + const urlSchemes = schemes.filter((s) => s !== "mailto").map(escapeRe); + const mailto = schemes.includes("mailto"); + const urlRe = urlSchemes.length ? new RegExp("(?:" + urlSchemes.join("|") + ")://[^" + AUTOLINK_BODY_EXCLUDED + "<>\\[\\](){}]*[^" + AUTOLINK_BODY_EXCLUDED + `<>\\[\\](){}.,;:!?'"]`, "yu") : null; + const mailtoRe = mailto ? new RegExp("mailto:" + EMAIL, "y") : null; + const emailRe = mailto ? new RegExp(EMAIL, "y") : null; + const at = (re, text, pos) => { + re.lastIndex = pos; + const m = re.exec(text); + return m ? m[0] : null; + }; + return { + name: "autolink", + matchInline(text, pos) { + const url = urlRe && at(urlRe, text, pos); + if (url) { + return { node: linkNode(url, url), end: pos + url.length }; + } + const mt = mailtoRe && at(mailtoRe, text, pos); + if (mt) { + return { node: linkNode(mt, mt.slice("mailto:".length)), end: pos + mt.length }; + } + const em = emailRe && at(emailRe, text, pos); + if (em) { + return { node: linkNode("mailto:" + em, em), end: pos + em.length }; + } + return null; + } + }; +} +function linkNode(href, text) { + return { type: "link", href, children: [{ type: "text", value: text }] }; +} +function escapeRe(s) { + return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +var EMAIL; +var init_autolink = __esm({ + "node_modules/@markup-carve/carve/dist/autolink.js"() { + init_parse(); + EMAIL = "[a-zA-Z0-9._%+-]{1,64}@(?:[a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,63}"; + } +}); + +// node_modules/@markup-carve/carve/dist/external-links.js +function isExternal(href) { + return /^https?:\/\//i.test(href); +} +function setAttr(attrs, name, value) { + const kv = attrs.keyValues ??= {}; + for (const key2 of Object.keys(kv)) { + if (key2 !== name && key2.toLowerCase() === name) { + delete kv[key2]; + if (attrs.order) + attrs.order = attrs.order.filter((o) => o !== key2); + } + } + kv[name] = value; +} +function externalLinks(opts = {}) { + const target = opts.target ?? "_blank"; + let rel = opts.rel ?? "noopener noreferrer"; + if (opts.nofollow && !rel.split(/\s+/).includes("nofollow")) { + rel = `${rel} nofollow`.trim(); + } + const visit4 = (value) => { + if (!value || typeof value !== "object") + return; + if (Array.isArray(value)) { + for (const item2 of value) + visit4(item2); + return; + } + const node = value; + if ((node.type === "link" || node.type === "autolink") && typeof node.href === "string" && isExternal(node.href)) { + const attrs = node.attrs ??= {}; + setAttr(attrs, "target", target); + setAttr(attrs, "rel", rel); + } + for (const child of Object.values(value)) + visit4(child); + }; + return { + name: "external-links", + beforeRender(doc) { + visit4(doc); + return doc; + } + }; +} +var init_external_links = __esm({ + "node_modules/@markup-carve/carve/dist/external-links.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/table-of-contents.js +function escapeHtml2(s) { + return s.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); +} +function stripBidi(s) { + return stripBidiControls(s); +} +function textNodes(nodes) { + const out = []; + const visit4 = (value) => { + if (Array.isArray(value)) { + for (const item2 of value) + visit4(item2); + return; + } + if (!value || typeof value !== "object") + return; + const node = value; + if (node["type"] === "text" && typeof node["value"] === "string") + out.push(node); + for (const key2 of Object.keys(node)) { + if (key2 !== "pos" && key2 !== "type" && key2 !== "value") + visit4(node[key2]); + } + }; + visit4(nodes); + return out; +} +function stripBidiAndTrim(nodes) { + for (const node of textNodes(nodes)) + node.value = stripBidi(node.value); + const first = nodes[0]; + if (first?.type === "text") + first.value = first.value.trimStart(); + const last = nodes[nodes.length - 1]; + if (last?.type === "text") + last.value = last.value.trimEnd(); +} +function tocHeadingNodes(children) { + const filtered = children.filter((c) => !(c.type === "span" && c.attrs?.classes?.includes("section-number"))); + const nodes = deriveDisplayNodes(filtered, true); + stripBidiAndTrim(nodes); + return nodes; +} +function renderInlineHtml(nodes, opts) { + return renderInlinesInLinkContext(nodes, opts); +} +function buildList(entries, listType, opts) { + if (entries.length === 0) + return ""; + let html = `<${listType}> +`; + const levelStack = [entries[0].level]; + let hasOpenItem = false; + for (const e of entries) { + if (hasOpenItem) { + let depth2 = levelStack.length; + const currentLevel = levelStack[depth2 - 1]; + if (e.level > currentLevel) { + html += ` +<${listType}> +`; + levelStack.push(e.level); + } else { + while (depth2 > 1 && e.level <= levelStack[depth2 - 2]) { + html += ` + +`; + levelStack.pop(); + depth2--; + } + html += "\n"; + levelStack[depth2 - 1] = e.level; + } + } + html += `
  • ${renderInlineHtml(e.nodes, opts)}`; + hasOpenItem = true; + } + html += "
  • \n"; + let depth = levelStack.length; + while (depth > 1) { + html += ` + +`; + levelStack.pop(); + depth--; + } + html += ` +`; + return html; +} +function tableOfContents(opts = {}) { + const minLevel = opts.minLevel ?? 1; + const maxLevel = opts.maxLevel ?? 6; + const listType = opts.listType === "ol" ? "ol" : "ul"; + const cssClass = opts.cssClass ?? "toc"; + const position = opts.position ?? "top"; + const collapsible = opts.collapsible ?? false; + const summary = opts.summary ?? "Table of Contents"; + const open = opts.open ?? false; + return { + name: "table-of-contents", + beforeRender(doc, ctx) { + const entries = []; + for (const node of doc.children) { + if (node.type !== "heading") + continue; + const h = node; + const id = h.attrs?.id; + if (!id || h.level < minLevel || h.level > maxLevel) + continue; + entries.push({ level: h.level, nodes: tocHeadingNodes(h.children), id }); + } + if (entries.length === 0) + return doc; + const list = buildList(entries, listType, ctx.options); + const html = collapsible ? `
    +${escapeHtml2(summary)} +${list}
    ` : ``; + const toc = { type: "raw_block", format: "html", content: html }; + if (position === "top") { + doc.children.unshift(toc); + return doc; + } + doc.children.push(toc); + doc.trailerBlocks = [...doc.trailerBlocks ?? [], toc]; + return doc; + } + }; +} +function levelOf(v, fallback) { + if (v === void 0) + return fallback; + const n = Number.parseInt(v, 10); + if (!Number.isFinite(n)) + return fallback; + return Math.min(6, Math.max(1, n)); +} +function tocWindow(attrs) { + const kv = attrs?.keyValues ?? {}; + if (kv.from !== void 0 || kv.to !== void 0) { + let minLevel = levelOf(kv.from, 1); + let maxLevel = levelOf(kv.to, 6); + if (minLevel > maxLevel) + [minLevel, maxLevel] = [maxLevel, minLevel]; + return { minLevel, maxLevel }; + } + return { minLevel: 1, maxLevel: levelOf(kv.depth, 6) }; +} +function navAttrs(attrs) { + const a = { classes: ["toc", ...(attrs?.classes ?? []).filter((c) => c !== "toc")] }; + if (attrs?.id !== void 0) + a.id = attrs.id; + const kv = attrs?.keyValues; + if (kv) { + const kept = {}; + for (const k of Object.keys(kv)) + if (!RESERVED_TOC_ATTRS.has(k)) + kept[k] = kv[k]; + if (Object.keys(kept).length > 0) + a.keyValues = kept; + } + return a; +} +function collectPlacementHeadings(node, out) { + if (!node || typeof node !== "object") + return; + const typed = node; + if (typed.type === "heading") { + const h = node; + const id = h.attrs?.id; + if (id !== void 0) + out.push({ level: h.level, nodes: tocHeadingNodes(h.children), id }); + return; + } + for (const key2 of Object.keys(node)) { + if (key2 === "pos") + continue; + const value = node[key2]; + if (Array.isArray(value)) + for (const el of value) + collectPlacementHeadings(el, out); + else if (value && typeof value === "object") + collectPlacementHeadings(value, out); + } +} +function renderToc(node, ctx, entries, budget) { + const attrs = ctx.renderAttrs(navAttrs(node.attrs)); + const emptyNav = ``; + const wrap = (nav2) => node.children.length === 0 ? nav2 : `${ctx.renderChildren(node.children, ctx.level)} +${nav2}`; + const { minLevel, maxLevel } = tocWindow(node.attrs); + const picked = entries.filter((e) => e.level >= minLevel && e.level <= maxLevel); + if (picked.length === 0) + return wrap(emptyNav); + const nav = ` +${buildList(picked, "ul", void 0)}`; + if (!budget.charge(utf8ByteLength(nav))) + return wrap(emptyNav); + return wrap(nav); +} +function tocPlacement() { + let entries = []; + let budget = new AbbrBudget(void 0); + return { + name: "toc", + beforeRender(doc) { + entries = []; + budget = budgetForDocument(doc); + for (const node of doc.children) + collectPlacementHeadings(node, entries); + return doc; + }, + blockRenderers: { + admonition: (node, ctx) => { + const a = node; + return a.kind === "toc" ? renderToc(a, ctx, entries, budget) : void 0; + } + } + }; +} +var RESERVED_TOC_ATTRS; +var init_table_of_contents = __esm({ + "node_modules/@markup-carve/carve/dist/table-of-contents.js"() { + init_abbr_budget(); + init_heading_ids(); + init_render_html(); + init_bidi_controls(); + RESERVED_TOC_ATTRS = /* @__PURE__ */ new Set(["depth", "from", "to"]); + } +}); + +// node_modules/@markup-carve/carve/dist/heading-permalinks.js +function stripId2(attrs) { + if (!attrs?.id) + return attrs; + const { id: _id, order, ...rest } = attrs; + return { ...rest, ...order ? { order: order.filter((o) => o !== "#id") } : {} }; +} +function headingPermalinks(opts = {}) { + const symbol = opts.symbol ?? "\xB6"; + const cssClass = opts.cssClass ?? "permalink"; + const ariaLabel = opts.ariaLabel ?? "Permalink"; + const levels = opts.levels ?? [1, 2, 3, 4, 5, 6]; + const prepend = opts.prepend ?? false; + const showOnHover = opts.showOnHover ?? false; + const copyToClipboard = opts.copyToClipboard ?? false; + return { + name: "heading-permalinks", + blockRenderers: { + heading: (node, ctx) => { + const h = node; + const id = h.attrs?.id; + if (!id || !levels.includes(h.level)) + return void 0; + const inner = ctx.renderInlines(h.children); + const copyAttr = copyToClipboard ? ' data-permalink-copy=""' : ""; + const anchor = `${ctx.escapeHtml(symbol)}`; + const marker = showOnHover ? `${anchor}` : anchor; + const body = prepend ? `${marker} ${inner}` : `${inner} ${marker}`; + const attrs = ctx.sections ? stripId2(h.attrs) : h.attrs; + return `${ctx.indent(ctx.level)}${body}`; + } + } + }; +} +var init_heading_permalinks = __esm({ + "node_modules/@markup-carve/carve/dist/heading-permalinks.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/code-group.js +function isCodeGroup(node) { + if (node.type === "admonition") + return node.kind === "code-group"; + if (node.type === "div") + return (node.attrs?.classes ?? []).includes("code-group"); + return false; +} +function extraClasses(node) { + const classes = node.attrs?.classes ?? []; + return classes.filter((c) => c !== "code-group"); +} +function extractItems(node) { + const items = []; + let position = 0; + for (const child of node.children) { + if (child.type !== "code_block") + continue; + position++; + const cb = child; + const language = cb.lang && cb.lang !== "" ? cb.lang : void 0; + const labelText = cb.label?.trim(); + const label = labelText && labelText !== "" ? labelText : language ?? `Code ${position}`; + const selected = cb.attrs?.keyValues?.selected !== void 0; + items.push({ block: cb, language, label, selected }); + } + if (items.length && !items.some((i) => i.selected)) + items[0].selected = true; + return items; +} +function withoutSelected(attrs) { + if (!attrs?.keyValues || attrs.keyValues.selected === void 0) + return attrs; + const kv = { ...attrs.keyValues }; + delete kv.selected; + const out = { ...attrs, keyValues: kv }; + if (attrs.order) + out.order = attrs.order.filter((s) => s !== "selected"); + return out; +} +function codeGroup(opts = {}) { + const wrapperClass = opts.wrapperClass ?? "code-group"; + const panelClass = opts.panelClass ?? "code-group-panel"; + const labelClass = opts.labelClass ?? "code-group-label"; + const radioClass = opts.radioClass ?? "code-group-radio"; + const idPrefix = opts.idPrefix ?? "codegroup"; + const highlighter = opts.highlighter; + let groupCounter = 0; + const renderGroup2 = (node, ctx) => { + const items = extractItems(node); + if (items.length === 0) + return void 0; + groupCounter++; + const groupId = ctx.uniqueId(`${idPrefix}-${groupCounter}`); + const pad = ctx.indent(ctx.level); + const classes = [wrapperClass, ...extraClasses(node).filter((c) => c !== wrapperClass)]; + const attrs = { classes }; + if (node.attrs?.id !== void 0) + attrs.id = node.attrs.id; + if (node.attrs?.keyValues) + attrs.keyValues = { ...node.attrs.keyValues }; + attrs.order = [".class", ...(node.attrs?.order ?? []).filter((s) => s !== ".class")]; + let html = `${pad} +`; + items.forEach((item2, index2) => { + const inputId = ctx.uniqueId(`${groupId}-tab-${index2 + 1}`); + const checked = item2.selected ? " checked" : ""; + html += ` +`; + html += ` +`; + }); + for (const item2 of items) { + html += `
    `; + html += renderCodeBlock2(item2, ctx); + html += "
    \n"; + } + html += `${pad}`; + return html; + }; + const renderCodeBlock2 = (item2, ctx) => { + const content = item2.block.content.replace(/\n+$/, ""); + if (highlighter) + return highlighter(content, item2.language); + const langAttr = item2.language ? ` class="language-${item2.language}"` : ""; + const escaped = ctx.escapeHtml(item2.block.content); + return `${escaped} + +`; + }; + const renderGroupStatic = (node, ctx) => { + const items = extractItems(node); + if (items.length === 0) + return void 0; + const pad = ctx.indent(ctx.level); + const innerPad = ctx.indent(ctx.level + 1); + const classes = [wrapperClass, ...extraClasses(node).filter((c) => c !== wrapperClass)]; + const attrs = { classes }; + if (node.attrs?.id !== void 0) + attrs.id = node.attrs.id; + if (node.attrs?.keyValues) + attrs.keyValues = { ...node.attrs.keyValues }; + attrs.order = [".class", ...(node.attrs?.order ?? []).filter((s) => s !== ".class")]; + let html = `${pad} +`; + for (const item2 of items) { + html += `${innerPad}
    +`; + html += `${innerPad}

    ${ctx.escapeHtml(item2.label)}

    +`; + html += renderCodeBlock2(item2, ctx); + html += `${innerPad}
    +`; + } + html += `${pad}`; + return html; + }; + return { + name: "code-group", + beforeRender(doc) { + groupCounter = 0; + return doc; + }, + blockRenderers: { + admonition: (node, ctx) => isCodeGroup(node) ? renderGroup2(node, ctx) : void 0, + div: (node, ctx) => isCodeGroup(node) ? renderGroup2(node, ctx) : void 0 + }, + staticBlockRenderers: { + admonition: (node, ctx) => isCodeGroup(node) ? renderGroupStatic(node, ctx) : void 0, + div: (node, ctx) => isCodeGroup(node) ? renderGroupStatic(node, ctx) : void 0 + } + }; +} +var init_code_group = __esm({ + "node_modules/@markup-carve/carve/dist/code-group.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/tabs.js +function isTabs(node) { + if (node.type === "admonition") + return node.kind === "tabs"; + if (node.type === "div") + return (node.attrs?.classes ?? []).includes("tabs"); + return false; +} +function isTab(node) { + if (node.type === "admonition") + return node.kind === "tab"; + if (node.type === "div") + return (node.attrs?.classes ?? []).includes("tab"); + return false; +} +function extraClasses2(node, structural) { + return (node.attrs?.classes ?? []).filter((c) => c !== structural); +} +function tabs(opts = {}) { + const mode = opts.mode === "aria" ? "aria" : "css"; + const wrapperClass = opts.wrapperClass ?? "tabs"; + const tabClass = opts.tabClass ?? "tabs-panel"; + const labelClass = opts.labelClass ?? "tabs-label"; + const radioClass = opts.radioClass ?? "tabs-radio"; + const idPrefix = opts.idPrefix ?? "tabset"; + let tabSetCounter = 0; + let labelCounter = 0; + const explicitLabel = (tab) => tab.label ?? tab.attrs?.keyValues?.label; + const extractLabel = (tab) => { + const label = explicitLabel(tab); + if (label !== void 0) + return label; + for (const child of tab.children) { + if (child.type === "heading") + return inlineText(child.children); + } + return `Tab ${++labelCounter}`; + }; + const renderTabContent = (tab, ctx) => { + const skipFirstHeading = explicitLabel(tab) === void 0; + let skipped = false; + let html = ""; + const title = tab.type === "admonition" ? tab.title : void 0; + if (title !== void 0) { + html += `

    ${ctx.renderInlines(title)}

    +`; + } + for (const child of tab.children) { + if (skipFirstHeading && !skipped && child.type === "heading") { + skipped = true; + continue; + } + const fragment = ctx.renderChildren([child], 0); + if (fragment !== "") + html += `${fragment} +`; + } + return html; + }; + const collectTabs = (wrapper, ctx) => { + const items = []; + for (const child of wrapper.children) { + if (!isTab(child)) + continue; + const tab = child; + items.push({ + label: extractLabel(tab), + content: renderTabContent(tab, ctx), + selected: tab.attrs?.keyValues?.selected !== void 0, + id: tab.attrs?.id + }); + } + if (items.length && !items.some((i) => i.selected)) + items[0].selected = true; + return items; + }; + const buildWrapperAttributes = (wrapper, ctx, role) => { + const classes = [ + wrapperClass, + ...extraClasses2(wrapper, "tabs").filter((c) => c !== wrapperClass) + ]; + const attrs = { classes }; + const id = wrapper.attrs?.id; + if (id !== void 0) + attrs.id = id; + if (wrapper.attrs?.keyValues || role) { + attrs.keyValues = { ...wrapper.attrs?.keyValues ?? {} }; + if (role) + attrs.keyValues.role = role; + } + const authorOrder = (wrapper.attrs?.order ?? []).filter((s) => s !== ".class"); + attrs.order = [ + ".class", + ...role ? ["role"] : [], + ...authorOrder.filter((s) => s !== "role") + ]; + return ctx.renderAttrs(attrs); + }; + const renderCss = (wrapper, items, ctx) => { + tabSetCounter++; + const setId = ctx.uniqueId(`${idPrefix}-${tabSetCounter}`); + const pad = ctx.indent(ctx.level); + let html = `${pad} +`; + items.forEach((tab, index2) => { + const inputId = tab.id ?? ctx.uniqueId(`${setId}-tab-${index2 + 1}`); + const checked = tab.selected ? " checked" : ""; + html += ` +`; + html += ` +`; + }); + for (const tab of items) { + html += `
    +${tab.content}
    +`; + } + html += `${pad}`; + return html; + }; + const renderAria = (wrapper, items, ctx) => { + tabSetCounter++; + const setId = ctx.uniqueId(`${idPrefix}-${tabSetCounter}`); + const pad = ctx.indent(ctx.level); + const pairIds = items.map((tab, index2) => { + const num = index2 + 1; + return { + tab: tab.id ? `${ctx.escapeAttr(tab.id)}-tab` : ctx.uniqueId(`${setId}-tab-${num}`), + panel: tab.id ? `${ctx.escapeAttr(tab.id)}-panel` : ctx.uniqueId(`${setId}-panel-${num}`) + }; + }); + let html = `${pad} +`; + items.forEach((tab, index2) => { + const tabId = pairIds[index2].tab; + const panelId = pairIds[index2].panel; + const selected = tab.selected ? "true" : "false"; + const tabindex = tab.selected ? "" : ' tabindex="-1"'; + html += ` +`; + }); + items.forEach((tab, index2) => { + const tabId = pairIds[index2].tab; + const panelId = pairIds[index2].panel; + const hidden = tab.selected ? "" : " hidden"; + html += `
    +${tab.content}
    +`; + }); + html += `${pad}`; + return html; + }; + const renderTabs = (node, ctx) => { + const items = collectTabs(node, ctx); + if (items.length === 0) + return void 0; + return mode === "aria" ? renderAria(node, items, ctx) : renderCss(node, items, ctx); + }; + const renderTabsStatic = (node, ctx) => { + const items = collectTabs(node, ctx); + if (items.length === 0) + return void 0; + const pad = ctx.indent(ctx.level); + const innerPad = ctx.indent(ctx.level + 1); + let html = `${pad} +`; + for (const tab of items) { + html += `${innerPad}
    +`; + html += `${innerPad}

    ${ctx.escapeHtml(tab.label)}

    +`; + html += tab.content; + html += `${innerPad}
    +`; + } + html += `${pad}`; + return html; + }; + return { + name: "tabs", + beforeRender(doc) { + tabSetCounter = 0; + labelCounter = 0; + return doc; + }, + blockRenderers: { + admonition: (node, ctx) => isTabs(node) ? renderTabs(node, ctx) : void 0, + div: (node, ctx) => isTabs(node) ? renderTabs(node, ctx) : void 0 + }, + staticBlockRenderers: { + admonition: (node, ctx) => isTabs(node) ? renderTabsStatic(node, ctx) : void 0, + div: (node, ctx) => isTabs(node) ? renderTabsStatic(node, ctx) : void 0 + } + }; +} +var init_tabs = __esm({ + "node_modules/@markup-carve/carve/dist/tabs.js"() { + init_heading_ids(); + } +}); + +// node_modules/@markup-carve/carve/dist/heading-level-shift.js +function shiftBlock(node, shift) { + switch (node.type) { + case "heading": + node.level = Math.min(6, node.level + shift); + break; + case "block_quote": + case "div": + case "admonition": + case "figure_group": + node.children.forEach((c) => shiftBlock(c, shift)); + break; + case "list": + for (const it of node.items) + it.children.forEach((c) => shiftBlock(c, shift)); + break; + case "definition_list": + for (const it of node.items) + for (const d of it.definitions) + for (const b of d) + shiftBlock(b, shift); + break; + case "figure": + if (node.target.type === "block_quote") + shiftBlock(node.target, shift); + break; + default: + break; + } +} +function headingLevelShift(opts = {}) { + const shift = Math.max(0, Math.min(opts.shift ?? 1, 5)); + return { + name: "heading-level-shift", + beforeRender(doc) { + if (shift === 0) + return doc; + doc.children.forEach((c) => shiftBlock(c, shift)); + return doc; + } + }; +} +var init_heading_level_shift = __esm({ + "node_modules/@markup-carve/carve/dist/heading-level-shift.js"() { + } +}); + +// node_modules/@markup-carve/carve/dist/heading-reference.js +function normalizeQuotes(text) { + return text.replace(/[“”]/g, '"').replace(/[‘’]/g, "'"); +} +function resolveInlines(nodes, targets, counts) { + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + if (node.type === "link" && node.attrs?.keyValues?.[MARK] !== void 0) { + const link = node; + const target = link.attrs.keyValues[MARK]; + const display = inlineText(link.children); + const norm = normalizeQuotes(target); + const id = targets.get(norm); + if (id !== void 0 && counts.get(norm) === 1) { + link.href = `#${id}`; + const kv = { ...link.attrs.keyValues }; + delete kv[MARK]; + link.attrs = { ...link.attrs, keyValues: kv }; + if (link.attrs.order) + link.attrs.order = link.attrs.order.filter((s) => s !== MARK); + } else { + const literal = target === display ? `[[${target}]]` : `[[${target}|${display}]]`; + nodes[i] = { type: "text", value: literal }; + } + continue; + } + const kids = node.children ?? node.content; + if (Array.isArray(kids)) + resolveInlines(kids, targets, counts); + } +} +function headingReference(opts = {}) { + const classes = (opts.cssClass ?? "heading-ref").split(" ").filter((c) => c !== ""); + return { + name: "heading-reference", + matchInline(text, pos) { + if (text[pos] !== "[" || text[pos + 1] !== "[") + return null; + const first = text[pos + 2]; + if (first === void 0 || first === "]" || first === "|" || first === "#") + return null; + const close = text.indexOf("]]", pos + 2); + if (close < 0) + return null; + const body = text.slice(pos + 2, close); + const bar = body.indexOf("|"); + const rawTarget = bar >= 0 ? body.slice(0, bar) : body; + if (rawTarget.includes("]")) + return null; + const target = rawTarget.trim(); + if (target === "") + return null; + const display = bar >= 0 ? body.slice(bar + 1).trim() : target; + const link = { + type: "link", + href: "", + attrs: { classes: [...classes], keyValues: { [MARK]: target }, order: [".class", MARK] }, + children: [{ type: "text", value: display }] + }; + return { node: link, end: close + 2 }; + }, + beforeRender(doc) { + const targets = /* @__PURE__ */ new Map(); + const counts = /* @__PURE__ */ new Map(); + for (const node of doc.children) { + if (node.type !== "heading") + continue; + const h = node; + const id = h.attrs?.id; + const text = normalizeQuotes(inlineText(h.children).trim()); + if (text === "" || id === void 0) + continue; + counts.set(text, (counts.get(text) ?? 0) + 1); + if (!targets.has(text)) + targets.set(text, id); + } + for (const node of doc.children) + walkBlock(node, targets, counts); + return doc; + } + }; +} +function walkBlock(node, targets, counts) { + switch (node.type) { + case "heading": + case "paragraph": + resolveInlines(node.children, targets, counts); + break; + case "block_quote": + case "div": + case "admonition": + case "figure_group": + node.children.forEach((c) => walkBlock(c, targets, counts)); + break; + case "list": + for (const it of node.items) + it.children.forEach((c) => walkBlock(c, targets, counts)); + break; + case "table": + for (const row of node.rows) + for (const cell of row.cells) + resolveInlines(cell.children, targets, counts); + break; + case "definition_list": + for (const it of node.items) { + for (const t of it.terms) + resolveInlines(t, targets, counts); + for (const d of it.definitions) + for (const b of d) + walkBlock(b, targets, counts); + } + break; + default: + break; + } +} +var MARK; +var init_heading_reference = __esm({ + "node_modules/@markup-carve/carve/dist/heading-reference.js"() { + init_heading_ids(); + MARK = "data-heading-ref"; + } +}); + +// node_modules/@markup-carve/carve/dist/default-attributes.js +function pushOrder(attrs, slot) { + if (!attrs.order) + attrs.order = []; + if (!attrs.order.includes(slot)) + attrs.order.push(slot); +} +function mergeClasses(attrs, classes) { + const existing = attrs.classes ?? []; + let changed = false; + for (const cls of classes.split(" ")) { + const c = cls.trim(); + if (c !== "" && !existing.includes(c)) { + existing.push(c); + changed = true; + } + } + if (changed) { + attrs.classes = existing; + pushOrder(attrs, ".class"); + } +} +function applyDefaults(node, defaults) { + const n = node; + if (!n.attrs) + n.attrs = {}; + const attrs = n.attrs; + for (const [name, value] of Object.entries(defaults)) { + if (name === "class") { + mergeClasses(attrs, value); + continue; + } + if (name === "id") { + if (attrs.id === void 0) { + attrs.id = value; + pushOrder(attrs, "#id"); + } + continue; + } + if (!attrs.keyValues || attrs.keyValues[name] === void 0) { + attrs.keyValues = { ...attrs.keyValues ?? {}, [name]: value }; + pushOrder(attrs, name); + } + } +} +function visit2(node, byType) { + const defaults = byType.get(node.type); + if (defaults) + applyDefaults(node, defaults); + const block = node; + const inline = node; + if (Array.isArray(node.children)) { + for (const c of node.children) + visit2(c, byType); + } + if (Array.isArray(inline.content)) { + for (const c of inline.content) + visit2(c, byType); + } + switch (node.type) { + case "list": + for (const it of block.items) + for (const c of it.children) + visit2(c, byType); + break; + case "definition_list": + for (const it of block.items) { + for (const t of it.terms) + for (const c of t) + visit2(c, byType); + for (const d of it.definitions) + for (const c of d) + visit2(c, byType); + } + break; + case "table": + for (const row of block.rows) + for (const cell of row.cells) + visit2(cell, byType); + break; + case "figure": + visit2(block.target, byType); + break; + default: + break; + } +} +function defaultAttributes(opts = {}) { + const defaults = opts.defaults ?? {}; + const byType = /* @__PURE__ */ new Map(); + for (const [phpType, attrs] of Object.entries(defaults)) { + const jsTypes = TYPE_MAP[phpType]; + if (!jsTypes) + continue; + for (const jsType of jsTypes) + byType.set(jsType, attrs); + } + return { + name: "default-attributes", + beforeRender(doc) { + if (byType.size === 0) + return doc; + for (const c of doc.children) + visit2(c, byType); + return doc; + } + }; +} +var TYPE_MAP; +var init_default_attributes = __esm({ + "node_modules/@markup-carve/carve/dist/default-attributes.js"() { + TYPE_MAP = { + paragraph: ["paragraph"], + heading: ["heading"], + code_block: ["code_block"], + block_quote: ["block_quote"], + list: ["list"], + table: ["table"], + div: ["div", "admonition"], + thematic_break: ["thematic_break"], + link: ["link"], + image: ["image"], + span: ["span"], + code: ["code"], + footnote: ["footnote"], + footnote_ref: ["footnote"], + emphasis: ["emphasis"], + strong: ["strong"], + superscript: ["superscript"], + subscript: ["subscript"], + strike: ["strike"] + }; + } +}); + +// node_modules/@markup-carve/carve/dist/index.js +var dist_exports = {}; +__export(dist_exports, { + AstJsonDepthError: () => AstJsonDepthError, + AstJsonNodeTypeError: () => AstJsonNodeTypeError, + AstJsonPartitionError: () => AstJsonPartitionError, + AstJsonRootError: () => AstJsonRootError, + AstJsonRootFieldError: () => AstJsonRootFieldError, + AstJsonSchemaError: () => AstJsonSchemaError, + AstJsonUnknownFieldError: () => AstJsonUnknownFieldError, + AstJsonUnknownNodeTypeError: () => AstJsonUnknownNodeTypeError, + AstPatchError: () => AstPatchError, + BBCODE_MAX_INPUT_LENGTH: () => BBCODE_MAX_INPUT_LENGTH, + BbcodeInputTooLargeError: () => BbcodeInputTooLargeError, + CANONICAL_ADMONITION_KINDS: () => CANONICAL_ADMONITION_KINDS, + CANONICAL_BLOCK_TYPES: () => CANONICAL_BLOCK_TYPES, + CANONICAL_INLINE_TYPES: () => CANONICAL_INLINE_TYPES, + HtmlImportLimitError: () => HtmlImportLimitError, + KNOWN_LINT_PLATFORMS: () => KNOWN_LINT_PLATFORMS, + LIB_VERSION: () => LIB_VERSION, + LinkPolicy: () => LinkPolicy, + MAX_AST_JSON_DEPTH: () => MAX_AST_JSON_DEPTH, + MAX_RENDER_DEPTH: () => MAX_RENDER_DEPTH, + Profile: () => Profile, + ProfileViolationError: () => ProfileViolationError, + RenderDepthError: () => RenderDepthError, + SMART_PUNCTUATION_GLYPHS: () => SMART_PUNCTUATION_GLYPHS, + SMART_QUOTE_LOCALES: () => SMART_QUOTE_LOCALES, + SPEC_VERSION: () => SPEC_VERSION, + SourceUnspellableError: () => SourceUnspellableError, + abc: () => abc, + applyAstPatch: () => applyAstPatch, + applyMigrationFixes: () => applyMigrationFixes, + applyProfile: () => applyProfile, + autolink: () => autolink, + bbcodeToCarve: () => bbcodeToCarve, + buildMarker: () => buildMarker, + canonicalType: () => canonicalType, + carveToAnsi: () => carveToAnsi, + carveToAstJson: () => carveToAstJson, + carveToCarve: () => carveToCarve, + carveToHtml: () => carveToHtml, + carveToMarkdown: () => carveToMarkdown, + carveToPlainText: () => carveToPlainText, + chart: () => chart, + checkPortability: () => checkPortability, + citations: () => citations, + codeCallouts: () => codeCallouts, + codeGroup: () => codeGroup, + colorSwatch: () => colorSwatch, + compareSpecVersions: () => compareSpecVersions, + createAstPatch: () => createAstPatch, + d2: () => d2, + defaultAttributes: () => defaultAttributes, + details: () => details, + diffAst: () => diffAst, + djotMigrationWarnings: () => djotMigrationWarnings, + externalLinks: () => externalLinks, + fencedRender: () => fencedRender, + formatChanges: () => formatChanges, + formatLintWarnings: () => formatLintWarnings, + formatMigrationWarnings: () => formatMigrationWarnings, + formatProfileViolation: () => formatProfileViolation, + fromAstJson: () => fromAstJson, + glossary: () => glossary, + graphviz: () => graphviz, + headingLevelShift: () => headingLevelShift, + headingNumbers: () => headingNumbers, + headingPermalinks: () => headingPermalinks, + headingReference: () => headingReference, + htmlToAst: () => htmlToAst, + htmlToCarve: () => htmlToCarve, + imgFence: () => imgFence, + index: () => index, + isSmartQuoteLocaleSupported: () => isSmartQuoteLocaleSupported, + lintCarve: () => lintCarve, + listTable: () => listTable, + markdownToCarve: () => markdownToCarve, + mathBlock: () => mathBlock, + mergeAst: () => mergeAst, + mermaid: () => mermaid, + needsReview: () => needsReview, + normalizeHtml: () => normalizeHtml, + parse: () => parse2, + parseWithSourceLayout: () => parseWithSourceLayout, + plantuml: () => plantuml, + presets: () => presets, + readStamp: () => readStamp, + renderAnsi: () => renderAnsi2, + renderCarve: () => renderCarve2, + renderHtml: () => renderHtml2, + renderMarkdown: () => renderMarkdown2, + renderPlainText: () => renderPlainText2, + resolve: () => resolve, + sanitizeSvg: () => sanitizeSvg, + semanticSpan: () => semanticSpan, + smartQuoteLocales: () => smartQuoteLocales, + smartQuotes: () => smartQuotes, + spoiler: () => spoiler, + stampCarve: () => stampCarve, + stripTrailingMarker: () => stripTrailingMarker, + tabNormalize: () => tabNormalize, + tableOfContents: () => tableOfContents, + tabs: () => tabs, + toAstJson: () => toAstJson, + toSourceLayout: () => toSourceLayout, + tocPlacement: () => tocPlacement, + vegaLite: () => vegaLite, + wavedrom: () => wavedrom, + wikilinks: () => wikilinks +}); +function enforceProfileMaxLength(source, opts) { + const profile = opts.profile; + if (!profile) + return; + const maxLength = profile.getMaxLength(); + if (maxLength > 0 && byteLength(source) > maxLength) { + throw new RangeError(`Input exceeds the profile's maximum length of ${maxLength} bytes (got ${byteLength(source)} bytes).`); + } +} +function runProfile(doc, opts) { + const profile = opts.profile; + if (!profile) + return doc; + return applyProfile(doc, profile, opts.profileBaseHost ?? null).doc; +} +function byteLength(s) { + return new TextEncoder().encode(s).length; +} +function parse2(source, opts = {}) { + const doc = parse(source, opts); + promoteBlockImages(doc.children, true); + if (doc.footnoteDefs) { + for (const body of Object.values(doc.footnoteDefs)) + promoteBlockImages(body, true); + } + doc.children = promoteCitationDefinitions(doc.children); + return doc; +} +function parseWithSourceLayout(source, opts = {}) { + const ast = toAstJson(parse2(source, opts)); + return { ast, layout: toSourceLayout(source, ast) }; +} +function renderHtml2(ast, opts = {}) { + return renderHtml(adoptBlockFootnoteDefs(ast), opts); +} +function renderMarkdown2(ast, opts = {}) { + return renderMarkdown(adoptBlockFootnoteDefs(ast), opts); +} +function renderCarve2(ast, opts = {}) { + return renderCarve(adoptBlockFootnoteDefs(ast), opts); +} +function renderPlainText2(ast, opts = {}) { + return renderPlainText(adoptBlockFootnoteDefs(ast), opts); +} +function renderAnsi2(ast, opts = {}) { + return renderAnsi(adoptBlockFootnoteDefs(ast), opts); +} +function resolve(doc, opts = {}) { + const resolved = resolveHeadingIds(doc, headingIdSlugOpts(opts)); + numberFootnotes(resolved); + return coalesceTextRuns(resolved); +} +function carveToHtml(source, opts = {}) { + enforceProfileMaxLength(source, opts); + const exts = opts.extensions ?? []; + const parseOpts = { + ...opts, + extensions: exts, + ...opts.sourceLine ? { positions: true } : {} + }; + let doc = applyTransforms(resolve(parse2(source, parseOpts), { + asciiHeadingIds: opts.asciiHeadingIds ?? false, + lowercaseHeadingIds: opts.lowercaseHeadingIds ?? false + }), exts, opts, true); + doc = runProfile(doc, opts); + return renderHtml2(doc, opts); +} +function applyTransforms(doc, exts, opts, targetIsHtml) { + if (!exts) + return doc; + let out = doc; + for (const ext of exts) + if (ext.afterParse) + out = ext.afterParse(out); + const options = Object.freeze({ ...opts }); + const mode = targetIsHtml ? opts.mode ?? "interactive" : "interactive"; + const ctx = Object.freeze({ + options, + mode, + isStatic: mode === "static", + targetIsHtml + }); + for (const ext of exts) + if (ext.beforeRender) + out = ext.beforeRender(out, ctx); + return out; +} +function carveToAstJson(source, opts = {}) { + enforceProfileMaxLength(source, opts); + const exts = opts.extensions ?? []; + let doc = applyTransforms( + resolve(parse2(source, { ...opts, extensions: exts, positions: true }), { + asciiHeadingIds: opts.asciiHeadingIds ?? false, + lowercaseHeadingIds: opts.lowercaseHeadingIds ?? false + }), + exts, + opts, + // The exchange shape is not HTML. A hook that emits HTML must leave the + // source node alone here, exactly as it does for Markdown/plain/ANSI. + false + ); + doc = runProfile(doc, opts); + return toAstJson(doc); +} +function carveToMarkdown(source, opts = {}) { + enforceProfileMaxLength(source, opts); + let doc = applyTransforms(resolve(parse2(source, opts), { + asciiHeadingIds: opts.asciiHeadingIds ?? false, + lowercaseHeadingIds: opts.lowercaseHeadingIds ?? false + }), opts.extensions, opts, false); + doc = runProfile(doc, opts); + return renderMarkdown2(doc, opts); +} +function carveToCarve(source, opts = {}) { + const doc = parse2(source, opts); + promoteBlockImages(doc.children, true); + if (doc.footnoteDefs) { + for (const body of Object.values(doc.footnoteDefs)) + promoteBlockImages(body, true); + } + return renderCarve2(doc, opts); +} +function carveToPlainText(source, opts = {}) { + enforceProfileMaxLength(source, opts); + let doc = applyTransforms(resolve(parse2(source, opts), { + asciiHeadingIds: opts.asciiHeadingIds ?? false, + lowercaseHeadingIds: opts.lowercaseHeadingIds ?? false + }), opts.extensions, opts, false); + doc = runProfile(doc, opts); + return renderPlainText2(doc, opts); +} +function carveToAnsi(source, opts = {}) { + enforceProfileMaxLength(source, opts); + let doc = applyTransforms(resolve(parse2(source, opts), { + asciiHeadingIds: opts.asciiHeadingIds ?? false, + lowercaseHeadingIds: opts.lowercaseHeadingIds ?? false + }), opts.extensions, opts, false); + doc = runProfile(doc, opts); + return renderAnsi2(doc, opts); +} +var init_dist2 = __esm({ + "node_modules/@markup-carve/carve/dist/index.js"() { + init_parse(); + init_heading_ids(); + init_citations(); + init_footnote_numbering(); + init_profile_filter(); + init_render_html(); + init_render_markdown(); + init_render_carve(); + init_render_plain(); + init_render_ansi(); + init_legacy_nodes(); + init_ast_json(); + init_coalesce_text_runs(); + init_source_layout(); + init_ast(); + init_html_import(); + init_source_layout(); + init_diff(); + init_ast_patch(); + init_merge(); + init_portability(); + init_ast_json(); + init_render_depth(); + init_source_unspellable_error(); + init_djot_migrate(); + init_bbcode_migrate(); + init_markdown_migrate(); + init_lint(); + init_tab_normalize(); + init_details(); + init_semantic_span(); + init_list_table(); + init_glossary(); + init_heading_numbers(); + init_code_callouts(); + init_smart_quotes(); + init_index_terms(); + init_citations(); + init_fenced_render(); + init_svg_fence(); + init_svg_sanitize(); + init_math_block(); + init_spoiler(); + init_color_swatch(); + init_wikilinks(); + init_autolink(); + init_external_links(); + init_table_of_contents(); + init_heading_permalinks(); + init_code_group(); + init_tabs(); + init_heading_level_shift(); + init_heading_reference(); + init_default_attributes(); + init_profile(); + init_profile_filter(); + init_stamp(); + init_version(); + } +}); + +// dist/server.js +var import_node12 = __toESM(require_node3(), 1); + +// node_modules/vscode-languageserver-textdocument/lib/esm/main.js +var FullTextDocument = class _FullTextDocument { + constructor(uri, languageId, version, content) { + this._uri = uri; + this._languageId = languageId; + this._version = version; + this._content = content; + this._lineOffsets = void 0; + } + get uri() { + return this._uri; + } + get languageId() { + return this._languageId; + } + get version() { + return this._version; + } + getText(range) { + if (range) { + const start = this.offsetAt(range.start); + const end = this.offsetAt(range.end); + return this._content.substring(start, end); + } + return this._content; + } + update(changes, version) { + for (const change2 of changes) { + if (_FullTextDocument.isIncremental(change2)) { + const range = getWellformedRange(change2.range); + const startOffset = this.offsetAt(range.start); + const endOffset = this.offsetAt(range.end); + this._content = this._content.substring(0, startOffset) + change2.text + this._content.substring(endOffset, this._content.length); + const startLine = Math.max(range.start.line, 0); + const endLine = Math.max(range.end.line, 0); + let lineOffsets = this._lineOffsets; + const addedLineOffsets = computeLineOffsets(change2.text, false, startOffset); + if (endLine - startLine === addedLineOffsets.length) { + for (let i = 0, len = addedLineOffsets.length; i < len; i++) { + lineOffsets[i + startLine + 1] = addedLineOffsets[i]; + } + } else { + if (addedLineOffsets.length < 1e4) { + lineOffsets.splice(startLine + 1, endLine - startLine, ...addedLineOffsets); + } else { + this._lineOffsets = lineOffsets = lineOffsets.slice(0, startLine + 1).concat(addedLineOffsets, lineOffsets.slice(endLine + 1)); + } + } + const diff = change2.text.length - (endOffset - startOffset); + if (diff !== 0) { + for (let i = startLine + 1 + addedLineOffsets.length, len = lineOffsets.length; i < len; i++) { + lineOffsets[i] = lineOffsets[i] + diff; + } + } + } else if (_FullTextDocument.isFull(change2)) { + this._content = change2.text; + this._lineOffsets = void 0; + } else { + throw new Error("Unknown change event received"); + } + } + this._version = version; + } + getLineOffsets() { + if (this._lineOffsets === void 0) { + this._lineOffsets = computeLineOffsets(this._content, true); + } + return this._lineOffsets; + } + positionAt(offset) { + offset = Math.max(Math.min(offset, this._content.length), 0); + const lineOffsets = this.getLineOffsets(); + let low = 0, high = lineOffsets.length; + if (high === 0) { + return { line: 0, character: offset }; + } + while (low < high) { + const mid = Math.floor((low + high) / 2); + if (lineOffsets[mid] > offset) { + high = mid; + } else { + low = mid + 1; + } + } + const line2 = low - 1; + offset = this.ensureBeforeEOL(offset, lineOffsets[line2]); + return { line: line2, character: offset - lineOffsets[line2] }; + } + offsetAt(position) { + const lineOffsets = this.getLineOffsets(); + if (position.line >= lineOffsets.length) { + return this._content.length; + } else if (position.line < 0) { + return 0; + } + const lineOffset = lineOffsets[position.line]; + if (position.character <= 0) { + return lineOffset; + } + const nextLineOffset = position.line + 1 < lineOffsets.length ? lineOffsets[position.line + 1] : this._content.length; + const offset = Math.min(lineOffset + position.character, nextLineOffset); + return this.ensureBeforeEOL(offset, lineOffset); + } + ensureBeforeEOL(offset, lineOffset) { + while (offset > lineOffset && isEOL(this._content.charCodeAt(offset - 1))) { + offset--; + } + return offset; + } + get lineCount() { + return this.getLineOffsets().length; + } + static isIncremental(event) { + const candidate = event; + return candidate !== void 0 && candidate !== null && typeof candidate.text === "string" && candidate.range !== void 0 && (candidate.rangeLength === void 0 || typeof candidate.rangeLength === "number"); + } + static isFull(event) { + const candidate = event; + return candidate !== void 0 && candidate !== null && typeof candidate.text === "string" && candidate.range === void 0 && candidate.rangeLength === void 0; + } +}; +var TextDocument; +(function(TextDocument2) { + function create(uri, languageId, version, content) { + return new FullTextDocument(uri, languageId, version, content); + } + TextDocument2.create = create; + function update(document, changes, version) { + if (document instanceof FullTextDocument) { + document.update(changes, version); + return document; + } else { + throw new Error("TextDocument.update: document must be created by TextDocument.create"); + } + } + TextDocument2.update = update; + function applyEdits(document, edits) { + const text = document.getText(); + const sortedEdits = mergeSort(edits.map(getWellformedEdit), (a, b) => { + const diff = a.range.start.line - b.range.start.line; + if (diff === 0) { + return a.range.start.character - b.range.start.character; + } + return diff; + }); + let lastModifiedOffset = 0; + const spans = []; + for (const e of sortedEdits) { + const startOffset = document.offsetAt(e.range.start); + if (startOffset < lastModifiedOffset) { + throw new Error("Overlapping edit"); + } else if (startOffset > lastModifiedOffset) { + spans.push(text.substring(lastModifiedOffset, startOffset)); + } + if (e.newText.length) { + spans.push(e.newText); + } + lastModifiedOffset = document.offsetAt(e.range.end); + } + spans.push(text.substr(lastModifiedOffset)); + return spans.join(""); + } + TextDocument2.applyEdits = applyEdits; +})(TextDocument || (TextDocument = {})); +function mergeSort(data, compare) { + if (data.length <= 1) { + return data; + } + const p = data.length / 2 | 0; + const left = data.slice(0, p); + const right = data.slice(p); + mergeSort(left, compare); + mergeSort(right, compare); + let leftIdx = 0; + let rightIdx = 0; + let i = 0; + while (leftIdx < left.length && rightIdx < right.length) { + const ret = compare(left[leftIdx], right[rightIdx]); + if (ret <= 0) { + data[i++] = left[leftIdx++]; + } else { + data[i++] = right[rightIdx++]; + } + } + while (leftIdx < left.length) { + data[i++] = left[leftIdx++]; + } + while (rightIdx < right.length) { + data[i++] = right[rightIdx++]; + } + return data; +} +function computeLineOffsets(text, isAtLineStart, textOffset = 0) { + const result = isAtLineStart ? [textOffset] : []; + for (let i = 0; i < text.length; i++) { + const ch = text.charCodeAt(i); + if (isEOL(ch)) { + if (ch === 13 && i + 1 < text.length && text.charCodeAt(i + 1) === 10) { + i++; + } + result.push(textOffset + i + 1); + } + } + return result; +} +function isEOL(char) { + return char === 13 || char === 10; +} +function getWellformedRange(range) { + const start = range.start; + const end = range.end; + if (start.line > end.line || start.line === end.line && start.character > end.character) { + return { start: end, end: start }; + } + return range; +} +function getWellformedEdit(textEdit) { + const range = getWellformedRange(textEdit.range); + if (range !== textEdit.range) { + return { newText: textEdit.newText, range }; + } + return textEdit; +} + +// dist/server.js +init_dist2(); + +// dist/analyze.js +var import_node2 = __toESM(require_node3(), 1); +init_dist2(); +var import_node_path = __toESM(require("node:path"), 1); +var import_node_url = require("node:url"); + +// dist/inline-text.js +function smartPunctuationText(node) { + if (typeof node !== "object" || node === null) + return ""; + const candidate = node; + if (candidate.type !== "smart_punctuation") + return ""; + if (typeof candidate.glyph === "string") + return candidate.glyph; + return typeof candidate.value === "string" ? candidate.value : ""; +} + +// dist/captions.js +function captionTargets(doc) { + const targets = []; + collect(doc.children, targets); + return targets; +} +function captionTargetById(doc, id) { + const wanted = id.toLowerCase(); + return captionTargets(doc).find((target) => target.id.toLowerCase() === wanted) ?? null; +} +function panelLetter2(index2) { + let out = ""; + let n = index2; + do { + out = String.fromCharCode(97 + n % 26) + out; + n = Math.floor(n / 26) - 1; + } while (n >= 0); + return out; +} +function collect(nodes, targets) { + for (const node of nodes) { + if (node.type === "figure_group") { + const groupText = captionRefText(node.caption); + pushTarget(targets, node, "composite figure", groupText); + collectPanels(node, groupText, targets); + continue; + } + if (node.type === "figure") { + pushTarget(targets, node, "figure", captionRefText(node.caption)); + } else if (node.type === "table") { + pushTarget(targets, node, "table", captionRefText(node.caption)); + } + if ("children" in node && Array.isArray(node.children)) { + collect(node.children.filter(isBlockNode2), targets); + } + if (node.type === "figure" && isBlockNode2(node.target)) { + collect([node.target], targets); + } + } +} +function collectPanels(group, groupText, targets) { + let panelIndex = 0; + for (const child of group.children) { + const isPanel2 = child.type === "figure" || child.type === "table"; + if (isPanel2) { + pushTarget(targets, child, "panel", groupText === null ? null : `${groupText}${panelLetter2(panelIndex)}`); + panelIndex++; + if (child.type === "figure" && isBlockNode2(child.target)) + collect([child.target], targets); + if ("children" in child && Array.isArray(child.children)) { + collect(child.children.filter(isBlockNode2), targets); + } + continue; + } + collect([child], targets); + } +} +function pushTarget(targets, node, kind2, text) { + const id = node.attrs?.id; + if (!id) + return; + targets.push({ id, kind: kind2, text, pos: node.pos }); +} +function captionRefText(caption) { + if (!caption) + return null; + let out = ""; + for (const node of caption) { + if (node.type === "caption_number") { + const n = node.n; + if (typeof n !== "number") + return null; + return `${out}${n}`.trim(); + } + out += plainText([node]); + } + return null; +} +function plainText(nodes) { + let out = ""; + for (const node of nodes) { + if (node.type === "text") + out += node.value; + else if ("children" in node && Array.isArray(node.children)) { + out += plainText(node.children); + } else if (node.type === "code") + out += node.value; + else if (node.type === "literal_inline") + out += node.content; + else + out += smartPunctuationText(node); + } + return out; +} +function isBlockNode2(node) { + return Boolean(node && typeof node === "object" && "type" in node); +} + +// dist/include-directive.js +var DIRECTIVE_SCAN_RE = /\{\{\s+(?:"((?:\\.|[^"\\])*)"|\u201c([^\u201d]*)\u201d|([^#@}\s"\u201c]+))((?:\s+#[A-Za-z_][\w-]*)?)(.*?)\s+\}\}/g; +var DIRECTIVE_FULL_RE = /^\{\{\s+(?:"((?:\\.|[^"\\])*)"|\u201c([^\u201d]*)\u201d|([^#@}\s"\u201c]+))((?:\s+#[A-Za-z_][\w-]*)?)(.*?)\s+\}\}$/; +var OPTION_RE = /^@([A-Za-z_][\w-]*):([^#@}\s]+)$/; +function unescapeQuotedPath(value) { + return value.replace(/\\(["\\])/g, "$1"); +} +function parseDirective(raw, onInvalidOption) { + const m = DIRECTIVE_FULL_RE.exec(raw); + if (!m) + return null; + const includePath = m[1] !== void 0 ? unescapeQuotedPath(m[1]) : m[2] ?? m[3]; + if (includePath === "") + return null; + const sectionPart = m[4]?.trim(); + const section = sectionPart ? sectionPart.slice(1) : void 0; + let lines; + let shift = 0; + const rest = m[5]?.trim(); + if (rest) { + for (const part of rest.split(/\s+/)) { + const opt = OPTION_RE.exec(part); + const invalid = () => { + if (part.startsWith("@")) + onInvalidOption?.(part); + return null; + }; + if (!opt) + return invalid(); + const [, key2, value] = opt; + if (key2 === "lines") { + const lm = /^([1-9]\d*)-([1-9]\d*)$/.exec(value); + if (!lm) + return invalid(); + lines = { start: Number(lm[1]), end: Number(lm[2]) }; + if (lines.end < lines.start) + return invalid(); + } else if (key2 === "shift") { + if (value === "auto") + shift = "auto"; + else if (!/^[+-]?\d+$/.test(value)) + return invalid(); + else + shift = Number(value); + } else { + return invalid(); + } + } + } + const directive = { raw, path: includePath, shift }; + if (section !== void 0) + directive.section = section; + if (lines !== void 0) + directive.lines = lines; + return directive; +} +function verbatimSpans(source) { + const spans = []; + let offset = 0; + let fence = null; + for (const line2 of source.split("\n")) { + const lineStart = offset; + const lineEnd = offset + line2.length; + offset = lineEnd + 1; + if (fence) { + const close = /^ {0,3}(`{3,}|~{3,})[ \t]*$/.exec(line2); + if (close && close[1][0] === fence.char && close[1].length >= fence.length) { + spans.push({ start: fence.start, end: lineEnd }); + fence = null; + } + continue; + } + const open = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line2); + if (open && !(open[1][0] === "`" && open[2].includes("`"))) { + fence = { char: open[1][0], length: open[1].length, start: lineStart }; + continue; + } + const runs = /`+/g; + let openRun = null; + for (let m = runs.exec(line2); m; m = runs.exec(line2)) { + if (!openRun) { + openRun = { index: m.index, length: m[0].length }; + continue; + } + if (m[0].length === openRun.length) { + spans.push({ start: lineStart + openRun.index, end: lineStart + m.index + m[0].length }); + openRun = null; + } + } + } + if (fence) + spans.push({ start: fence.start, end: source.length }); + return spans; +} +function findDirectives(source, onInvalidOption) { + const shielded = verbatimSpans(source); + const inVerbatim = (index2) => shielded.some((span2) => index2 >= span2.start && index2 < span2.end); + const re = new RegExp(DIRECTIVE_SCAN_RE.source, "g"); + const found = []; + for (let m = re.exec(source); m; m = re.exec(source)) { + const start = m.index; + const end = start + m[0].length; + if (inVerbatim(start)) + continue; + const parsed = parseDirective(m[0], (part) => onInvalidOption?.(part, start, end)); + if (!parsed) + continue; + found.push({ ...parsed, start, end }); + } + return found; +} + +// dist/includes.js +var MIN_BUDGET = 1024 * 1024; +var DEFAULT_MAX_DEPTH = 16; +function lineStarts(source) { + const starts = [0]; + for (let i = 0; i < source.length; i += 1) { + if (source[i] === "\n") + starts.push(i + 1); + } + return starts; +} +function locate2(state, offset) { + let low = 0; + let high = state.lineStarts.length - 1; + while (low < high) { + const mid = low + high + 1 >> 1; + if (state.lineStarts[mid] <= offset) + low = mid; + else + high = mid - 1; + } + return { line: low + 1, column: offset - state.lineStarts[low] + 1 }; +} +function warn(state, rule, message, at, file, detail) { + const warning = { + ...locate2(state, at.start), + rule, + message, + start: at.start, + end: at.end + }; + if (file !== void 0) + warning.file = file; + if (detail !== void 0) + warning.detail = detail; + state.warnings.push(warning); +} +function note(state, id, resolved, watch) { + const key2 = watch ?? id; + const previous = state.dependencies.get(key2); + if (!previous || resolved) { + state.dependencies.set(key2, { + id, + resolved, + ...watch === void 0 ? {} : { watch } + }); + } else if (previous.watch === void 0 && watch !== void 0) { + previous.watch = watch; + } +} +function visit3(state, text, file, stack, depth, anchor) { + const directives = findDirectives(text, (part, start, end) => { + warn(state, "include-unknown-option", `Unknown include option "${part}".`, anchor ?? { start, end }, file); + }); + for (const directive of directives) { + const at = anchor ?? { start: directive.start, end: directive.end }; + if (depth >= state.maxDepth) { + note(state, directive.path, false); + warn(state, "include-depth", `Include depth limit of ${state.maxDepth} exceeded for "${directive.path}".`, at, file); + continue; + } + if (state.usedBytes >= state.maxBytes) { + warn(state, "include-budget", `Include byte budget exceeded by "${directive.path}".`, at, file); + continue; + } + let resolved; + try { + resolved = state.resolver(directive.path, { + stack: [...stack], + depth, + ...state.sourcePath !== void 0 ? { sourcePath: state.sourcePath } : {} + }); + } catch (error) { + note(state, directive.path, false); + warn(state, "include-unresolved", `Include "${directive.path}" could not be resolved.`, at, file, error instanceof Error ? error.message : String(error)); + continue; + } + if (!resolved.ok) { + note(state, resolved.id, false, resolved.watch); + warn(state, "include-unresolved", `Include "${directive.path}" could not be resolved.`, at, file, resolved.denial); + continue; + } + note(state, resolved.id, true, resolved.watch); + if (stack.includes(resolved.id)) { + warn(state, "include-cycle", `Include cycle detected for "${directive.path}".`, at, file); + continue; + } + state.usedBytes += resolved.bytes; + if (state.usedBytes > state.maxBytes) { + warn(state, "include-budget", `Include byte budget exceeded by "${directive.path}".`, at, file); + continue; + } + if (!state.documents.has(resolved.id)) { + state.documents.set(resolved.id, { + source: resolved.source, + ...resolved.version === void 0 ? {} : { version: resolved.version } + }); + } + visit3(state, resolved.source, resolved.id, [...stack, resolved.id], depth + 1, at); + } +} +function resolveIncludes(source, options = {}) { + if (!options.resolver) + return { warnings: [], dependencies: [], bytes: 0, documents: [] }; + const normalized = source.replace(/\r\n?/g, "\n"); + const state = { + resolver: options.resolver, + sourcePath: options.sourcePath, + maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH, + maxBytes: options.maxBytes ?? Math.max(MIN_BUDGET, Buffer.byteLength(normalized, "utf8") * 8), + usedBytes: 0, + warnings: [], + dependencies: /* @__PURE__ */ new Map(), + documents: /* @__PURE__ */ new Map(), + lineStarts: lineStarts(normalized) + }; + const rootStack = options.sourcePath !== void 0 ? [options.sourcePath] : []; + visit3(state, normalized, options.sourcePath, rootStack, 0, null); + return { + warnings: state.warnings, + dependencies: [...state.dependencies.values()], + bytes: state.usedBytes, + documents: [...state.documents].map(([id, child]) => ({ id, ...child })) + }; +} + +// dist/table-diagnostics.js +var import_node = __toESM(require_node3(), 1); +function tableDiagnostics(source) { + const diagnostics2 = []; + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + for (let line2 = 0; line2 < lines.length; line2 += 1) { + const text = lines[line2]; + if (!/^\s*\|/.test(text)) + continue; + for (const match of text.matchAll(/\|=?[<>~^v]{1,2}(?=\S)/g)) { + diagnostics2.push(diagnostic("table-alignment-run-padding", import_node.DiagnosticSeverity.Warning, line2, match.index, match.index + match[0].length, "A table alignment run needs a terminating space; this spelling is literal content.")); + } + if (line2 > 0 && /^\s*\|/.test(lines[line2 - 1] ?? "")) + continue; + let end = line2; + while (end + 1 < lines.length && /^\s*\|/.test(lines[end + 1] ?? "")) + end += 1; + const columns = Math.max(...lines.slice(line2, end + 1).map(columnCount), 0); + const attrLine = lines[line2 - 1] ?? ""; + const attrs = positionalAttributes(attrLine); + for (const attr of attrs) { + if (attr.values.length > columns) { + diagnostics2.push(diagnostic("table-column-arity", import_node.DiagnosticSeverity.Error, line2 - 1, attr.start, attr.end, `${attr.name} has ${attr.values.length} entries for a ${columns}-column table.`)); + } else if (attr.values.length < columns) { + diagnostics2.push(diagnostic("table-column-arity", import_node.DiagnosticSeverity.Warning, line2 - 1, attr.start, attr.end, `${attr.name} leaves ${columns - attr.values.length} trailing column(s) unset.`)); + } + if (attr.name === "widths") { + const total = attr.values.reduce((sum, value) => sum + (Number(value) || 0), 0); + if (total > 100) + diagnostics2.push(diagnostic("table-width-total", import_node.DiagnosticSeverity.Warning, line2 - 1, attr.start, attr.end, `Column widths total ${total}%, overcommitting the table.`)); + } + } + const aligns = attrs.find((attr) => attr.name === "aligns"); + if (aligns && /\|=?[<>~>]/.test(text)) { + diagnostics2.push(diagnostic("table-column-overlap", import_node.DiagnosticSeverity.Warning, line2 - 1, aligns.start, aligns.end, "An in-table horizontal alignment marker overrides this table attribute.")); + } + line2 = end; + } + return diagnostics2; +} +function columnCount(line2) { + const pipes = [...line2.matchAll(/(? name === "semantic-span" ? { name, semanticSpanNames: ["samp", "var", "cite", "dfn"] } : { name }); + for (const warning of lintCarve(source, { + platforms: options.lint?.platforms, + extensions: lintExtensions + })) { + const len = Math.max(1, warning.end - warning.start); + const diagnostic2 = { + severity: import_node2.DiagnosticSeverity.Warning, + range: { + start: { line: warning.line - 1, character: warning.column - 1 }, + end: { line: warning.line - 1, character: warning.column - 1 + len } + }, + source: "carve", + code: warning.rule, + message: warning.message + }; + const related = options.uri ? firstDuplicateDeclaration(source, warning.rule, warning.message, warning.line - 1) : null; + if (options.uri && related) + diagnostic2.relatedInformation = [{ + location: { uri: options.uri, range: related }, + message: "First declaration is here." + }]; + diagnostics2.push(diagnostic2); + } + diagnostics2.push(...tableDiagnostics(source)); + const includes = resolveIncludes(norm, options.includes ?? {}); + for (const warning of includes.warnings) { + diagnostics2.push({ + severity: import_node2.DiagnosticSeverity.Warning, + range: { + start: positionAt(norm, warning.start), + end: positionAt(norm, warning.end) + }, + source: "carve", + code: warning.rule, + // `warning.detail` is deliberately not folded in: §19 I7 keeps the + // failure class out of author-visible text so a denial cannot be used + // to probe host layout. The attributed child is named relative to the + // include root for the same reason - never as an absolute path. + message: attributeToChild(warning.message, warning.file, options.includes) + }); + } + return { + diagnostics: configuredDiagnostics(diagnostics2, options.lint?.severities), + symbols: doc ? documentSymbols(doc) : tolerantHeadingSymbols(source), + dependencies: includes.dependencies, + includedSymbols: includedSymbols(includes.documents, options.includedParseCache) + }; +} +function configuredDiagnostics(diagnostics2, overrides) { + if (!overrides) + return diagnostics2; + const levels = { + error: import_node2.DiagnosticSeverity.Error, + warning: import_node2.DiagnosticSeverity.Warning, + information: import_node2.DiagnosticSeverity.Information, + hint: import_node2.DiagnosticSeverity.Hint + }; + return diagnostics2.flatMap((diagnostic2) => { + const configured = diagnostic2.code === void 0 ? void 0 : overrides[String(diagnostic2.code)]; + if (!configured) + return [diagnostic2]; + if (configured === "off") + return []; + return [{ ...diagnostic2, severity: levels[configured] }]; + }); +} +function parseErrorRange(source, message) { + const located = /(?:line|at)\s+(\d+)(?::|,\s*column\s+)(\d+)/i.exec(message); + if (!located) + return rangeAt(source, 0, 1); + const line2 = Math.max(0, Number(located[1]) - 1); + const character = Math.max(0, Number(located[2]) - 1); + return { start: { line: line2, character }, end: { line: line2, character: character + 1 } }; +} +function tolerantHeadingSymbols(source) { + const symbols = []; + for (const [line2, text] of source.replace(/\r\n?/g, "\n").split("\n").entries()) { + const match = /^(#{1,6}) (.+)$/.exec(text); + if (!match) + continue; + const range = { start: { line: line2, character: 0 }, end: { line: line2, character: text.length } }; + symbols.push({ name: match[2], kind: import_node2.SymbolKind.String, range, selectionRange: range }); + } + return symbols; +} +function firstDuplicateDeclaration(source, rule, message, repeatedLine) { + const headingKey = rule === "duplicate-heading-id" ? /heading id "([^"]+)"/.exec(message)?.[1] : void 0; + const footnoteKey = rule === "duplicate-footnote-definition" ? /\[\^([^\]]+)\]/.exec(message)?.[1] : void 0; + const key2 = headingKey ?? footnoteKey; + if (!key2) + return null; + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + const declarations = []; + for (let line2 = 0; line2 < lines.length; line2 += 1) { + const text = lines[line2]; + const match = headingKey ? /^\{[^}]*#([^\s}]+)[^}]*\}\s*$/.exec(text) : /^(?: {0,3})\[\^([^\]]+)\]:/.exec(text); + if (!match || match[1].toLocaleLowerCase() !== key2.toLocaleLowerCase()) + continue; + const character = text.indexOf(match[1]); + if (line2 >= repeatedLine - 1) + break; + declarations.push({ + start: { line: line2, character }, + end: { line: line2, character: character + match[1].length } + }); + } + return declarations[0] ?? null; +} +function includedSymbols(documents2, cache) { + const symbols = []; + for (const child of documents2) { + let document = child.version === void 0 ? void 0 : cache?.get(child.id, child.version); + if (!document) { + try { + document = resolve(parse2(child.source)); + } catch { + continue; + } + if (child.version !== void 0) + cache?.set(child.id, child.version, document); + } + const uri = (0, import_node_url.pathToFileURL)(child.id).toString(); + for (const entry of walkOutline(document.children)) { + if (entry.type !== "heading") + continue; + const symbol = headingSymbol(entry); + symbols.push({ + name: symbol.name, + kind: symbol.kind, + location: { uri, range: symbol.range }, + containerName: import_node_path.default.basename(child.id) + }); + } + } + return symbols; +} +function attributeToChild(message, file, includes) { + if (file === void 0 || file === includes?.sourcePath) + return message; + return `${message} (in ${relativeToRoot(file, includes?.includeRoot)})`; +} +function relativeToRoot(file, root) { + if (root === void 0) + return file; + const relative = import_node_path.default.relative(root, file); + if (!relative || import_node_path.default.isAbsolute(relative)) + return file; + if (relative.split(import_node_path.default.sep)[0] === "..") + return file; + return relative; +} +function documentSymbols(doc) { + const stack = []; + const roots = []; + const place = (symbol) => { + const parent = stack[stack.length - 1]; + if (parent) { + parent.symbol.children ??= []; + parent.symbol.children.push(symbol); + } else { + roots.push(symbol); + } + }; + for (const entry of walkOutline(doc.children)) { + if (entry.type === "figure_group") { + place(figureGroupSymbol(entry)); + continue; + } + while (stack.length && stack[stack.length - 1].level >= entry.level) { + stack.pop(); + } + const symbol = headingSymbol(entry); + place(symbol); + stack.push({ level: entry.level, symbol }); + } + return roots; +} +function* walkOutline(nodes) { + for (const node of nodes) { + if (node.type === "heading") + yield node; + if (node.type === "figure_group") { + yield node; + yield* walkOutline(node.children); + continue; + } + if ("children" in node && Array.isArray(node.children)) { + yield* walkOutline(node.children.filter(isBlockNode3)); + } + if (node.type === "figure") { + if ("children" in node.target && Array.isArray(node.target.children)) { + yield* walkOutline(node.target.children.filter(isBlockNode3)); + } + } + } +} +function isPanel(node) { + return node.type === "figure" || node.type === "table"; +} +function figureGroupSymbol(group) { + const range = blockRange(group); + const panels = group.children.filter(isPanel); + return { + name: (group.caption ? plainText2(group.caption) : "") || "Composite figure", + detail: panels.length === 1 ? "1 panel" : `${panels.length} panels`, + kind: import_node2.SymbolKind.Struct, + range, + selectionRange: range, + children: panels.map((panel, index2) => panelSymbol(panel, index2)) + }; +} +function panelSymbol(panel, index2) { + const caption = panel.caption; + const range = blockRange(panel); + return { + name: (caption ? plainText2(caption) : "") || `Panel ${panelLetter2(index2)}`, + kind: panel.type === "table" ? import_node2.SymbolKind.Array : import_node2.SymbolKind.Object, + range, + selectionRange: range, + children: [] + }; +} +function blockRange(node) { + if (!node.pos) { + return { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }; + } + return { + start: { line: node.pos.startLine - 1, character: 0 }, + end: { line: node.pos.endLine - 1, character: 200 } + }; +} +function isBlockNode3(node) { + return Boolean(node && typeof node === "object" && "type" in node); +} +function headingSymbol(heading) { + const range = heading.pos ? { + start: { line: heading.pos.startLine - 1, character: 0 }, + end: { line: heading.pos.endLine - 1, character: 200 } + } : { + start: { line: 0, character: 0 }, + end: { line: 0, character: 0 } + }; + return { + name: plainText2(heading.children) || `Heading ${heading.level}`, + kind: import_node2.SymbolKind.String, + range, + selectionRange: range, + children: [] + }; +} +function plainText2(nodes) { + let out = ""; + for (const node of nodes) { if (node.type === "text") out += node.value; else if ("children" in node && Array.isArray(node.children)) { - out += plainText(node.children); + out += plainText2(node.children); } else if (node.type === "code") out += node.value; else if (node.type === "literal_inline") out += node.content; + else if (node.type === "caption_number") + out += String(node.n); else if (node.type === "symbol") out += `:${node.name}:`; else if (node.type === "mention") @@ -14719,25 +42361,222 @@ function plainText(nodes) { } function positionAt(source, offset) { const before = source.slice(0, offset); - const line = before.split("\n").length - 1; + const line2 = before.split("\n").length - 1; const lastNewline = before.lastIndexOf("\n"); return { - line, + line: line2, character: offset - lastNewline - 1 }; } function rangeAt(source, index2, length) { const before = source.slice(0, index2); - const line = before.split("\n").length - 1; + const line2 = before.split("\n").length - 1; const lastNewline = before.lastIndexOf("\n"); const character = index2 - lastNewline - 1; return { - start: { line, character }, - end: { line, character: character + length } + start: { line: line2, character }, + end: { line: line2, character: character + length } + }; +} + +// dist/include-settings.js +var import_node_fs2 = require("node:fs"); +var import_node_path3 = __toESM(require("node:path"), 1); +var import_node_url2 = require("node:url"); + +// dist/include-path.js +var import_node_fs = require("node:fs"); +var import_node_path2 = __toESM(require("node:path"), 1); +var REMOTE_RE = /^(?:[A-Za-z][A-Za-z0-9+.-]*:)?\/\//; +function remoteHost(spec) { + const withScheme = spec.startsWith("//") ? `https:${spec}` : spec; + try { + return new URL(withScheme).hostname; + } catch { + return ""; + } +} +function fileSystemResolver(includeRoot, opts = {}) { + const rootReal = (0, import_node_fs.realpathSync)(includeRoot); + const allowedRemoteHosts = opts.allowedRemoteHosts ?? []; + const contains5 = (candidate) => { + const rel = import_node_path2.default.relative(rootReal, candidate); + if (rel === "") + return true; + if (!rel || import_node_path2.default.isAbsolute(rel)) + return false; + return rel.split(import_node_path2.default.sep)[0] !== ".."; + }; + const missingCandidate = (candidate) => { + let ancestor = import_node_path2.default.dirname(candidate); + const suffix = [import_node_path2.default.basename(candidate)]; + while (ancestor !== import_node_path2.default.dirname(ancestor)) { + try { + const ancestorReal = (0, import_node_fs.realpathSync)(ancestor); + const canonicalCandidate = import_node_path2.default.join(ancestorReal, ...suffix); + return contains5(canonicalCandidate) ? canonicalCandidate : void 0; + } catch { + suffix.unshift(import_node_path2.default.basename(ancestor)); + ancestor = import_node_path2.default.dirname(ancestor); + } + } + return void 0; + }; + return (includePath, ctx) => { + if (REMOTE_RE.test(includePath)) { + const host = remoteHost(includePath); + if (!allowedRemoteHosts.includes(host)) { + return { ok: false, id: includePath, denial: "remote-not-allowed" }; + } + return { ok: false, id: includePath, denial: "remote-not-allowed" }; + } + if (!opts.allowAbsolute && import_node_path2.default.isAbsolute(includePath)) { + return { ok: false, id: includePath, denial: "absolute-denied" }; + } + const parent = ctx.stack[ctx.stack.length - 1]; + const base = parent ? import_node_path2.default.dirname(import_node_path2.default.resolve(rootReal, parent)) : rootReal; + const joined = import_node_path2.default.isAbsolute(includePath) ? includePath : import_node_path2.default.resolve(base, includePath); + let real; + try { + real = (0, import_node_fs.realpathSync)(joined); + } catch { + const watch = missingCandidate(joined); + return watch === void 0 ? { ok: false, id: includePath, denial: "outside-root" } : { ok: false, id: includePath, denial: "not-found", watch }; + } + if (!contains5(real)) { + return { ok: false, id: includePath, denial: "outside-root" }; + } + let fd; + try { + fd = (0, import_node_fs.openSync)(real, "r"); + } catch { + return { ok: false, id: includePath, denial: "not-found" }; + } + try { + const stat = (0, import_node_fs.fstatSync)(fd); + if (!stat.isFile()) + return { ok: false, id: real, denial: "not-a-file" }; + const cached = opts.cache?.get(real, stat.mtimeMs, stat.size); + const version = `${stat.mtimeMs}:${stat.size}`; + if (cached) + return { ok: true, id: real, watch: real, version, ...cached }; + const buffer = Buffer.allocUnsafe(stat.size); + let read = 0; + while (read < stat.size) { + const n = (0, import_node_fs.readSync)(fd, buffer, read, stat.size - read, read); + if (n <= 0) + break; + read += n; + } + const value = { + ok: true, + id: real, + watch: real, + version, + source: buffer.subarray(0, read).toString("utf8"), + // Encoded bytes, not JavaScript characters, so the budget counts what + // the include-bomb actually costs. + bytes: read + }; + opts.cache?.set(real, stat.mtimeMs, stat.size, value); + return value; + } finally { + (0, import_node_fs.closeSync)(fd); + } + }; +} + +// dist/include-settings.js +var DEFAULT_INCLUDE_SETTINGS = { enabled: "auto" }; +function readIncludeSettings(raw) { + const source = raw?.carve?.includes; + if (!source || typeof source !== "object") + return DEFAULT_INCLUDE_SETTINGS; + const enabled = source["enabled"]; + const settings = { + enabled: enabled === "on" || enabled === "off" ? enabled : "auto" }; + if (typeof source["includeRoot"] === "string") + settings.includeRoot = source["includeRoot"]; + if (typeof source["allowAbsolute"] === "boolean") + settings.allowAbsolute = source["allowAbsolute"]; + if (Array.isArray(source["allowedRemoteHosts"])) { + settings.allowedRemoteHosts = source["allowedRemoteHosts"].filter((host) => typeof host === "string"); + } + if (typeof source["maxDepth"] === "number") + settings.maxDepth = source["maxDepth"]; + if (typeof source["maxBytes"] === "number") + settings.maxBytes = source["maxBytes"]; + return settings; +} +function readWorkspaceTrusted(raw) { + return raw?.workspaceTrusted === true; +} +function fsPath(uri) { + if (!uri.startsWith("file:")) + return void 0; + try { + return (0, import_node_url2.fileURLToPath)(uri); + } catch { + return void 0; + } +} +function contains(root, candidate) { + const rel = import_node_path3.default.relative(root, candidate); + if (rel === "") + return true; + if (!rel || import_node_path3.default.isAbsolute(rel)) + return false; + return rel.split(import_node_path3.default.sep)[0] !== ".."; +} +function workspaceRootFor(documentPath, roots) { + let best; + for (const root of roots ?? []) { + if (!contains(root, documentPath)) + continue; + if (best === void 0 || root.length > best.length) + best = root; + } + return best; +} +function includeOptionsFor(input) { + if (input.settings.enabled === "off") + return void 0; + if (input.settings.enabled === "auto" && !input.workspaceTrusted) + return void 0; + const documentPath = fsPath(input.uri); + if (documentPath === void 0) + return void 0; + const configured = input.settings.includeRoot ?? workspaceRootFor(documentPath, input.workspaceRoots) ?? (0, import_node_path3.dirname)(documentPath); + let root; + try { + root = (0, import_node_fs2.realpathSync)(configured); + } catch { + return void 0; + } + let resolver; + try { + resolver = fileSystemResolver(root, { + allowAbsolute: input.settings.allowAbsolute ?? false, + allowedRemoteHosts: input.settings.allowedRemoteHosts ?? [], + ...input.cache === void 0 ? {} : { cache: input.cache } + }); + } catch { + return void 0; + } + const options = { resolver, sourcePath: documentPath, includeRoot: root }; + if (input.settings.maxDepth !== void 0) + options.maxDepth = input.settings.maxDepth; + if (input.settings.maxBytes !== void 0) + options.maxBytes = input.settings.maxBytes; + return options; } +// dist/definition.js +init_dist2(); + // dist/position.js +init_dist2(); function codepointColumnToUtf16(lineText, column) { if (column <= 1) return 0; @@ -14764,15 +42603,18 @@ function sourceLines(source) { var COLUMN_PROBE = "\u{1F600}x"; var CODEPOINT_PROBE_END_COLUMN = 3; var cachedUnit; -function engineColumnUnit() { - if (cachedUnit) - return cachedUnit; +function probeEndColumn() { try { - const endColumn = parse2(COLUMN_PROBE).children[0]?.pos?.endColumn; - cachedUnit = endColumn === CODEPOINT_PROBE_END_COLUMN ? "codepoint" : "utf16"; + return parse2(COLUMN_PROBE).children[0]?.pos?.endColumn; } catch { - cachedUnit = "utf16"; + return void 0; } +} +function engineColumnUnit() { + if (cachedUnit) + return cachedUnit; + const endColumn = probeEndColumn(); + cachedUnit = endColumn === CODEPOINT_PROBE_END_COLUMN ? "codepoint" : "utf16"; return cachedUnit; } function astColumnToCharacter(lineText, column) { @@ -14782,30 +42624,70 @@ function characterToAstColumn(lineText, character) { return engineColumnUnit() === "codepoint" ? utf16CharToCodepointColumn(lineText, character) : character + 1; } +// dist/include-definition.js +var import_node_url3 = require("node:url"); +function includeDefinitionAt(source, position, options) { + if (!options?.resolver) + return null; + const normalized = source.replace(/\r\n?/g, "\n"); + const offset = offsetAt(normalized, position); + const directive = findDirectives(normalized).find((candidate) => offset >= candidate.start && offset < candidate.end); + if (!directive) + return null; + const stack = options.sourcePath === void 0 ? [] : [options.sourcePath]; + const resolved = options.resolver(directive.path, { + stack, + depth: 0, + ...options.sourcePath === void 0 ? {} : { sourcePath: options.sourcePath } + }); + if (!resolved.ok) + return null; + return { + uri: (0, import_node_url3.pathToFileURL)(resolved.id).toString(), + range: { + start: { line: 0, character: 0 }, + end: { line: 0, character: 0 } + } + }; +} +function offsetAt(source, position) { + let offset = 0; + for (let line2 = 0; line2 < position.line; line2 += 1) { + const newline = source.indexOf("\n", offset); + if (newline < 0) + return source.length; + offset = newline + 1; + } + return Math.min(source.length, offset + position.character); +} + // dist/definition.js -function definitionAt(uri, source, position) { +function definitionAt(uri, source, position, includes) { + const included = includeDefinitionAt(source, position, includes); + if (included) + return included; const lines = source.replace(/\r\n?/g, "\n").split("\n"); - const line = lines[position.line] ?? ""; - const citationTarget = resolveCitationAt(lines, line, position); + const line2 = lines[position.line] ?? ""; + const citationTarget = resolveCitationAt(lines, line2, position); if (citationTarget !== null) return locationAtLine(uri, citationTarget); - const crossrefTarget = resolveCrossrefAt(uri, source, line, position); + const crossrefTarget = resolveCrossrefAt(uri, source, line2, position); if (crossrefTarget !== null) return crossrefTarget; - const footnoteTarget = resolveFootnoteAt(lines, line, position); + const footnoteTarget = resolveFootnoteAt(lines, line2, position); if (footnoteTarget !== null) return locationAtLine(uri, footnoteTarget); - const linkrefTarget = resolveLinkrefAt(lines, line, position); + const linkrefTarget = resolveLinkrefAt(lines, line2, position); if (linkrefTarget !== null) return locationAtLine(uri, linkrefTarget); - const wikilinkTarget = resolveWikilinkAt(uri, source, line, position); + const wikilinkTarget = resolveWikilinkAt(uri, source, line2, position); if (wikilinkTarget !== null) return wikilinkTarget; return null; } -function resolveCitationAt(lines, line, position) { +function resolveCitationAt(lines, line2, position) { const citationGroupRe = /\[([^\]]*@[^\]]*)\]/g; - for (const m of line.matchAll(citationGroupRe)) { + for (const m of line2.matchAll(citationGroupRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) @@ -14817,23 +42699,23 @@ function resolveCitationAt(lines, line, position) { const keyAbsEnd = keyAbsStart + km[1].length; if (position.character < start + 1 + km.index || position.character > keyAbsEnd) continue; - const key = km[1]; - return findCitationDef(lines, key); + const key2 = km[1]; + return findCitationDef(lines, key2); } } return null; } -function findCitationDef(lines, key) { - const defRe = new RegExp(`^\\[@${escapeRegExp(key)}\\]:`); +function findCitationDef(lines, key2) { + const defRe = new RegExp(`^\\[@${escapeRegExp(key2)}\\]:`); for (let i = 0; i < lines.length; i++) { if (defRe.test(lines[i])) return i; } return null; } -function resolveCrossrefAt(uri, source, line, position) { +function resolveCrossrefAt(uri, source, line2, position) { const crossrefRe = /<\/#([A-Za-z0-9_.:-]+)>/g; - for (const m of line.matchAll(crossrefRe)) { + for (const m of line2.matchAll(crossrefRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) @@ -14841,7 +42723,7 @@ function resolveCrossrefAt(uri, source, line, position) { return findHeadingById(uri, source, m[1]); } const fragLinkRe = /\[[^\]]*\]\(#([A-Za-z0-9_.:-]+)[^)]*\)/g; - for (const m of line.matchAll(fragLinkRe)) { + for (const m of line2.matchAll(fragLinkRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) @@ -14853,28 +42735,35 @@ function resolveCrossrefAt(uri, source, line, position) { function findHeadingById(uri, source, targetId) { let doc; try { - doc = resolve(parse2(source)); + doc = resolve(parse2(source, { positions: true })); } catch { return null; } const heading = findHeadingWithId(doc.children, targetId.toLowerCase()); - if (!heading || !heading.pos) - return null; - const line = heading.pos.startLine - 1; + if (!heading || !heading.pos) { + return findCaptionById(uri, doc, targetId); + } + const line2 = heading.pos.startLine - 1; return { uri, range: { - start: { line, character: 0 }, + start: { line: line2, character: 0 }, // The heading's end column counts codepoints; the range carries UTF-16 // code units. Without a column at all, 200 stands in for "the whole // line", as it did before. end: { - line, - character: heading.pos.endColumn === void 0 ? 199 : astColumnToCharacter(sourceLines(source)[line] ?? "", heading.pos.endColumn) + line: line2, + character: heading.pos.endColumn === void 0 ? 199 : astColumnToCharacter(sourceLines(source)[line2] ?? "", heading.pos.endColumn) } } }; } +function findCaptionById(uri, doc, targetId) { + const target = captionTargetById(doc, targetId); + if (!target?.pos) + return null; + return locationAtLine(uri, target.pos.startLine - 1); +} function findHeadingWithId(nodes, targetId) { for (const node of nodes) { if (node.type === "heading") { @@ -14883,19 +42772,19 @@ function findHeadingWithId(nodes, targetId) { return node; } if ("children" in node && Array.isArray(node.children)) { - const found = findHeadingWithId(node.children.filter(isBlockNode2), targetId); + const found = findHeadingWithId(node.children.filter(isBlockNode4), targetId); if (found) return found; } } return null; } -function isBlockNode2(node) { +function isBlockNode4(node) { return Boolean(node && typeof node === "object" && "type" in node); } -function resolveFootnoteAt(lines, line, position) { +function resolveFootnoteAt(lines, line2, position) { const fnRefRe = /\[\^([^\]\s]+)\]/g; - for (const m of line.matchAll(fnRefRe)) { + for (const m of line2.matchAll(fnRefRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) @@ -14913,9 +42802,9 @@ function findFootnoteDef(lines, label) { } return null; } -function resolveLinkrefAt(lines, line, position) { +function resolveLinkrefAt(lines, line2, position) { const fullRefRe = /\]\[([^\]^][^\]]*)\]/g; - for (const m of line.matchAll(fullRefRe)) { + for (const m of line2.matchAll(fullRefRe)) { const labelStart = m.index + 2; const labelEnd = labelStart + m[1].length; if (position.character < labelStart || position.character > labelEnd) @@ -14924,7 +42813,7 @@ function resolveLinkrefAt(lines, line, position) { return findLinkrefDef(lines, label); } const collapsedRe = /\[([^\]^][^\]]*)\]\[\]/g; - for (const m of line.matchAll(collapsedRe)) { + for (const m of line2.matchAll(collapsedRe)) { const labelStart = m.index + 1; const labelEnd = labelStart + m[1].length; if (position.character < labelStart || position.character > labelEnd) @@ -14937,8 +42826,8 @@ function resolveLinkrefAt(lines, line, position) { function findLinkrefDef(lines, label) { const normalized = label.replace(/\s+/g, " ").trim(); for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const defMatch = /^( {0,3})\[([^\]]+)\]:/.exec(line); + const line2 = lines[i]; + const defMatch = /^( {0,3})\[([^\]]+)\]:/.exec(line2); if (defMatch && !defMatch[2].startsWith("^")) { const defLabel = defMatch[2].replace(/\s+/g, " ").trim(); if (defLabel === normalized) @@ -14947,9 +42836,9 @@ function findLinkrefDef(lines, label) { } return null; } -function resolveWikilinkAt(uri, source, line, position) { +function resolveWikilinkAt(uri, source, line2, position) { const wikilinkRe = /\[\[([^\]|#]+?)(?:[|#][^\]]*)?]]/g; - for (const m of line.matchAll(wikilinkRe)) { + for (const m of line2.matchAll(wikilinkRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) @@ -14970,17 +42859,17 @@ function findHeadingByText(uri, source, text) { const heading = findHeadingWithText(doc.children, target); if (!heading || !heading.pos) return null; - const line = heading.pos.startLine - 1; + const line2 = heading.pos.startLine - 1; return { uri, range: { - start: { line, character: 0 }, + start: { line: line2, character: 0 }, // The heading's end column counts codepoints; the range carries UTF-16 // code units. Without a column at all, 200 stands in for "the whole // line", as it did before. end: { - line, - character: heading.pos.endColumn === void 0 ? 199 : astColumnToCharacter(sourceLines(source)[line] ?? "", heading.pos.endColumn) + line: line2, + character: heading.pos.endColumn === void 0 ? 199 : astColumnToCharacter(sourceLines(source)[line2] ?? "", heading.pos.endColumn) } } }; @@ -15009,19 +42898,19 @@ function findHeadingWithText(nodes, targetText) { return node; } if ("children" in node && Array.isArray(node.children)) { - const found = findHeadingWithText(node.children.filter(isBlockNode2), targetText); + const found = findHeadingWithText(node.children.filter(isBlockNode4), targetText); if (found) return found; } } return null; } -function locationAtLine(uri, line) { +function locationAtLine(uri, line2) { return { uri, range: { - start: { line, character: 0 }, - end: { line, character: 9999 } + start: { line: line2, character: 0 }, + end: { line: line2, character: 9999 } } }; } @@ -15030,56 +42919,86 @@ function escapeRegExp(value) { } // dist/references.js +init_dist2(); function referencesAt(uri, source, position, context) { const lines = source.replace(/\r\n?/g, "\n").split("\n"); - const line = lines[position.line] ?? ""; - const headingResult = resolveHeadingGroup(uri, source, lines, line, position, context); + const line2 = lines[position.line] ?? ""; + const headingResult = resolveHeadingGroup(uri, source, lines, line2, position, context); if (headingResult) return headingResult; - const footnoteResult = resolveFootnoteGroup(uri, lines, line, position, context); + const footnoteResult = resolveFootnoteGroup(uri, lines, line2, position, context); if (footnoteResult) return footnoteResult; - const citationResult = resolveCitationGroup(uri, lines, line, position, context); + const citationResult = resolveCitationGroup(uri, lines, line2, position, context); if (citationResult) return citationResult; - const linkrefResult = resolveLinkrefGroup(uri, lines, line, position, context); + const linkrefResult = resolveLinkrefGroup(uri, lines, line2, position, context); if (linkrefResult) return linkrefResult; - const wikilinkResult = resolveWikilinkGroup(uri, source, lines, line, position, context); + const wikilinkResult = resolveWikilinkGroup(uri, source, lines, line2, position, context); if (wikilinkResult) return wikilinkResult; + const captionResult = resolveCaptionDeclarationGroup(uri, source, lines, position, context); + if (captionResult) + return captionResult; return null; } -function resolveHeadingGroup(uri, source, lines, line, position, context) { - const headingMatch = /^(#{1,6})\s+/.exec(line); +function resolveHeadingGroup(uri, source, lines, line2, position, context) { + const headingMatch = /^(#{1,6})\s+/.exec(line2); if (headingMatch) { const id = getHeadingId(source, position.line); - if (id) - return collectHeadingRefs(uri, source, lines, id, position.line, context); + if (id) { + return collectRefs(uri, source, lines, id, { line: position.line, kind: "heading" }, context); + } } const crossrefRe = /<\/#([A-Za-z0-9_.:-]+)>/g; - for (const m of line.matchAll(crossrefRe)) { + for (const m of line2.matchAll(crossrefRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) continue; const id = m[1]; - const defLine = findHeadingLineById(source, id); - if (defLine === null) + const declaration = findDeclarationById(source, id); + if (declaration === null) return []; - return collectHeadingRefs(uri, source, lines, id, defLine, context); + return collectRefs(uri, source, lines, id, declaration, context); } const fragLinkRe = /\[[^\]]*\]\(#([A-Za-z0-9_.:-]+)[^)]*\)/g; - for (const m of line.matchAll(fragLinkRe)) { + for (const m of line2.matchAll(fragLinkRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) continue; const id = m[1]; - const defLine = findHeadingLineById(source, id); - if (defLine === null) + const declaration = findDeclarationById(source, id); + if (declaration === null) return []; - return collectHeadingRefs(uri, source, lines, id, defLine, context); + return collectRefs(uri, source, lines, id, declaration, context); + } + return null; +} +function resolveCaptionDeclarationGroup(uri, source, lines, position, context) { + const declared = captionIdDeclaredAt(source, position.line); + if (declared === null) + return null; + const declaration = findDeclarationById(source, declared); + if (declaration === null) + return []; + return collectRefs(uri, source, lines, declared, declaration, context); +} +function captionIdDeclaredAt(source, lineIndex) { + let doc; + try { + doc = resolve(parse2(source, { positions: true })); + } catch { + return null; + } + for (const target of captionTargets(doc)) { + if (!target.pos) + continue; + const hostLine = target.pos.startLine - 1; + if (lineIndex === hostLine || lineIndex === hostLine - 1) + return target.id; } return null; } @@ -15093,29 +43012,32 @@ function getHeadingId(source, lineIndex) { const heading = findHeadingAtLine(doc.children, lineIndex + 1); return heading?.attrs?.id ?? null; } -function findHeadingAtLine(nodes, line) { +function findHeadingAtLine(nodes, line2) { for (const node of nodes) { - if (node.type === "heading" && node.pos?.startLine === line) + if (node.type === "heading" && node.pos?.startLine === line2) return node; if ("children" in node && Array.isArray(node.children)) { - const found = findHeadingAtLine(node.children.filter(isBlockNode3), line); + const found = findHeadingAtLine(node.children.filter(isBlockNode5), line2); if (found) return found; } } return null; } -function findHeadingLineById(source, targetId) { +function findDeclarationById(source, targetId) { let doc; try { - doc = resolve(parse2(source)); + doc = resolve(parse2(source, { positions: true })); } catch { return null; } const heading = findHeadingWithId2(doc.children, targetId.toLowerCase()); - if (!heading || !heading.pos) - return null; - return heading.pos.startLine - 1; + if (heading?.pos) + return { line: heading.pos.startLine - 1, kind: "heading" }; + const caption = captionTargetById(doc, targetId); + if (caption?.pos) + return { line: caption.pos.startLine - 1, kind: "caption" }; + return null; } function findHeadingWithId2(nodes, targetId) { for (const node of nodes) { @@ -15125,15 +43047,16 @@ function findHeadingWithId2(nodes, targetId) { return node; } if ("children" in node && Array.isArray(node.children)) { - const found = findHeadingWithId2(node.children.filter(isBlockNode3), targetId); + const found = findHeadingWithId2(node.children.filter(isBlockNode5), targetId); if (found) return found; } } return null; } -function collectHeadingRefs(uri, source, lines, id, defLine, context) { +function collectRefs(uri, source, lines, id, declaration, context) { const locs = []; + const defLine = declaration.line; if (context.includeDeclaration) { locs.push(lineLocation(uri, defLine, 0, lines[defLine]?.length ?? 0)); } @@ -15154,20 +43077,22 @@ function collectHeadingRefs(uri, source, lines, id, defLine, context) { } } } - const implicitRefRe = /\[([^\]\n]+)\]\[\]/g; - for (let i = 0; i < lines.length; i++) { - for (const m of lines[i].matchAll(implicitRefRe)) { - const slug = m[1].trim().toLowerCase().replace(/\s+/g, "-"); - if (slug === idLower) { - locs.push(lineLocation(uri, i, m.index, m.index + m[0].length)); + if (declaration.kind === "heading") { + const implicitRefRe = /\[([^\]\n]+)\]\[\]/g; + for (let i = 0; i < lines.length; i++) { + for (const m of lines[i].matchAll(implicitRefRe)) { + const slug = m[1].trim().toLowerCase().replace(/\s+/g, "-"); + if (slug === idLower) { + locs.push(lineLocation(uri, i, m.index, m.index + m[0].length)); + } } } } return dedup(locs); } -function resolveFootnoteGroup(uri, lines, line, position, context) { +function resolveFootnoteGroup(uri, lines, line2, position, context) { const fnAnyRe = /\[\^([^\]\s]+)\]/g; - for (const m of line.matchAll(fnAnyRe)) { + for (const m of line2.matchAll(fnAnyRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) @@ -15192,9 +43117,9 @@ function collectFootnoteRefs2(uri, lines, label, context) { } return locs; } -function resolveCitationGroup(uri, lines, line, position, context) { +function resolveCitationGroup(uri, lines, line2, position, context) { const citDefRe = /^\[@([A-Za-z0-9_.:-]+)\]:/; - const defMatch = citDefRe.exec(line); + const defMatch = citDefRe.exec(line2); if (defMatch) { const keyStart = 2; const keyEnd = keyStart + defMatch[1].length; @@ -15203,7 +43128,7 @@ function resolveCitationGroup(uri, lines, line, position, context) { } } const citGroupRe = /\[([^\]]*@[^\]]*)\]/g; - for (const m of line.matchAll(citGroupRe)) { + for (const m of line2.matchAll(citGroupRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) @@ -15220,10 +43145,10 @@ function resolveCitationGroup(uri, lines, line, position, context) { } return null; } -function collectCitationRefs(uri, lines, key, context) { +function collectCitationRefs(uri, lines, key2, context) { const locs = []; - const defRe = new RegExp(`^\\[@${escapeRegExp2(key)}\\]:`); - const usageRe = new RegExp(`-?@${escapeRegExp2(key)}(?=[\\];, ])`, "g"); + const defRe = new RegExp(`^\\[@${escapeRegExp2(key2)}\\]:`); + const usageRe = new RegExp(`-?@${escapeRegExp2(key2)}(?=[\\];, ])`, "g"); for (let i = 0; i < lines.length; i++) { const l = lines[i]; const isDef = defRe.test(l); @@ -15239,8 +43164,8 @@ function collectCitationRefs(uri, lines, key, context) { } return locs; } -function resolveLinkrefGroup(uri, lines, line, position, context) { - const defMatch = /^( {0,3})\[([^\]^][^\]]*)\]:/.exec(line); +function resolveLinkrefGroup(uri, lines, line2, position, context) { + const defMatch = /^( {0,3})\[([^\]^][^\]]*)\]:/.exec(line2); if (defMatch) { const labelStart = defMatch[1].length + 1; const labelEnd = labelStart + defMatch[2].length; @@ -15249,7 +43174,7 @@ function resolveLinkrefGroup(uri, lines, line, position, context) { } } const fullRefRe = /\]\[([^\]^][^\]]*)\]/g; - for (const m of line.matchAll(fullRefRe)) { + for (const m of line2.matchAll(fullRefRe)) { const labelStart = m.index + 2; const labelEnd = labelStart + m[1].length; if (position.character < labelStart || position.character > labelEnd) @@ -15257,7 +43182,7 @@ function resolveLinkrefGroup(uri, lines, line, position, context) { return collectLinkrefRefs(uri, lines, m[1], context); } const collapsedRe = /\[([^\]^][^\]]*)\]\[\]/g; - for (const m of line.matchAll(collapsedRe)) { + for (const m of line2.matchAll(collapsedRe)) { const labelStart = m.index + 1; const labelEnd = labelStart + m[1].length; if (position.character < labelStart || position.character > labelEnd) @@ -15300,9 +43225,9 @@ function collectLinkrefRefs(uri, lines, label, context) { } return locs; } -function resolveWikilinkGroup(uri, source, lines, line, position, context) { +function resolveWikilinkGroup(uri, source, lines, line2, position, context) { const wikilinkRe = /\[\[([^\]|#]+?)(?:[|#][^\]]*)?]]/g; - for (const m of line.matchAll(wikilinkRe)) { + for (const m of line2.matchAll(wikilinkRe)) { const start = m.index; const end = start + m[0].length; if (position.character < start || position.character >= end) @@ -15351,680 +43276,2222 @@ function findHeadingWithText2(nodes, targetText) { return node; } if ("children" in node && Array.isArray(node.children)) { - const found = findHeadingWithText2(node.children.filter(isBlockNode3), targetText); + const found = findHeadingWithText2(node.children.filter(isBlockNode5), targetText); if (found) return found; } } - return null; -} -function headingPlainText2(nodes) { - let out = ""; - for (const node of nodes) { - if (node.type === "text") - out += node.value; - else if ("children" in node && Array.isArray(node.children)) { - out += headingPlainText2(node.children); - } else if (node.type === "code") - out += node.value; - else if (node.type === "literal_inline") - out += node.content; - else - out += smartPunctuationText(node); + return null; +} +function headingPlainText2(nodes) { + let out = ""; + for (const node of nodes) { + if (node.type === "text") + out += node.value; + else if ("children" in node && Array.isArray(node.children)) { + out += headingPlainText2(node.children); + } else if (node.type === "code") + out += node.value; + else if (node.type === "literal_inline") + out += node.content; + else + out += smartPunctuationText(node); + } + return out.trim(); +} +function isBlockNode5(node) { + return Boolean(node && typeof node === "object" && "type" in node); +} +function lineLocation(uri, line2, startChar, endChar) { + return { + uri, + range: { + start: { line: line2, character: startChar }, + end: { line: line2, character: endChar } + } + }; +} +function escapeRegExp2(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +function dedup(locs) { + const seen = /* @__PURE__ */ new Set(); + return locs.filter((loc) => { + const key2 = `${loc.uri}:${loc.range.start.line}:${loc.range.start.character}`; + if (seen.has(key2)) + return false; + seen.add(key2); + return true; + }); +} + +// dist/workspace-index.js +var import_node3 = __toESM(require_node3(), 1); +init_dist2(); +var WorkspaceIndex = class { + #documents = /* @__PURE__ */ new Map(); + update(uri, source, version) { + const current = this.#documents.get(uri); + if (current?.version === version && current.source === source) + return; + this.#documents.set(uri, { version, source, tokens: scanDocument(uri, source) }); + } + remove(uri) { + this.#documents.delete(uri); + } + clear() { + this.#documents.clear(); + } + tokens(uri) { + if (uri !== void 0) + return [...this.#documents.get(uri)?.tokens ?? []]; + return [...this.#documents.values()].flatMap((document) => document.tokens); + } + tokenAt(uri, position) { + const candidates = this.tokens(uri).filter((token) => contains2(token.range, position)); + candidates.sort((a, b) => rangeSize(a.range) - rangeSize(b.range)); + return candidates[0] ?? null; + } + definitions(kind2, key2) { + return this.tokens().filter((token) => token.declaration && sameIdentity(token, kind2, key2)); + } + references(kind2, key2, includeDeclaration = false) { + return this.tokens().filter((token) => (includeDeclaration || !token.declaration) && sameIdentity(token, kind2, key2)).map(({ uri, range }) => ({ uri, range })); + } + symbols(query = "") { + const wanted = query.toLocaleLowerCase(); + return this.tokens().filter((token) => token.declaration && token.key.toLocaleLowerCase().includes(wanted)).map((token) => ({ + name: token.label ?? token.key, + kind: symbolKind(token.kind), + location: { uri: token.uri, range: token.range }, + containerName: token.kind + })); + } + rename(uri, position, newName) { + const target = this.tokenAt(uri, position); + if (!target || !isValidName(target.kind, newName)) + return null; + const edits = /* @__PURE__ */ new Map(); + for (const token of this.tokens()) { + if (!sameIdentity(token, target.kind, target.key)) + continue; + const entries = edits.get(token.uri) ?? []; + entries.push(token.generated && token.declaration ? { + range: { start: { line: token.range.start.line, character: 0 }, end: { line: token.range.start.line, character: 0 } }, + newText: `{#${newName}} +` + } : { range: token.range, newText: newName }); + edits.set(token.uri, entries); + } + return { changes: Object.fromEntries(edits) }; + } +}; +function scanDocument(uri, source) { + const tokens = []; + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + for (let line2 = 0; line2 < lines.length; line2 += 1) { + const text = lines[line2]; + const heading = /^(#{1,6}) (.*)$/.exec(text); + if (heading) { + const explicit = /\{#([^\s}]+)(?:\s[^}]*)?\}\s*$/.exec(heading[2]); + if (explicit) + push(tokens, uri, "heading", explicit[1], line2, text.indexOf(explicit[1]), true); + } + const attributed = /^\{[^}]*#([^\s}]+)[^}]*\}\s*$/.exec(text); + if (attributed) { + const next = lines[line2 + 1] ?? ""; + const kind2 = /^#{1,6} /.test(next) ? "heading" : "caption"; + push(tokens, uri, kind2, attributed[1], line2, text.indexOf(attributed[1]), true); + } + const footnoteDef = /^(?: {0,3})\[\^([^\]]+)\]:/.exec(text); + if (footnoteDef) + push(tokens, uri, "footnote", footnoteDef[1], line2, text.indexOf(footnoteDef[1]), true); + const citationDef = /^(?: {0,3})\[@([^\]]+)\]:/.exec(text); + if (citationDef) + push(tokens, uri, "citation", citationDef[1], line2, text.indexOf(citationDef[1]), true); + const linkDef = /^(?: {0,3})\[([^\]^@][^\]]*)\]:/.exec(text); + if (linkDef) + push(tokens, uri, "linkref", linkDef[1], line2, text.indexOf(linkDef[1]), true); + for (const match of text.matchAll(/<\/#([^>\s]+)>|\]\(#([^\s)]+)\)/g)) { + const key2 = match[1] ?? match[2]; + const start = match.index + match[0].indexOf(key2); + push(tokens, uri, "heading", key2, line2, start, false); + } + for (const match of text.matchAll(/\[\^([^\]]+)\](?!:)/g)) { + push(tokens, uri, "footnote", match[1], line2, match.index + 2, false); + } + for (const match of text.matchAll(/\]\[([^\]]+)\]/g)) { + if (match[1] === "" || match[1].startsWith("^") || match[1].startsWith("@")) + continue; + push(tokens, uri, "linkref", match[1], line2, match.index + 2, false); + } + for (const group of text.matchAll(/\[([^\]]*@[^^\]]+)\]/g)) { + if (citationDef && group.index === text.indexOf(`[@${citationDef[1]}]`)) + continue; + for (const cite of group[1].matchAll(/@([\p{L}\p{N}_:.+-]+)/gu)) { + push(tokens, uri, "citation", cite[1], line2, group.index + 1 + cite.index + 1, false); + } + } + } + try { + const document = resolve(parse2(source, { positions: true })); + walkBlocks4(document.children, (node) => { + if (node.type !== "heading" || !node.pos || !node.attrs?.id) + return; + const line2 = node.pos.startLine - 1; + const alreadyAuthored = tokens.some((token) => token.declaration && anchorKind(token.kind) && token.key === node.attrs?.id && (token.range.start.line === line2 || token.range.start.line === line2 - 1)); + if (alreadyAuthored) + return; + const lineText = lines[line2] ?? ""; + const start = Math.min(lineText.length, /^#{1,6}\s+/.exec(lineText)?.[0].length ?? 0); + tokens.push({ + kind: "heading", + key: node.attrs.id, + uri, + declaration: true, + generated: true, + label: inlineText3(node.children) || node.attrs.id, + range: { start: { line: line2, character: start }, end: { line: line2, character: lineText.length } } + }); + }); + } catch { + } + return dedupe(tokens); +} +function walkBlocks4(nodes, visit4) { + for (const node of nodes) { + visit4(node); + if ("children" in node && Array.isArray(node.children)) { + walkBlocks4(node.children.filter((child) => Boolean(child && typeof child === "object" && "type" in child && !inlineKinds.has(child.type))), visit4); + } + } +} +var inlineKinds = /* @__PURE__ */ new Set(["text", "softbreak", "linebreak", "emph", "strong", "underline", "strikethrough", "highlight", "superscript", "subscript", "code", "verbatim", "math", "link", "image", "crossref", "footnote", "citation", "symbol", "smart", "span"]); +function inlineText3(nodes) { + return nodes.map((node) => { + if ("value" in node && typeof node.value === "string") + return node.value; + if ("children" in node && Array.isArray(node.children)) + return inlineText3(node.children); + return ""; + }).join("").trim(); +} +function push(tokens, uri, kind2, key2, line2, character, declaration) { + tokens.push({ + kind: kind2, + key: key2, + uri, + declaration, + range: { + start: { line: line2, character }, + end: { line: line2, character: character + key2.length } + } + }); +} +function dedupe(tokens) { + const seen = /* @__PURE__ */ new Set(); + return tokens.filter((token) => { + const id = `${token.kind}:${token.key}:${token.range.start.line}:${token.range.start.character}:${token.declaration}`; + if (seen.has(id)) + return false; + seen.add(id); + return true; + }); +} +function sameIdentity(token, kind2, key2) { + const sameKind = token.kind === kind2 || anchorKind(token.kind) && anchorKind(kind2); + return sameKind && token.key.toLocaleLowerCase() === key2.toLocaleLowerCase(); +} +function anchorKind(kind2) { + return kind2 === "heading" || kind2 === "caption"; +} +function contains2(range, position) { + return position.line === range.start.line && position.character >= range.start.character && position.character <= range.end.character; +} +function rangeSize(range) { + return (range.end.line - range.start.line) * 1e6 + range.end.character - range.start.character; +} +function symbolKind(kind2) { + if (kind2 === "heading") + return import_node3.SymbolKind.Namespace; + if (kind2 === "caption") + return import_node3.SymbolKind.Object; + if (kind2 === "citation") + return import_node3.SymbolKind.Key; + return import_node3.SymbolKind.Variable; +} +function isValidName(kind2, value) { + if (value.length === 0 || /[\[\]\r\n]/.test(value)) + return false; + if (kind2 === "heading" || kind2 === "caption" || kind2 === "citation") + return !/\s/.test(value); + return true; +} + +// dist/codelens.js +function codeLenses(source) { + const lines = source.split(/\r?\n/); + const refCounts = /* @__PURE__ */ new Map(); + lines.forEach((line2) => { + for (const m of line2.matchAll(/\[\^([^\]\s]+)\](?!:)/g)) { + refCounts.set(m[1], (refCounts.get(m[1]) ?? 0) + 1); + } + }); + const lenses = []; + lines.forEach((line2, lineNo) => { + const def = /^( {0,3})\[\^([^\]\s]+)\]:/.exec(line2); + if (!def) + return; + const label = def[2]; + const count = refCounts.get(label) ?? 0; + const start = def[1].length; + lenses.push({ + range: { + start: { line: lineNo, character: start }, + end: { line: lineNo, character: start + label.length + 3 } + }, + command: { + title: count === 1 ? "1 reference" : `${count} references`, + command: "" + } + }); + }); + const tokens = scanDocument("file:///document.crv", source); + for (const declaration of tokens) { + if (!declaration.declaration || declaration.kind === "footnote") + continue; + const count = tokens.filter((token) => !token.declaration && token.kind === declaration.kind && token.key.toLocaleLowerCase() === declaration.key.toLocaleLowerCase()).length; + lenses.push({ + range: declaration.range, + command: { title: count === 1 ? "1 reference" : `${count} references`, command: "" } + }); + } + return lenses; +} + +// dist/completion.js +var import_node4 = __toESM(require_node3(), 1); +init_dist2(); +var ADMONITIONS = ["note", "tip", "warning", "danger", "info", "success", "example", "quote"]; +var FIGURE_GROUP = "figure"; +function completionAt(source, position, context = {}) { + const line2 = source.split(/\r?\n/)[position.line] ?? ""; + const prefix = line2.slice(0, position.character); + let match; + if (match = /:::\s*([\w-]*)$/.exec(prefix)) { + return [ + ...ADMONITIONS.map((kind2) => completion(kind2, import_node4.CompletionItemKind.Keyword, match[1], position, "Admonition kind")), + completion(FIGURE_GROUP, import_node4.CompletionItemKind.Struct, match[1], position, "Composite figure") + ]; + } + if (match = /<\/#([\w-]*)$/.exec(prefix)) { + const workspace = (context.workspaceTokens ?? []).filter((token) => token.declaration && (token.kind === "heading" || token.kind === "caption")).map((token) => completion(token.key, import_node4.CompletionItemKind.Reference, match[1], position, `${token.kind} in workspace`)); + return uniqueCompletions([ + ...headingIds(source).map((id) => completion(id, import_node4.CompletionItemKind.Reference, match[1], position, "Heading id")), + ...resolvableCaptionIds(source).map(({ id, detail }) => completion(id, import_node4.CompletionItemKind.Reference, match[1], position, detail)), + ...workspace + ]); + } + if (match = /\[\^([\w-]*)$/.exec(prefix)) { + return footnoteLabels(source).map((label) => completion(label, import_node4.CompletionItemKind.Reference, match[1], position, "Footnote")); + } + if (match = /\]\[([\w-]*)$/.exec(prefix)) { + return linkReferenceLabels(source).map((label) => completion(label, import_node4.CompletionItemKind.Reference, match[1], position, "Link reference")); + } + if (match = /\[@([\w:.-]*)$/.exec(prefix)) { + const local = citationLabels(source); + const workspace = (context.workspaceTokens ?? []).filter((token) => token.declaration && token.kind === "citation").map((token) => token.key); + return [.../* @__PURE__ */ new Set([...local, ...workspace])].map((label) => completion(label, import_node4.CompletionItemKind.Reference, match[1], position, "Citation key")); + } + if (match = /\{[^}\n]*\b([\w-]*)$/.exec(prefix)) { + const attributes = [ + "#id", + ".class", + "align=", + "valign=", + "width=", + "aligns=", + "valigns=", + "widths=", + "header-rows=", + "header-cols=", + "footer-rows=", + "start=", + "type=", + "title=", + "label=" + ]; + return attributes.map((attribute) => completion(attribute, import_node4.CompletionItemKind.Property, match[1], position, "Carve attribute")); + } + if (match = /:(\w*)$/.exec(prefix)) { + return ["abbr", "time", "kbd", "samp", "var", "cite", "dfn"].map((name) => completion(name, import_node4.CompletionItemKind.TypeParameter, match[1], position, "Semantic span")); + } + return []; +} +function uniqueCompletions(items) { + const seen = /* @__PURE__ */ new Set(); + return items.filter((item2) => { + if (seen.has(item2.label)) + return false; + seen.add(item2.label); + return true; + }); +} +function completion(value, kind2, partial, position, detail) { + return { + label: value, + kind: kind2, + detail, + // Replace the partial token the user already typed so values containing + // `-` or `#` are not mangled by the editor's default word range. + textEdit: { + range: { + start: { line: position.line, character: position.character - partial.length }, + end: position + }, + newText: value + } + }; +} +function headingIds(source) { + const ids = []; + try { + const doc = resolve(parse2(source)); + walkBlocks5(doc.children, (node) => { + if (node.type === "heading" && node.attrs?.id) + ids.push(node.attrs.id); + }); + } catch { + } + return [...new Set(ids)]; +} +function resolvableCaptionIds(source) { + let targets; + try { + targets = captionTargets(resolve(parse2(source, { positions: true }))); + } catch { + return []; + } + const resolvable = []; + for (const target of targets) { + if (target.text === null) + continue; + resolvable.push({ id: target.id, detail: `${target.text} (${target.kind})` }); + } + return resolvable; +} +function footnoteLabels(source) { + try { + const doc = resolve(parse2(source)); + return Object.keys(doc.footnoteDefs ?? {}); + } catch { + return []; + } +} +function linkReferenceLabels(source) { + const labels = /* @__PURE__ */ new Set(); + for (const line2 of source.split(/\r?\n/)) { + const match = /^\s{0,3}\[([^\]]+)\]:\s+\S/.exec(line2); + if (match && !match[1].startsWith("^")) + labels.add(match[1]); + } + return [...labels]; +} +function citationLabels(source) { + const labels = /* @__PURE__ */ new Set(); + for (const line2 of source.split(/\r?\n/)) { + const match = /^\s{0,3}\[@([^\]]+)\]:/.exec(line2); + if (match) + labels.add(match[1]); + } + return [...labels]; +} +function walkBlocks5(nodes, visit4) { + for (const node of nodes) { + visit4(node); + if ("children" in node && Array.isArray(node.children)) { + walkBlocks5(node.children.filter(isBlockNode6), visit4); + } + } +} +function isBlockNode6(node) { + return Boolean(node && typeof node === "object" && "type" in node); +} + +// dist/folding.js +init_dist2(); +var FOLDABLE = /* @__PURE__ */ new Set([ + "code_block", + "raw_block", + "comment", + "block_quote", + "list", + "table", + "admonition", + "div", + "definition_list", + "figure", + // A composite figure is a fenced container like any other, and a long one is + // exactly what a reader wants to collapse (PART 9 §4c). + "figure_group" +]); +function foldingRanges(source) { + let doc; + try { + doc = resolve(parse2(source, { positions: true })); + } catch { + return lexicalFolds(source); + } + const ranges = []; + const headings = []; + const visit4 = (nodes) => { + for (const node of nodes) { + if (node.type === "heading" && node.pos) { + headings.push({ level: node.level, startLine: node.pos.startLine }); + } + if (node.pos && node.pos.endLine > node.pos.startLine && FOLDABLE.has(node.type)) { + ranges.push({ startLine: node.pos.startLine - 1, endLine: node.pos.endLine - 1 }); + } + if ("children" in node && Array.isArray(node.children)) { + visit4(node.children.filter(isBlockNode7)); + } + } + }; + visit4(doc.children); + const lastLine = Math.max(0, source.split(/\r?\n/).length - 1); + for (let i = 0; i < headings.length; i++) { + const heading = headings[i]; + let end = lastLine; + for (let j = i + 1; j < headings.length; j++) { + if (headings[j].level <= heading.level) { + end = headings[j].startLine - 2; + break; + } + } + if (end > heading.startLine - 1) { + ranges.push({ startLine: heading.startLine - 1, endLine: end, kind: "region" }); + } + } + return ranges; +} +function lexicalFolds(source) { + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + const ranges = []; + const headings = []; + const fences = []; + for (let line2 = 0; line2 < lines.length; line2 += 1) { + const text = lines[line2]; + const heading = /^(#{1,6}) /.exec(text); + if (heading) + headings.push({ level: heading[1].length, line: line2 }); + const fence = /^\s*(`{3,}|~{3,}|:{3,}|%{3,})/.exec(text); + if (!fence) + continue; + const top = fences.at(-1); + if (top && top.marker[0] === fence[1][0] && fence[1].length >= top.marker.length) { + fences.pop(); + if (line2 > top.line) + ranges.push({ startLine: top.line, endLine: line2 }); + } else { + fences.push({ marker: fence[1], line: line2 }); + } + } + for (let index2 = 0; index2 < headings.length; index2 += 1) { + const heading = headings[index2]; + const next = headings.slice(index2 + 1).find((candidate) => candidate.level <= heading.level); + const endLine = (next?.line ?? lines.length) - 1; + if (endLine > heading.line) + ranges.push({ startLine: heading.line, endLine, kind: "region" }); } - return out.trim(); + return ranges; } -function isBlockNode3(node) { +function isBlockNode7(node) { return Boolean(node && typeof node === "object" && "type" in node); } -function lineLocation(uri, line, startChar, endChar) { - return { - uri, - range: { - start: { line, character: startChar }, - end: { line, character: endChar } - } - }; -} -function escapeRegExp2(value) { - return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + +// dist/format.js +function formatDocument(source) { + if (source === "" || source.endsWith("\n")) + return source; + return source + (source.includes("\r\n") ? "\r\n" : "\n"); } -function dedup(locs) { - const seen = /* @__PURE__ */ new Set(); - return locs.filter((loc) => { - const key = `${loc.uri}:${loc.range.start.line}:${loc.range.start.character}`; - if (seen.has(key)) - return false; - seen.add(key); - return true; - }); +function formatRange(source, startLine, endLine) { + const eol = source.includes("\r\n") ? "\r\n" : "\n"; + return source.split(/\r?\n/).slice(startLine, endLine + 1).join(eol); } - -// dist/codelens.js -function codeLenses(source) { - const lines = source.split(/\r?\n/); - const refCounts = /* @__PURE__ */ new Map(); - lines.forEach((line) => { - for (const m of line.matchAll(/\[\^([^\]\s]+)\](?!:)/g)) { - refCounts.set(m[1], (refCounts.get(m[1]) ?? 0) + 1); - } - }); - const lenses = []; - lines.forEach((line, lineNo) => { - const def = /^( {0,3})\[\^([^\]\s]+)\]:/.exec(line); - if (!def) - return; - const label = def[2]; - const count = refCounts.get(label) ?? 0; - const start = def[1].length; - lenses.push({ - range: { - start: { line: lineNo, character: start }, - end: { line: lineNo, character: start + label.length + 3 } - }, - command: { - title: count === 1 ? "1 reference" : `${count} references`, - command: "" - } - }); - }); - return lenses; +function continuationPrefix(source, line2) { + const previous = source.split(/\r?\n/)[line2 - 1] ?? ""; + const quote = /^(\s*(?:> )+)/.exec(previous); + if (quote) + return quote[1]; + const table = /^(\s*)\|/.exec(previous); + if (table) + return `${table[1]}| `; + const definition = /^(\s*): /.exec(previous); + if (definition) + return `${definition[1]} `; + return ""; } -// dist/completion.js -var import_node2 = __toESM(require_node3(), 1); -var ADMONITIONS = ["note", "tip", "warning", "danger", "info", "success", "example", "quote"]; -function completionAt(source, position) { - const line = source.split(/\r?\n/)[position.line] ?? ""; - const prefix = line.slice(0, position.character); - let match; - if (match = /:::\s*([\w-]*)$/.exec(prefix)) { - return ADMONITIONS.map((kind) => completion(kind, import_node2.CompletionItemKind.Keyword, match[1], position, "Admonition kind")); - } - if (match = /<\/#([\w-]*)$/.exec(prefix)) { - return headingIds(source).map((id) => completion(id, import_node2.CompletionItemKind.Reference, match[1], position, "Heading id")); +// dist/hover.js +var import_node5 = __toESM(require_node3(), 1); +init_dist2(); +var rules = [ + { + pattern: /\|=?\s*[<>~^v]{1,2}(?=\{| )/g, + contents: "**Table alignment**\n\nA one- or two-character run sets horizontal and/or vertical cell alignment. Two-axis runs normalize to horizontal then vertical." + }, + { + pattern: /\b(?:aligns|valigns|widths|header-rows|header-cols|footer-rows)=/g, + contents: "**Table metadata**\n\nA positional table/ListTable field. Empty list entries leave that column unset; cell-local values win." + }, + { + pattern: /\[@[^\]\n]+\]/g, + contents: "**Citation**\n\nCitation groups reference `[@key]: ...` bibliography entries when the Citations extension is enabled." + }, + { + pattern: /\{\{[^}\n]+\}\}/g, + contents: "**Include**\n\nProcessor-level file inclusion. The language server resolves it only in a trusted, explicitly enabled workspace." + }, + { + pattern: /#{1,6}/g, + contents: "**Heading**\n\n`#` through `######` create section headings." + }, + { + pattern: /\*[^*\n]+\*/g, + contents: "**Bold**\n\nCarve uses single asterisks for bold text: `*bold*`." + }, + { + pattern: /\/[^/\n]+\//g, + contents: "**Italic**\n\nCarve uses slashes for italic text: `/italic/`." + }, + { + pattern: /_[^_\n]+_/g, + contents: "**Underline**\n\nCarve uses underscores for underline: `_underlined_`." + }, + { + pattern: /~[^~\n]+~/g, + contents: "**Strikethrough**\n\nCarve uses tildes for strikethrough: `~removed~`." + }, + { + pattern: /\{[^}\n]+\}/g, + contents: "**Attributes**\n\nAttach IDs, classes, and key/value pairs with `{#id .class key=value}`." + }, + { + pattern: /\[[^\]\n]+\]\([^\s)]+(?:\s+"[^"]*")?\)/g, + contents: "**Link**\n\nInline links use `[label](url)`." + }, + { + pattern: /!\[[^\]\n]*\]\([^\s)]+(?:\s+"[^"]*")?\)/g, + contents: "**Image**\n\nImages use `![alt](url)` and can be followed by captions." + }, + { + pattern: /`[^`\n]+`/g, + contents: "**Inline Code**\n\nBackticks mark inline code spans." } - if (match = /\[\^([\w-]*)$/.exec(prefix)) { - return footnoteLabels(source).map((label) => completion(label, import_node2.CompletionItemKind.Reference, match[1], position, "Footnote")); +]; +function hoverAt(source, position) { + const lines = sourceLines(source); + try { + const hover = astHoverAt(resolve(parse2(source)), position, lines); + if (hover) + return hover; + } catch { } - if (match = /\]\[([\w-]*)$/.exec(prefix)) { - return linkReferenceLabels(source).map((label) => completion(label, import_node2.CompletionItemKind.Reference, match[1], position, "Link reference")); + const line2 = lines[position.line]; + if (line2 === void 0) + return null; + for (const rule of rules) { + rule.pattern.lastIndex = 0; + for (const match of line2.matchAll(rule.pattern)) { + const start = match.index ?? 0; + const end = start + match[0].length; + if (position.character < start || position.character > end) + continue; + return { + contents: { + kind: import_node5.MarkupKind.Markdown, + value: rule.contents + }, + range: { + start: { line: position.line, character: start }, + end: { line: position.line, character: end } + } + }; + } } - return []; + return null; } -function completion(value, kind, partial, position, detail) { +function astHoverAt(doc, position, lines) { + const cursor = { + line: position.line, + character: characterToAstColumn(lines[position.line] ?? "", position.character) - 1 + }; + const matches = []; + const resolveRef = (id) => captionTargetById(doc, id); + for (const node of doc.children) + collectBlock(matches, node, cursor, resolveRef); + matches.sort((a, b) => spanSize(a.pos) - spanSize(b.pos)); + const match = matches[0]; + if (!match) + return null; return { - label: value, - kind, - detail, - // Replace the partial token the user already typed so values containing - // `-` or `#` are not mangled by the editor's default word range. - textEdit: { - range: { - start: { line: position.line, character: position.character - partial.length }, - end: position - }, - newText: value - } + contents: { + kind: import_node5.MarkupKind.Markdown, + value: match.contents + }, + range: toRange(match.pos, lines) }; } -function headingIds(source) { - const ids = []; - try { - const doc = resolve(parse2(source)); - walkBlocks(doc.children, (node) => { - if (node.type === "heading" && node.attrs?.id) - ids.push(node.attrs.id); - }); - } catch { +function collectBlock(matches, node, position, resolveRef) { + addMatch(matches, node.pos, position, blockContents(node)); + switch (node.type) { + case "heading": + collectInline(matches, node.children, position, resolveRef); + break; + case "paragraph": + collectInline(matches, node.children, position, resolveRef); + break; + case "block_quote": + node.children.forEach((child) => collectBlock(matches, child, position, resolveRef)); + break; + case "list": + node.items.forEach((item2) => item2.children.forEach((child) => collectBlock(matches, child, position, resolveRef))); + break; + case "admonition": + case "div": + node.children.forEach((child) => collectBlock(matches, child, position, resolveRef)); + if (node.type === "admonition" && node.title) + collectInline(matches, node.title, position, resolveRef); + break; + case "definition_list": + node.items.forEach((item2) => { + item2.terms.forEach((term) => collectInline(matches, term, position, resolveRef)); + item2.definitions.forEach((definition) => definition.forEach((child) => collectBlock(matches, child, position, resolveRef))); + }); + break; + case "figure": + collectBlock(matches, node.target, position, resolveRef); + collectInline(matches, node.caption, position, resolveRef); + break; + case "figure_group": + node.children.forEach((child) => collectBlock(matches, child, position, resolveRef)); + if (node.caption) + collectInline(matches, node.caption, position, resolveRef); + break; + case "table": + if (node.caption) + collectInline(matches, node.caption, position, resolveRef); + node.rows.forEach((row) => row.cells.forEach((cell) => collectInline(matches, cell.children, position, resolveRef))); + break; + } +} +function collectInline(matches, nodes, position, resolveRef) { + for (const node of nodes) { + addMatch(matches, node.pos, position, inlineContents(node, resolveRef)); + const children = node.children; + if (Array.isArray(children)) + collectInline(matches, children, position, resolveRef); + const content = node.content; + if (Array.isArray(content)) + collectInline(matches, content, position, resolveRef); + } +} +function addMatch(matches, pos, position, contents) { + if (!contents || !pos || !contains3(pos, position)) + return; + matches.push({ pos, contents }); +} +function blockContents(node) { + switch (node.type) { + case "heading": + return "**Heading**\n\n`#` through `######` create section headings."; + case "code_block": + return "**Code Block**\n\nTriple backtick or tilde fences create verbatim code blocks."; + case "raw_block": + return "**Raw Block**\n\nRaw passthrough blocks render only for matching output formats."; + case "block_quote": + return "**Block Quote**\n\nLines beginning with `>` create quoted blocks."; + case "list": + return "**List**\n\nUse bullets, task markers, or ordered markers for lists."; + case "table": + return "**Table**\n\nPipe-delimited rows create tables."; + case "admonition": + return "**Admonition**\n\nTyped `:::` fences create admonition blocks."; + case "div": + return "**Div**\n\nBare `:::` fences create generic container blocks."; + case "figure_group": + return "**Composite Figure**\n\nA bare `::: figure` fence is one figure of ordered panels. The `^ ` line after the closing fence captions the whole group. An opener carrying a title or a `[label]` stays a generic container instead."; + default: + return null; + } +} +function inlineContents(node, resolveRef) { + switch (node.type) { + case "strong": + return "**Bold**\n\nCarve uses single asterisks for bold text: `*bold*`."; + case "emphasis": + return "**Italic**\n\nCarve uses slashes for italic text: `/italic/`."; + case "underline": + return "**Underline**\n\nCarve uses underscores for underline: `_underlined_`."; + case "strike": + return "**Strikethrough**\n\nCarve uses tildes for strikethrough: `~removed~`."; + case "subscript": + return "**Subscript**\n\nCarve subscript uses the braced form `{,text,}`, e.g. `H{,2,}O`. A bare comma is literal text."; + case "superscript": + return "**Superscript**\n\nCarve superscript uses the braced form `{^text^}`, e.g. `E=mc{^2^}`. A bare caret is literal text."; + case "highlight": + return "**Highlight**\n\nCarve highlight is a single equals: `=marked=` (use the forced form `{=marked=}` intraword)."; + case "code": + return "**Inline Code**\n\nBackticks mark inline code spans."; + case "literal_inline": + return "**Inline Literal**\n\nA `!` prefix on a verbatim span renders its content as ordinary prose, without code styling: `` !`/kaet/` ``. Mirrors the `$`-math prefix."; + case "link": + return "**Link**\n\nInline links use `[label](url)` or reference-link syntax."; + case "image": + return "**Image**\n\nImages use `![alt](url)` and can be followed by captions."; + case "mention": + return "**Mention**\n\nMentions use `@name`."; + case "tag": + return "**Tag**\n\nTags use `#name`."; + case "span": + return "**Span**\n\nInline spans use `[text]{attrs}`."; + case "heading_ref": + return crossrefContents(node, resolveRef); + default: + return null; } - return [...new Set(ids)]; } -function footnoteLabels(source) { - try { - const doc = resolve(parse2(source)); - return Object.keys(doc.footnoteDefs ?? {}); - } catch { - return []; +function crossrefContents(node, resolveRef) { + const generic = "**Cross-reference**\n\nA `` reference links to the heading or captioned host carrying that id."; + const id = node.target; + if (typeof id !== "string") + return generic; + const target = resolveRef(id); + if (!target) + return generic; + if (target.text === null) { + return "**Cross-reference**\n\nAn unnumbered " + target.kind + ". It is an anchor, but it drew no number, so this reference has no caption text to render."; } + return "**Cross-reference**\n\nResolves to **" + target.text + "** (" + target.kind + ")."; } -function linkReferenceLabels(source) { - const labels = /* @__PURE__ */ new Set(); - for (const line of source.split(/\r?\n/)) { - const match = /^\s{0,3}\[([^\]]+)\]:\s+\S/.exec(line); - if (match && !match[1].startsWith("^")) - labels.add(match[1]); +function contains3(pos, position) { + if (pos.startColumn === void 0 || pos.endColumn === void 0 || position.line + 1 < pos.startLine || position.line + 1 > pos.endLine) { + return false; } - return [...labels]; + if (position.line + 1 === pos.startLine && position.character + 1 < pos.startColumn) + return false; + if (position.line + 1 === pos.endLine && position.character + 1 > pos.endColumn) + return false; + return true; } -function walkBlocks(nodes, visit) { - for (const node of nodes) { - visit(node); - if ("children" in node && Array.isArray(node.children)) { - walkBlocks(node.children.filter(isBlockNode4), visit); +function toRange(pos, lines) { + return { + start: { + line: pos.startLine - 1, + character: astColumnToCharacter(lines[pos.startLine - 1] ?? "", pos.startColumn ?? 1) + }, + end: { + line: pos.endLine - 1, + character: astColumnToCharacter(lines[pos.endLine - 1] ?? "", pos.endColumn ?? 1) } - } + }; } -function isBlockNode4(node) { - return Boolean(node && typeof node === "object" && "type" in node); +function spanSize(pos) { + if (pos.startOffset !== void 0 && pos.endOffset !== void 0) + return pos.endOffset - pos.startOffset; + return (pos.endLine - pos.startLine) * 1e3 + ((pos.endColumn ?? 1) - (pos.startColumn ?? 1)); } -// dist/folding.js -var FOLDABLE = /* @__PURE__ */ new Set([ - "code_block", - "raw_block", - "comment", - "block_quote", - "list", - "table", - "admonition", - "div", - "definition_list", - "figure" -]); -function foldingRanges(source) { - let doc; - try { - doc = resolve(parse2(source, { positions: true })); - } catch { - return []; +// dist/migration-actions.js +var import_node6 = __toESM(require_node3(), 1); +init_dist2(); +function normalize5(source) { + return source.replace(/\r\n?/g, "\n"); +} +function migrationFixes(source) { + const norm = normalize5(source); + return djotMigrationWarnings(source).map((warning) => ({ + rule: warning.rule, + range: import_node6.Range.create(positionAt2(norm, warning.start), positionAt2(norm, warning.end)), + suggestion: warning.suggestion + })); +} +function migrationCodeActions(uri, source, diagnostics2) { + const fixes = migrationFixes(source); + const actions = []; + for (const diagnostic2 of diagnostics2) { + if (typeof diagnostic2.code !== "string") + continue; + const fix = fixes.find((candidate) => candidate.rule === diagnostic2.code && candidate.range.start.line === diagnostic2.range.start.line && candidate.range.start.character === diagnostic2.range.start.character); + if (!fix) + continue; + actions.push({ + title: `Convert to Carve syntax: ${fix.suggestion}`, + kind: import_node6.CodeActionKind.QuickFix, + diagnostics: [diagnostic2], + edit: { + changes: { + [uri]: [import_node6.TextEdit.replace(fix.range, fix.suggestion)] + } + }, + isPreferred: true + }); } - const ranges = []; - const headings = []; - const visit = (nodes) => { - for (const node of nodes) { - if (node.type === "heading" && node.pos) { - headings.push({ level: node.level, startLine: node.pos.startLine }); - } - if (node.pos && node.pos.endLine > node.pos.startLine && FOLDABLE.has(node.type)) { - ranges.push({ startLine: node.pos.startLine - 1, endLine: node.pos.endLine - 1 }); - } - if ("children" in node && Array.isArray(node.children)) { - visit(node.children.filter(isBlockNode5)); + const fixAll = migrationFixAllAction(uri, source); + if (fixAll) + actions.push(fixAll); + return actions; +} +function migrationFixAllAction(uri, source) { + const { output, applied } = applyMigrationFixes(source); + if (applied.length === 0) + return null; + const norm = normalize5(source); + const fullRange = import_node6.Range.create(positionAt2(norm, 0), positionAt2(norm, norm.length)); + const n = applied.length; + return { + title: `Fix all Carve migration collisions (${n})`, + kind: import_node6.CodeActionKind.SourceFixAll, + edit: { + changes: { + [uri]: [import_node6.TextEdit.replace(fullRange, output)] } } }; - visit(doc.children); - const lastLine = Math.max(0, source.split(/\r?\n/).length - 1); - for (let i = 0; i < headings.length; i++) { - const heading = headings[i]; - let end = lastLine; - for (let j = i + 1; j < headings.length; j++) { - if (headings[j].level <= heading.level) { - end = headings[j].startLine - 2; - break; - } - } - if (end > heading.startLine - 1) { - ranges.push({ startLine: heading.startLine - 1, endLine: end, kind: "region" }); - } +} +function positionAt2(source, offset) { + const before = source.slice(0, offset); + const line2 = before.split("\n").length - 1; + const lastNewline = before.lastIndexOf("\n"); + return { + line: line2, + character: offset - lastNewline - 1 + }; +} + +// dist/lint-actions.js +var import_node7 = __toESM(require_node3(), 1); +function lintCodeActions(uri, source, diagnostics2) { + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + const actions = []; + for (const diagnostic2 of diagnostics2) { + const code = String(diagnostic2.code ?? ""); + const line2 = lines[diagnostic2.range.start.line] ?? ""; + let edit = null; + let title = ""; + if (code === "raw-block-syntax") { + const match = /^(\s*`{3,})raw(?: +([^\s]+))?/.exec(line2); + if (match) { + const replacement = `${match[1]}=${match[2] ?? "html"}`; + edit = replace(diagnostic2.range.start.line, match[0].length, replacement); + title = "Convert to a Carve raw fence"; + } + } else if (code === "blockquote-marker-without-space") { + const marker = /^\s*>/.exec(line2); + if (marker) { + const character = marker[0].length; + edit = { range: point(diagnostic2.range.start.line, character), newText: " " }; + title = "Insert the block-quote separator"; + } + } else if (code === "table-alignment-run-padding") { + const marker = /\|=?[<>~^v]{1,2}(?=\S)/.exec(line2); + if (marker) { + const character = marker.index + marker[0].length; + edit = { range: point(diagnostic2.range.start.line, character), newText: " " }; + title = "Terminate the table alignment run with a space"; + } + } else if (code === "unresolved-footnote") { + const match = /\[\^([^\]]+)\]/.exec(line2.slice(diagnostic2.range.start.character)) ?? /\[\^([^\]]+)\]/.exec(line2); + if (match) { + edit = append(source, ` +[^${match[1]}]: `); + title = `Create footnote definition \u201C${match[1]}\u201D`; + } + } else if (code === "unresolved-reference-link") { + const match = /\]\[([^\]]+)\]/.exec(line2.slice(diagnostic2.range.start.character)) ?? /\]\[([^\]]+)\]/.exec(line2); + if (match && match[1]) { + edit = append(source, ` +[${match[1]}]: `); + title = `Create link definition \u201C${match[1]}\u201D`; + } + } + if (!edit) + continue; + actions.push({ + title, + kind: import_node7.CodeActionKind.QuickFix, + diagnostics: [diagnostic2], + isPreferred: true, + edit: { changes: { [uri]: [edit] } } + }); } - return ranges; + return actions; } -function isBlockNode5(node) { - return Boolean(node && typeof node === "object" && "type" in node); +function append(source, newText) { + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + const line2 = Math.max(0, lines.length - 1); + return { range: point(line2, lines[line2]?.length ?? 0), newText }; +} +function point(line2, character) { + return { start: { line: line2, character }, end: { line: line2, character } }; +} +function replace(line2, end, newText) { + return { range: { start: { line: line2, character: 0 }, end: { line: line2, character: end } }, newText }; } -// dist/format.js -function formatDocument(source) { - const eol = source.includes("\r\n") ? "\r\n" : "\n"; +// dist/rename.js +function collectTokens(source) { + const tokens = []; const lines = source.split(/\r?\n/); - const out = []; - let openFence = null; - let blankRun = 0; - for (const raw of lines) { - if (openFence !== null) { - out.push(raw); - if (closesFence(raw, openFence)) - openFence = null; - blankRun = 0; - continue; - } - const opener = fenceOpener(raw); - if (opener) { - openFence = opener; - out.push(raw.replace(/[ \t]+$/, "")); - blankRun = 0; - continue; - } - const trimmed = raw.replace(/[ \t]+$/, ""); - if (trimmed === "") { - blankRun++; - if (blankRun === 1) - out.push(""); - continue; + lines.forEach((line2, lineNo) => { + for (const m of line2.matchAll(/\[\^([^\]\s]+)\]/g)) { + const start = m.index + 2; + tokens.push({ kind: "footnote", label: m[1], line: lineNo, startChar: start, endChar: start + m[1].length }); + } + const def = /^( {0,3})\[([^\]]+)\]:/.exec(line2); + if (def && !def[2].startsWith("^")) { + const start = def[1].length + 1; + tokens.push({ kind: "linkref", label: def[2], line: lineNo, startChar: start, endChar: start + def[2].length }); + } + for (const m of line2.matchAll(/\]\[([^\]]+)\]/g)) { + if (m[1].startsWith("^")) + continue; + const start = m.index + 2; + tokens.push({ kind: "linkref", label: m[1], line: lineNo, startChar: start, endChar: start + m[1].length }); + } + }); + return tokens; +} +function tokenAt(source, position) { + for (const token of collectTokens(source)) { + if (token.line === position.line && position.character >= token.startChar && position.character <= token.endChar) { + return token; } - blankRun = 0; - out.push(trimmed); } - while (out.length && out[0] === "") - out.shift(); - while (out.length && out[out.length - 1] === "") - out.pop(); - return out.length ? out.join(eol) + eol : ""; + return null; } -function fenceOpener(line) { - const match = /^( {0,3})(`{3,}|~{3,}|%{3,})(.*)$/.exec(line); - if (!match) - return null; - const marker = match[2]; - const info = match[3]; - if (marker[0] === "`" && info.includes("`")) +function tokenRange(token) { + return { + start: { line: token.line, character: token.startChar }, + end: { line: token.line, character: token.endChar } + }; +} +function prepareRename(source, position) { + const token = tokenAt(source, position); + return token ? { range: tokenRange(token), placeholder: token.label } : null; +} +function renameEdits(uri, source, position, newName) { + const target = tokenAt(source, position); + if (!target) return null; - if (marker[0] === "%" && info.trim() !== "") + const trimmed = newName.trim(); + if (trimmed === "" || /[[\]\s]/.test(trimmed)) return null; - return marker; -} -function closesFence(line, openFence) { - const match = /^ {0,3}(`{3,}|~{3,}|%{3,})[ \t]*$/.exec(line); - if (!match) - return false; - const close = match[1]; - if (close[0] !== openFence[0]) - return false; - return openFence[0] === "%" ? close.length === openFence.length : close.length >= openFence.length; + const edits = collectTokens(source).filter((token) => token.kind === target.kind && token.label === target.label).map((token) => ({ range: tokenRange(token), newText: trimmed })); + return { changes: { [uri]: edits } }; } -// dist/hover.js -var import_node3 = __toESM(require_node3(), 1); -var rules = [ - { - pattern: /#{1,6}/g, - contents: "**Heading**\n\n`#` through `######` create section headings." - }, - { - pattern: /\*[^*\n]+\*/g, - contents: "**Bold**\n\nCarve uses single asterisks for bold text: `*bold*`." - }, - { - pattern: /\/[^/\n]+\//g, - contents: "**Italic**\n\nCarve uses slashes for italic text: `/italic/`." - }, - { - pattern: /_[^_\n]+_/g, - contents: "**Underline**\n\nCarve uses underscores for underline: `_underlined_`." - }, - { - pattern: /~[^~\n]+~/g, - contents: "**Strikethrough**\n\nCarve uses tildes for strikethrough: `~removed~`." - }, - { - pattern: /\{[^}\n]+\}/g, - contents: "**Attributes**\n\nAttach IDs, classes, and key/value pairs with `{#id .class key=value}`." - }, - { - pattern: /\[[^\]\n]+\]\([^\s)]+(?:\s+"[^"]*")?\)/g, - contents: "**Link**\n\nInline links use `[label](url)`." - }, - { - pattern: /!\[[^\]\n]*\]\([^\s)]+(?:\s+"[^"]*")?\)/g, - contents: "**Image**\n\nImages use `![alt](url)` and can be followed by captions." - }, - { - pattern: /`[^`\n]+`/g, - contents: "**Inline Code**\n\nBackticks mark inline code spans." +// dist/diagnostic-scheduler.js +var DEFAULT_DIAGNOSTIC_DELAY_MS = 120; +var DiagnosticScheduler = class { + timers = /* @__PURE__ */ new Map(); + versions = /* @__PURE__ */ new Map(); + delayMs; + run; + constructor(options) { + this.delayMs = options.delayMs ?? DEFAULT_DIAGNOSTIC_DELAY_MS; + this.run = options.run; + } + /** + * Queue analysis for `uri` at `version`, superseding any queued run for it. + * + * Superseding rather than queueing is the whole point: a run already waiting + * would otherwise publish diagnostics for text the author has since changed. + */ + schedule(uri, version) { + this.versions.set(uri, version); + const queued = this.timers.get(uri); + if (queued !== void 0) + clearTimeout(queued); + const timer = setTimeout(() => { + this.timers.delete(uri); + const latest = this.versions.get(uri); + if (latest === void 0) + return; + this.run(uri, latest); + }, this.delayMs); + this.timers.set(uri, timer); + } + /** + * Analyze `uri` now, dropping any queued run for it. + * + * For open and save, where waiting out a burst that is not happening only + * adds latency. + */ + flush(uri, version) { + const queued = this.timers.get(uri); + if (queued !== void 0) { + clearTimeout(queued); + this.timers.delete(uri); + } + this.versions.set(uri, version); + this.run(uri, version); + } + /** Forget `uri` entirely: no queued run of it will fire. */ + cancel(uri) { + const queued = this.timers.get(uri); + if (queued !== void 0) { + clearTimeout(queued); + this.timers.delete(uri); + } + this.versions.delete(uri); + } + /** Drop every queued run. */ + dispose() { + for (const timer of this.timers.values()) + clearTimeout(timer); + this.timers.clear(); + this.versions.clear(); + } + /** Is a run queued for `uri`? Test and diagnostic aid. */ + pending(uri) { + return this.timers.has(uri); + } +}; + +// dist/include-cache.js +var IncludeSourceCache = class { + maxEntries; + #entries = /* @__PURE__ */ new Map(); + constructor(maxEntries = 128) { + this.maxEntries = maxEntries; + } + get(id, mtimeMs, size) { + const entry = this.#entries.get(id); + if (!entry || entry.mtimeMs !== mtimeMs || entry.size !== size) { + if (entry) + this.#entries.delete(id); + return void 0; + } + this.#entries.delete(id); + this.#entries.set(id, entry); + return { source: entry.source, bytes: entry.bytes }; + } + set(id, mtimeMs, size, value) { + this.#entries.delete(id); + this.#entries.set(id, { ...value, mtimeMs, size }); + while (this.#entries.size > this.maxEntries) { + const oldest = this.#entries.keys().next().value; + if (oldest === void 0) + break; + this.#entries.delete(oldest); + } + } + invalidate(id) { + this.#entries.delete(id); + } + clear() { + this.#entries.clear(); + } + get size() { + return this.#entries.size; + } +}; +var IncludeParseCache = class { + maxEntries; + #entries = /* @__PURE__ */ new Map(); + constructor(maxEntries = 128) { + this.maxEntries = maxEntries; + } + get(id, version) { + const entry = this.#entries.get(id); + if (!entry || entry.version !== version) { + if (entry) + this.#entries.delete(id); + return void 0; + } + this.#entries.delete(id); + this.#entries.set(id, entry); + return entry.document; + } + set(id, version, document) { + this.#entries.delete(id); + this.#entries.set(id, { version, document }); + while (this.#entries.size > this.maxEntries) { + const oldest = this.#entries.keys().next().value; + if (oldest === void 0) + break; + this.#entries.delete(oldest); + } + } + invalidate(id) { + this.#entries.delete(id); + } + clear() { + this.#entries.clear(); + } +}; + +// dist/dependencies.js +var import_node_fs3 = require("node:fs"); +var import_node_path4 = __toESM(require("node:path"), 1); +var import_node_url4 = require("node:url"); +var DependencyIndex = class { + #byDocument = /* @__PURE__ */ new Map(); + #byPath = /* @__PURE__ */ new Map(); + update(documentUri, paths) { + const next = new Set(paths); + const previous = this.#byDocument.get(documentUri) ?? /* @__PURE__ */ new Set(); + if (same(previous, next)) + return false; + for (const target of previous) { + const documents2 = this.#byPath.get(target); + documents2?.delete(documentUri); + if (documents2?.size === 0) + this.#byPath.delete(target); + } + if (next.size === 0) + this.#byDocument.delete(documentUri); + else + this.#byDocument.set(documentUri, next); + for (const target of next) { + const documents2 = this.#byPath.get(target) ?? /* @__PURE__ */ new Set(); + documents2.add(documentUri); + this.#byPath.set(target, documents2); + } + return true; + } + remove(documentUri) { + return this.update(documentUri, []); } + documentsFor(target) { + return [...this.#byPath.get(target) ?? []]; + } + watchedPaths() { + return [...this.#byPath.keys()].sort(); + } +}; +function watcherFor(target) { + let base = import_node_path4.default.dirname(target); + while (!(0, import_node_fs3.existsSync)(base) && base !== import_node_path4.default.dirname(base)) + base = import_node_path4.default.dirname(base); + const pattern = import_node_path4.default.relative(base, target).split(import_node_path4.default.sep).map(escapeGlob).join("/"); + return { + globPattern: { + baseUri: (0, import_node_url4.pathToFileURL)(base).toString(), + pattern + } + }; +} +function escapeGlob(name) { + return name.replace(/([*?{}\[\]])/g, "[$1]"); +} +function same(left, right) { + return left.size === right.size && [...left].every((value) => right.has(value)); +} + +// dist/semantic.js +var import_node8 = __toESM(require_node3(), 1); +init_dist2(); +var semanticTokenTypes = [ + "keyword", + "string", + "comment", + "property", + "variable", + "number", + "operator", + "type" ]; -function hoverAt(source, position) { - const lines = sourceLines(source); +var semanticTokenModifiers = ["declaration", "definition", "readonly"]; +var tokenTypeIndex = new Map(semanticTokenTypes.map((type, index2) => [type, index2])); +var tokenModifierIndex = new Map(semanticTokenModifiers.map((modifier, index2) => [modifier, index2])); +function buildSemanticTokens(source, builder = new import_node8.SemanticTokensBuilder()) { + fillBuilder(builder, semanticTokens(source)); + return builder.build(); +} +function buildSemanticTokensRange(source, startLine, endLine) { + const builder = new import_node8.SemanticTokensBuilder(); + fillBuilder(builder, semanticTokens(source).filter((token) => token.line >= startLine && token.line <= endLine)); + return builder.build(); +} +function updateSemanticTokens(source, builder, previousResultId) { + builder.previousResult(previousResultId); + fillBuilder(builder, semanticTokens(source)); + return builder.buildEdits(); +} +function fillBuilder(builder, tokens) { + for (const token of tokens) { + builder.push(token.line, token.character, token.length, tokenTypeIndex.get(token.type) ?? 0, modifierMask(token.modifiers ?? [])); + } +} +function semanticTokens(source) { try { - const hover = astHoverAt(resolve(parse2(source)), position, lines); - if (hover) - return hover; + return astSemanticTokens(resolve(parse2(source)), source); } catch { + return lexicalSemanticTokens(source); } - const line = lines[position.line]; - if (line === void 0) - return null; - for (const rule of rules) { - rule.pattern.lastIndex = 0; - for (const match of line.matchAll(rule.pattern)) { - const start = match.index ?? 0; - const end = start + match[0].length; - if (position.character < start || position.character > end) - continue; - return { - contents: { - kind: import_node3.MarkupKind.Markdown, - value: rule.contents - }, - range: { - start: { line: position.line, character: start }, - end: { line: position.line, character: end } - } - }; - } - } - return null; } -function astHoverAt(doc, position, lines) { - const cursor = { - line: position.line, - character: characterToAstColumn(lines[position.line] ?? "", position.character) - 1 - }; - const matches = []; +function astSemanticTokens(doc, source) { + const tokens = []; + const lines = source.replace(/\r\n?/g, "\n").split("\n"); for (const node of doc.children) - collectBlock(matches, node, cursor); - matches.sort((a, b) => spanSize(a.pos) - spanSize(b.pos)); - const match = matches[0]; - if (!match) - return null; - return { - contents: { - kind: import_node3.MarkupKind.Markdown, - value: match.contents - }, - range: toRange(match.pos, lines) - }; + collectBlock2(tokens, lines, node); + let inFrontmatter = doc.frontmatter !== void 0 && lines[0]?.trim() === "---"; + for (let i = 0; i < lines.length; i++) { + const text = lines[i]; + if (inFrontmatter) { + const close = i > 0 && text.trim() === "---"; + pushRun(tokens, i, text, "string"); + if (close) + inFrontmatter = false; + continue; + } + const commentStart = findTrailingComment(text); + if (commentStart !== -1) { + push2(tokens, i, commentStart, text.length - commentStart, "comment"); + } + const scanText = commentStart !== -1 ? text.slice(0, commentStart) : text; + scanAstGaps(tokens, i, scanText); + } + return withoutOverlaps(tokens.sort((a, b) => a.line - b.line || a.character - b.character || b.length - a.length)); } -function collectBlock(matches, node, position) { - addMatch(matches, node.pos, position, blockContents(node)); +function collectBlock2(tokens, lines, node) { switch (node.type) { case "heading": - collectInline(matches, node.children, position); + pushLinePrefix(tokens, lines, node.pos, /^#{1,6}/, "operator"); + pushHeadingTitle(tokens, lines, node.pos); + collectInline2(tokens, lines, node.children); break; case "paragraph": - collectInline(matches, node.children, position); + collectInline2(tokens, lines, node.children); + break; + case "code_block": + case "raw_block": + pushPosition(tokens, lines, node.pos, "string"); + break; + case "comment": + pushPosition(tokens, lines, node.pos, "comment"); break; case "block_quote": - node.children.forEach((child) => collectBlock(matches, child, position)); + pushLinePrefix(tokens, lines, node.pos, /^\s*>+/, "operator"); + for (const child of node.children) + collectBlock2(tokens, lines, child); break; case "list": - node.items.forEach((item) => item.children.forEach((child) => collectBlock(matches, child, position))); + pushLinePrefix(tokens, lines, node.pos, LIST_MARKER_ONLY, "operator"); + for (const item2 of node.items) { + for (const child of item2.children) + collectBlock2(tokens, lines, child); + } break; case "admonition": + pushLinePrefix(tokens, lines, node.pos, /^\s*:{3,}\s*[A-Za-z][\w-]*/, "type"); + for (const child of node.children) + collectBlock2(tokens, lines, child); + if (node.title) + collectInline2(tokens, lines, node.title); + break; case "div": - node.children.forEach((child) => collectBlock(matches, child, position)); - if (node.type === "admonition" && node.title) - collectInline(matches, node.title, position); + pushLinePrefix(tokens, lines, node.pos, /^\s*:{3,}/, "operator"); + for (const child of node.children) + collectBlock2(tokens, lines, child); break; case "definition_list": - node.items.forEach((item) => { - item.terms.forEach((term) => collectInline(matches, term, position)); - item.definitions.forEach((definition) => definition.forEach((child) => collectBlock(matches, child, position))); - }); + for (const item2 of node.items) { + for (const term of item2.terms) + collectInline2(tokens, lines, term); + for (const definition of item2.definitions) { + for (const child of definition) + collectBlock2(tokens, lines, child); + } + } break; case "figure": - collectBlock(matches, node.target, position); - collectInline(matches, node.caption, position); + collectFigureTarget(tokens, lines, node.target); + collectInline2(tokens, lines, node.caption); + break; + // A composite figure (PART 9 §4c): one figure of ordered panels, opened by a + // BARE `::: figure` fence. Its opener carries the reserved kind word, so the + // prefix is scoped `type` exactly as an admonition's is - the two are the + // same shape on the line and a client colouring one should colour the other. + // The caption is the group's, and it sits AFTER the closing fence rather than + // inside the container, which is why it is collected here beside the children + // and not from any one of them. + case "figure_group": + pushLinePrefix(tokens, lines, node.pos, /^\s*:{3,}\s*figure/, "type"); + for (const child of node.children) + collectBlock2(tokens, lines, child); + if (node.caption) + collectInline2(tokens, lines, node.caption); break; case "table": + if (node.pos) { + for (let line2 = node.pos.startLine - 1; line2 < node.pos.endLine; line2 += 1) { + scanTableLine(tokens, line2, lines[line2] ?? ""); + } + } if (node.caption) - collectInline(matches, node.caption, position); - node.rows.forEach((row) => row.cells.forEach((cell) => collectInline(matches, cell.children, position))); + collectInline2(tokens, lines, node.caption); + for (const row of node.rows) { + for (const cell of row.cells) + collectInline2(tokens, lines, cell.children); + } + break; + case "image": + pushPosition(tokens, lines, node.pos, "string"); + break; + case "thematic_break": + pushPosition(tokens, lines, node.pos, "operator"); break; + case "abbreviation_def": + pushPosition(tokens, lines, node.pos, "property"); + break; + } +} +function scanTableLine(tokens, line2, text) { + for (const pipe of text.matchAll(/\|/g)) + push2(tokens, line2, pipe.index, 1, "operator"); + for (const marker of text.matchAll(/\|=?\s*([<>~^v]{1,2})(?=\{| )/g)) { + const run = marker[1]; + push2(tokens, line2, marker.index + marker[0].indexOf(run), run.length, "keyword"); + } + for (const attr of text.matchAll(/\b(aligns|valigns|widths|footer-rows|header-rows|header-cols)=/g)) { + push2(tokens, line2, attr.index, attr[1].length, "property"); } } -function collectInline(matches, nodes, position) { +function collectFigureTarget(tokens, lines, node) { + if (node.type === "image") + pushPosition(tokens, lines, node.pos, "string"); + else + collectBlock2(tokens, lines, node); +} +function collectInline2(tokens, lines, nodes) { for (const node of nodes) { - addMatch(matches, node.pos, position, inlineContents(node)); + if (node.type === "footnote_ref" || node.type === "inline_footnote") { + pushPosition(tokens, lines, node.pos, "variable", ["readonly"]); + continue; + } + if (node.type === "critic_comment") { + pushPosition(tokens, lines, node.pos, "comment"); + continue; + } + switch (node.type) { + case "text": + case "soft_break": + case "hard_break": + break; + case "code": + case "math": + case "literal_inline": + case "raw_inline": + case "link": + case "image": + case "autolink": + case "heading_ref": + pushPosition(tokens, lines, node.pos, "string"); + break; + case "mention": + case "tag": + case "symbol": + case "footnote_ref": + case "inline_footnote": + case "abbreviation": + pushPosition(tokens, lines, node.pos, "variable", ["readonly"]); + break; + case "span": + case "inline_extension": + pushPosition(tokens, lines, node.pos, "property"); + break; + case "insert": + pushPosition(tokens, lines, node.pos, "type"); + break; + case "delete": + case "critic_comment": + pushPosition(tokens, lines, node.pos, "comment"); + break; + case "substitution": + pushPosition(tokens, lines, node.pos, "keyword"); + break; + case "comment": + break; + default: + pushPosition(tokens, lines, node.pos, "keyword"); + break; + } const children = node.children; if (Array.isArray(children)) - collectInline(matches, children, position); + collectInline2(tokens, lines, children); const content = node.content; if (Array.isArray(content)) - collectInline(matches, content, position); + collectInline2(tokens, lines, content); } } -function addMatch(matches, pos, position, contents) { - if (!contents || !pos || !contains(pos, position)) +function pushPosition(tokens, lines, pos, type, modifiers = []) { + if (pos?.startLine === void 0 || pos.endLine === void 0 || pos.startColumn === void 0 || pos.endColumn === void 0) { return; - matches.push({ pos, contents }); + } + for (let line2 = pos.startLine; line2 <= pos.endLine; line2++) { + const text = lines[line2 - 1] ?? ""; + const start = line2 === pos.startLine ? astColumnToCharacter(text, pos.startColumn) : 0; + const end = line2 === pos.endLine ? astColumnToCharacter(text, pos.endColumn) : text.length; + push2(tokens, line2 - 1, start, Math.max(0, end - start), type, modifiers); + } } -function blockContents(node) { - switch (node.type) { - case "heading": - return "**Heading**\n\n`#` through `######` create section headings."; - case "code_block": - return "**Code Block**\n\nTriple backtick or tilde fences create verbatim code blocks."; - case "raw_block": - return "**Raw Block**\n\nRaw passthrough blocks render only for matching output formats."; - case "block_quote": - return "**Block Quote**\n\nLines beginning with `>` create quoted blocks."; - case "list": - return "**List**\n\nUse bullets, task markers, or ordered markers for lists."; - case "table": - return "**Table**\n\nPipe-delimited rows create tables."; - case "admonition": - return "**Admonition**\n\nTyped `:::` fences create admonition blocks."; - case "div": - return "**Div**\n\nBare `:::` fences create generic container blocks."; - default: - return null; +function pushLinePrefix(tokens, lines, pos, pattern, type) { + if (!pos?.startLine) + return; + const line2 = lines[pos.startLine - 1] ?? ""; + const match = pattern.exec(line2); + if (!match) + return; + push2(tokens, pos.startLine - 1, match.index, match[0].length, type); +} +function pushHeadingTitle(tokens, lines, pos) { + if (!pos?.startLine) + return; + const line2 = lines[pos.startLine - 1] ?? ""; + const match = /^(#{1,6})(\s+)(.*)$/.exec(line2); + if (!match) + return; + push2(tokens, pos.startLine - 1, match[1].length + match[2].length, match[3].length, "type", [ + "definition" + ]); +} +var DEF_SEPARATOR = String.raw`\]: [ \t]*`; +var QUOTE_PREFIX = /^([ \t]*>+)(?: |$)/; +var LIST_MARKER_ONLY = /^[ \t]*(?:[-*]|\(?[0-9A-Za-z]+[.)])/; +var LIST_PREFIX = /^([ \t]*)([-*]|\(?[0-9]+[.)]|\(?[A-Za-z][.)]) +(\[[ xX\-_>?]\] +(?=\S))?/; +function scanAstGaps(tokens, line2, text) { + const fnDef = new RegExp(String.raw`^(\[\^)([^\]\n]+)(` + DEF_SEPARATOR + String.raw`)(.*)`).exec(text); + if (fnDef) { + push2(tokens, line2, fnDef.index, 2, "operator"); + push2(tokens, line2, fnDef.index + 2, fnDef[2].length, "type"); + push2(tokens, line2, fnDef.index + 2 + fnDef[2].length, fnDef[3].length, "operator"); + return; + } + const refDef = new RegExp(String.raw`^(\[)([^\]\n]+)(` + DEF_SEPARATOR + String.raw`)(\S+)`).exec(text); + if (refDef) { + push2(tokens, line2, refDef.index, 1, "operator"); + push2(tokens, line2, refDef.index + 1, refDef[2].length, "type"); + push2(tokens, line2, refDef.index + 1 + refDef[2].length, refDef[3].length, "operator"); + push2(tokens, line2, refDef.index + refDef[0].length - refDef[4].length, refDef[4].length, "string"); + return; } + scan(tokens, line2, text, /\{=[^=\n]*=\}/g, "keyword"); + scan(tokens, line2, text, /\$\$[^$\n]+\$\$/g, "string"); + scan(tokens, line2, text, /\$[^$\n]+\$/g, "string"); } -function inlineContents(node) { - switch (node.type) { - case "strong": - return "**Bold**\n\nCarve uses single asterisks for bold text: `*bold*`."; - case "emphasis": - return "**Italic**\n\nCarve uses slashes for italic text: `/italic/`."; - case "underline": - return "**Underline**\n\nCarve uses underscores for underline: `_underlined_`."; - case "strike": - return "**Strikethrough**\n\nCarve uses tildes for strikethrough: `~removed~`."; - case "subscript": - return "**Subscript**\n\nCarve subscript uses the braced form `{,text,}`, e.g. `H{,2,}O`. A bare comma is literal text."; - case "superscript": - return "**Superscript**\n\nCarve superscript uses the braced form `{^text^}`, e.g. `E=mc{^2^}`. A bare caret is literal text."; - case "highlight": - return "**Highlight**\n\nCarve highlight is a single equals: `=marked=` (use the forced form `{=marked=}` intraword)."; - case "code": - return "**Inline Code**\n\nBackticks mark inline code spans."; - case "literal_inline": - return "**Inline Literal**\n\nA `!` prefix on a verbatim span renders its content as ordinary prose, without code styling: `` !`/kaet/` ``. Mirrors the `$`-math prefix."; - case "link": - return "**Link**\n\nInline links use `[label](url)` or reference-link syntax."; - case "image": - return "**Image**\n\nImages use `![alt](url)` and can be followed by captions."; - case "mention": - return "**Mention**\n\nMentions use `@name`."; - case "tag": - return "**Tag**\n\nTags use `#name`."; - case "span": - return "**Span**\n\nInline spans use `[text]{attrs}`."; - default: - return null; +function lexicalSemanticTokens(source) { + const tokens = []; + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + let inFence; + let inFrontmatter = lines[0]?.trim() === "---"; + for (let line2 = 0; line2 < lines.length; line2++) { + const text = lines[line2]; + if (inFrontmatter) { + const close = line2 > 0 && text.trim() === "---"; + pushRun(tokens, line2, text, "string"); + if (close) + inFrontmatter = false; + continue; + } + if (inFence) { + pushRun(tokens, line2, text, inFence.type); + if (new RegExp(`^\\s*${escapeRegExp3(inFence.marker)}\\s*$`).test(text)) { + inFence = void 0; + } + continue; + } + const commentBlock = /^%{3,}\s*$/.exec(text); + if (commentBlock) { + pushRun(tokens, line2, text, "comment"); + inFence = { marker: commentBlock[0].trim(), type: "comment" }; + continue; + } + if (/^%%/.test(text)) { + pushRun(tokens, line2, text, "comment"); + continue; + } + const trailingCommentStart = findTrailingComment(text); + const scanText = trailingCommentStart !== -1 ? text.slice(0, trailingCommentStart) : text; + if (trailingCommentStart !== -1) { + push2(tokens, line2, trailingCommentStart, text.length - trailingCommentStart, "comment"); + } + const codeFence = /^(\s*)(`{3,}|~{3,})(?:\s+([A-Za-z0-9_-]+))?/.exec(scanText); + if (codeFence) { + push2(tokens, line2, codeFence[1].length, codeFence[2].length, "operator"); + if (codeFence[3]) { + push2(tokens, line2, codeFence.index + codeFence[0].lastIndexOf(codeFence[3]), codeFence[3].length, "type"); + } + inFence = { marker: codeFence[2], type: "string" }; + continue; + } + const rawFence = /^(\s*)(%{3,})(?:\s+([A-Za-z0-9_-]+))?/.exec(scanText); + if (rawFence) { + push2(tokens, line2, rawFence[1].length, rawFence[2].length, "operator"); + if (rawFence[3]) { + push2(tokens, line2, rawFence.index + rawFence[0].lastIndexOf(rawFence[3]), rawFence[3].length, "type"); + } + inFence = { marker: rawFence[2], type: "string" }; + continue; + } + const heading = /^(#{1,6})(\s+)(.+)$/.exec(scanText); + if (heading) { + push2(tokens, line2, 0, heading[1].length, "operator"); + push2(tokens, line2, heading[1].length + heading[2].length, heading[3].length, "type", ["definition"]); + scanInline2(tokens, line2, scanText); + continue; + } + const div = /^(\s*)(:{3,})(?:\s+([A-Za-z][\w-]*))?/.exec(scanText); + if (div) { + push2(tokens, line2, div[1].length, div[2].length, "operator"); + if (div[3]) + push2(tokens, line2, div[0].lastIndexOf(div[3]), div[3].length, "type"); + } + const list = LIST_PREFIX.exec(scanText); + if (list) { + push2(tokens, line2, list[1].length, list[2].length, "operator"); + if (list[3]) + push2(tokens, line2, list[1].length + list[2].length + 1, list[3].trimEnd().length, "keyword"); + } + const quote = QUOTE_PREFIX.exec(scanText); + if (quote) + push2(tokens, line2, quote[1].search(/>/), quote[1].trimStart().length, "operator"); + const fnDef = new RegExp(String.raw`^(\[\^)([^\]\n]+)(` + DEF_SEPARATOR + String.raw`)(.*)`).exec(scanText); + if (fnDef) { + push2(tokens, line2, fnDef.index, 2, "operator"); + push2(tokens, line2, fnDef.index + 2, fnDef[2].length, "type"); + push2(tokens, line2, fnDef.index + 2 + fnDef[2].length, fnDef[3].length, "operator"); + continue; + } + const refDef = new RegExp(String.raw`^(\[)([^\]\n]+)(` + DEF_SEPARATOR + String.raw`)(\S+)`).exec(scanText); + if (refDef) { + push2(tokens, line2, refDef.index, 1, "operator"); + push2(tokens, line2, refDef.index + 1, refDef[2].length, "type"); + push2(tokens, line2, refDef.index + 1 + refDef[2].length, refDef[3].length, "operator"); + push2(tokens, line2, refDef.index + refDef[0].length - refDef[4].length, refDef[4].length, "string"); + continue; + } + const abbrDef = new RegExp(String.raw`^(\*\[)([^\]\n]+)(` + DEF_SEPARATOR + String.raw`)(.*)`).exec(scanText); + if (abbrDef) { + push2(tokens, line2, abbrDef.index, 2, "operator"); + push2(tokens, line2, abbrDef.index + 2, abbrDef[2].length, "property"); + push2(tokens, line2, abbrDef.index + 2 + abbrDef[2].length, abbrDef[3].length, "operator"); + continue; + } + scanInline2(tokens, line2, scanText); } + return withoutOverlaps(tokens.sort((a, b) => a.line - b.line || a.character - b.character || b.length - a.length)); } -function contains(pos, position) { - if (pos.startColumn === void 0 || pos.endColumn === void 0 || position.line + 1 < pos.startLine || position.line + 1 > pos.endLine) { - return false; +function scanInline2(tokens, line2, text) { + scan(tokens, line2, text, /`[^`\n]+`/g, "string"); + scan(tokens, line2, text, /\$\$[^$\n]+\$\$/g, "string"); + scan(tokens, line2, text, /\$[^$\n]+\$/g, "string"); + scan(tokens, line2, text, /!\[[^\]\n]*\]\([^\s)]+(?:\s+"[^"]*")?\)/g, "string"); + scan(tokens, line2, text, /\[[^\]\n]+\]\([^\s)]+(?:\s+"[^"]*")?\)/g, "string"); + scan(tokens, line2, text, /\[\^[^\]\n]+\]/g, "variable"); + scan(tokens, line2, text, /(?[^~\n]*~\}/g, "keyword"); + scan(tokens, line2, text, /\{=[^=\n]*=\}/g, "keyword"); + scan(tokens, line2, text, /\{#[^#\n]*#\}/g, "comment"); + scan(tokens, line2, text, /\{[^}\n]+\}/g, "property"); + scan(tokens, line2, text, /\\./g, "operator"); + scan(tokens, line2, text, /(\*\*\*[^*\n]+\*\*\*|\*[^*\n]+\*|\/[^/\n]+\/|_[^_\n]+_|~[^~\n]+~|\+\+[^+\n]+\+\+|--[^-\n]+--|(? pos.endColumn) - return false; - return true; } -function toRange(pos, lines) { - return { - start: { - line: pos.startLine - 1, - character: astColumnToCharacter(lines[pos.startLine - 1] ?? "", pos.startColumn ?? 1) - }, - end: { - line: pos.endLine - 1, - character: astColumnToCharacter(lines[pos.endLine - 1] ?? "", pos.endColumn ?? 1) +function pushRun(tokens, line2, text, type) { + if (text.length > 0) + push2(tokens, line2, 0, text.length, type); +} +function push2(tokens, line2, character, length, type, modifiers = []) { + if (length <= 0) + return; + tokens.push({ line: line2, character, length, type, modifiers }); +} +function modifierMask(modifiers) { + let mask = 0; + for (const modifier of modifiers) { + const index2 = tokenModifierIndex.get(modifier); + if (index2 !== void 0) + mask |= 1 << index2; + } + return mask; +} +function findTrailingComment(text) { + let inCode = false; + for (let i = 0; i < text.length; i++) { + const ch = text[i]; + if (ch === "`") { + inCode = !inCode; + continue; + } + if (inCode) + continue; + if (ch === "\\") { + i++; + continue; + } + if (ch === "%" && text[i + 1] === "%") { + const prev = i > 0 ? text[i - 1] : ""; + if (prev === " " || prev === " ") { + return i; + } } - }; + } + return -1; } -function spanSize(pos) { - if (pos.startOffset !== void 0 && pos.endOffset !== void 0) - return pos.endOffset - pos.startOffset; - return (pos.endLine - pos.startLine) * 1e3 + ((pos.endColumn ?? 1) - (pos.startColumn ?? 1)); +function escapeRegExp3(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +function withoutOverlaps(tokens) { + const filtered = []; + for (const token of tokens) { + const previous = filtered[filtered.length - 1]; + if (previous && previous.line === token.line && token.character < previous.character + previous.length) { + continue; + } + filtered.push(token); + } + return filtered; } -// dist/migration-actions.js -var import_node4 = __toESM(require_node3(), 1); -function normalize(source) { - return source.replace(/\r\n?/g, "\n"); +// dist/document-links.js +function documentLinks(uri, source) { + const links = []; + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + for (let line2 = 0; line2 < lines.length; line2 += 1) { + const text = lines[line2]; + for (const match of text.matchAll(/!?\[[^\]]*\]\(([^\s)]+)(?:\s+"[^"]*")?\)/g)) { + add(links, uri, match[1], line2, match.index + match[0].indexOf(match[1])); + } + for (const match of text.matchAll(/<((?:https?|mailto):[^>]+)>/g)) { + add(links, uri, match[1], line2, match.index + 1); + } + const definition = /^(?: {0,3})\[[^\]]+\]: ([^\s]+)(?:\s+"[^"]*")?/.exec(text); + if (definition) + add(links, uri, definition[1], line2, text.indexOf(definition[1])); + } + return links; } -function migrationFixes(source) { - const norm = normalize(source); - return djotMigrationWarnings(source).map((warning) => ({ - rule: warning.rule, - range: import_node4.Range.create(positionAt2(norm, warning.start), positionAt2(norm, warning.end)), - suggestion: warning.suggestion +function add(links, uri, destination, line2, character) { + let target; + try { + target = new URL(destination, uri).toString(); + } catch { + return; + } + links.push({ + target, + tooltip: `Open ${destination}`, + range: { + start: { line: line2, character }, + end: { line: line2, character: character + destination.length } + } + }); +} + +// dist/document-highlights.js +var import_node9 = __toESM(require_node3(), 1); +function documentHighlights(uri, source, position) { + const tokens = scanDocument(uri, source); + const target = tokens.find((token) => token.range.start.line === position.line && position.character >= token.range.start.character && position.character <= token.range.end.character); + if (!target) + return []; + return tokens.filter((token) => token.kind === target.kind && token.key.toLocaleLowerCase() === target.key.toLocaleLowerCase()).map((token) => ({ + range: token.range, + kind: token.declaration ? import_node9.DocumentHighlightKind.Write : import_node9.DocumentHighlightKind.Read })); } -function migrationCodeActions(uri, source, diagnostics) { - const fixes = migrationFixes(source); - const actions = []; - for (const diagnostic of diagnostics) { - if (typeof diagnostic.code !== "string") - continue; - const fix = fixes.find((candidate) => candidate.rule === diagnostic.code && candidate.range.start.line === diagnostic.range.start.line && candidate.range.start.character === diagnostic.range.start.character); - if (!fix) - continue; - actions.push({ - title: `Convert to Carve syntax: ${fix.suggestion}`, - kind: import_node4.CodeActionKind.QuickFix, - diagnostics: [diagnostic], - edit: { - changes: { - [uri]: [import_node4.TextEdit.replace(fix.range, fix.suggestion)] - } - }, - isPreferred: true + +// dist/inlay-hints.js +var import_node10 = __toESM(require_node3(), 1); +init_dist2(); +function inlayHints(source, requested) { + const hints = []; + try { + const doc = resolve(parse2(source, { positions: true })); + walk(doc.children, (node) => { + if (node.type !== "heading" || !node.pos || !node.attrs?.id) + return; + const line2 = node.pos.startLine - 1; + if (requested && (line2 < requested.start.line || line2 > requested.end.line)) + return; + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + const text = lines[line2] ?? ""; + if (text.includes(`{#${node.attrs.id}`) || (lines[line2 - 1] ?? "").includes(`#${node.attrs.id}`)) + return; + hints.push({ + position: { line: line2, character: text.length }, + label: ` #${node.attrs.id}`, + kind: import_node10.InlayHintKind.Type, + paddingLeft: true, + tooltip: "Generated heading id" + }); }); + } catch { + return []; } - const fixAll = migrationFixAllAction(uri, source); - if (fixAll) - actions.push(fixAll); - return actions; + return hints; } -function migrationFixAllAction(uri, source) { - const { output, applied } = applyMigrationFixes(source); - if (applied.length === 0) - return null; - const norm = normalize(source); - const fullRange = import_node4.Range.create(positionAt2(norm, 0), positionAt2(norm, norm.length)); - const n = applied.length; - return { - title: `Fix all Carve migration collisions (${n})`, - kind: import_node4.CodeActionKind.SourceFixAll, - edit: { - changes: { - [uri]: [import_node4.TextEdit.replace(fullRange, output)] - } - } - }; +function walk(nodes, visit4) { + for (const node of nodes) { + visit4(node); + if ("children" in node && Array.isArray(node.children)) + walk(node.children.filter(isBlock), visit4); + } } -function positionAt2(source, offset) { - const before = source.slice(0, offset); - const line = before.split("\n").length - 1; - const lastNewline = before.lastIndexOf("\n"); - return { - line, - character: offset - lastNewline - 1 - }; +function isBlock(value) { + return Boolean(value && typeof value === "object" && "type" in value); } -// dist/rename.js -function collectTokens(source) { - const tokens = []; - const lines = source.split(/\r?\n/); - lines.forEach((line, lineNo) => { - for (const m of line.matchAll(/\[\^([^\]\s]+)\]/g)) { - const start = m.index + 2; - tokens.push({ kind: "footnote", label: m[1], line: lineNo, startChar: start, endChar: start + m[1].length }); +// dist/selection.js +function selectionRanges(uri, source, positions) { + const lines = source.replace(/\r\n?/g, "\n").split("\n"); + const tokens = scanDocument(uri, source); + return positions.map((position) => { + const lineText = lines[position.line] ?? ""; + const lineRange = { + start: { line: position.line, character: 0 }, + end: { line: position.line, character: lineText.length } + }; + const documentRange = { + start: { line: 0, character: 0 }, + end: { line: Math.max(0, lines.length - 1), character: lines.at(-1)?.length ?? 0 } + }; + const parent = { range: lineRange, parent: { range: documentRange } }; + const token = tokens.find((candidate) => contains4(candidate.range, position)); + if (token) + return { range: token.range, parent }; + const word = wordRange(lineText, position); + return word ? { range: word, parent } : parent; + }); +} +function contains4(range, position) { + return position.line === range.start.line && position.character >= range.start.character && position.character <= range.end.character; +} +function wordRange(line2, position) { + for (const match of line2.matchAll(/[\p{L}\p{N}_-]+/gu)) { + const start = match.index; + const end = start + match[0].length; + if (position.character >= start && position.character <= end) { + return { start: { line: position.line, character: start }, end: { line: position.line, character: end } }; } - const def = /^( {0,3})\[([^\]]+)\]:/.exec(line); - if (def && !def[2].startsWith("^")) { - const start = def[1].length + 1; - tokens.push({ kind: "linkref", label: def[2], line: lineNo, startChar: start, endChar: start + def[2].length }); + } + return null; +} + +// dist/workspace-loader.js +var import_node_fs4 = require("node:fs"); +var import_node_path5 = __toESM(require("node:path"), 1); +var import_node_url5 = require("node:url"); +function indexWorkspace(index2, roots, limits = {}) { + const maxFiles = limits.maxFiles ?? 1e4; + const maxBytes = limits.maxBytes ?? 64 * 1024 * 1024; + let files = 0; + let bytes = 0; + let truncated = false; + const pending = [...roots]; + while (pending.length > 0) { + const directory = pending.pop(); + let entries; + try { + entries = (0, import_node_fs4.readdirSync)(directory, { withFileTypes: true }); + } catch { + continue; } - for (const m of line.matchAll(/\]\[([^\]]+)\]/g)) { - if (m[1].startsWith("^")) + for (const entry of entries) { + if (entry.name === ".git" || entry.name === "node_modules") continue; - const start = m.index + 2; - tokens.push({ kind: "linkref", label: m[1], line: lineNo, startChar: start, endChar: start + m[1].length }); + const absolute = import_node_path5.default.join(directory, entry.name); + if (entry.isDirectory()) { + pending.push(absolute); + continue; + } + if (!entry.isFile() || !entry.name.endsWith(".crv")) + continue; + if (files >= maxFiles) { + truncated = true; + return { files, bytes, truncated }; + } + try { + const size = (0, import_node_fs4.statSync)(absolute).size; + if (bytes + size > maxBytes) { + truncated = true; + return { files, bytes, truncated }; + } + index2.update((0, import_node_url5.pathToFileURL)(absolute).toString(), (0, import_node_fs4.readFileSync)(absolute, "utf8"), `disk:${(0, import_node_fs4.statSync)(absolute).mtimeMs}`); + files += 1; + bytes += size; + } catch { + } } - }); - return tokens; + } + return { files, bytes, truncated }; } -function tokenAt(source, position) { - for (const token of collectTokens(source)) { - if (token.line === position.line && position.character >= token.startChar && position.character <= token.endChar) { - return token; + +// dist/server.js +var import_node_fs7 = require("node:fs"); + +// dist/versioned-cache.js +var VersionedCache = class { + #entries = /* @__PURE__ */ new Map(); + get(uri, version) { + const entry = this.#entries.get(uri); + return entry?.version === version ? entry.value : void 0; + } + set(uri, version, value) { + this.#entries.set(uri, { version, value }); + return value; + } + getOrCreate(uri, version, create) { + return this.get(uri, version) ?? this.set(uri, version, create()); + } + remove(uri) { + this.#entries.delete(uri); + } + clear() { + this.#entries.clear(); + } +}; + +// dist/include-completion.js +var import_node_fs5 = require("node:fs"); +var import_node_path6 = __toESM(require("node:path"), 1); +var import_node11 = __toESM(require_node3(), 1); +function includeCompletions(source, position, options) { + if (!options?.sourcePath || !options.includeRoot) + return []; + const line2 = source.replace(/\r\n?/g, "\n").split("\n")[position.line] ?? ""; + const prefix = line2.slice(0, position.character); + const match = /\{\{\s*([^\s}@]*)$/.exec(prefix); + if (!match) + return []; + const authored = match[1]; + const [filePart, fragment] = authored.split("#", 2); + const root = realpathSafe(options.includeRoot); + if (!root) + return []; + const base = import_node_path6.default.resolve(import_node_path6.default.dirname(options.sourcePath), import_node_path6.default.dirname(filePart || ".")); + const contained = realpathSafe(base); + if (!contained || !isInside(root, contained)) + return []; + const replaceStart = position.character - (fragment === void 0 ? import_node_path6.default.basename(filePart) : fragment).length; + if (fragment !== void 0) { + const target = realpathSafe(import_node_path6.default.resolve(import_node_path6.default.dirname(options.sourcePath), filePart)); + if (!target || !isInside(root, target)) + return []; + let targetSource; + try { + targetSource = (0, import_node_fs5.readFileSync)(target, "utf8"); + } catch { + return []; } + return scanDocument(target, targetSource).filter((token) => token.kind === "heading" && token.declaration).map((token) => item(token.key, import_node11.CompletionItemKind.Reference, position, replaceStart, "Section in included file")); } - return null; + const partial = import_node_path6.default.basename(filePart); + let entries; + try { + entries = (0, import_node_fs5.readdirSync)(contained, { withFileTypes: true }); + } catch { + return []; + } + return entries.filter((entry) => entry.name.startsWith(partial) && (entry.isDirectory() || entry.name.endsWith(".crv"))).map((entry) => item(entry.name + (entry.isDirectory() ? "/" : ""), entry.isDirectory() ? import_node11.CompletionItemKind.Folder : import_node11.CompletionItemKind.File, position, replaceStart, "Contained include path")); } -function tokenRange(token) { +function item(label, kind2, position, start, detail) { + return { label, kind: kind2, detail, textEdit: { + range: { start: { line: position.line, character: start }, end: position }, + newText: label + } }; +} +function realpathSafe(value) { + try { + return (0, import_node_fs5.realpathSync)(value); + } catch { + return null; + } +} +function isInside(root, target) { + const relative = import_node_path6.default.relative(root, target); + return relative === "" || !import_node_path6.default.isAbsolute(relative) && !relative.split(import_node_path6.default.sep).includes(".."); +} + +// dist/settings.js +var import_node_fs6 = require("node:fs"); +var import_node_path7 = __toESM(require("node:path"), 1); +var DEFAULT_CARVE_SETTINGS = { + platforms: [], + extensions: [], + inlayHints: true, + formatter: "conservative", + severities: {} +}; +function readCarveSettings(raw) { + const carve = raw?.carve; + if (!carve) + return DEFAULT_CARVE_SETTINGS; + const platforms = Array.isArray(carve["platforms"]) ? carve["platforms"].filter((value) => value === "github") : []; + const extensions = Array.isArray(carve["extensions"]) ? carve["extensions"].filter((value) => typeof value === "string") : []; return { - start: { line: token.line, character: token.startChar }, - end: { line: token.line, character: token.endChar } + platforms, + extensions, + inlayHints: carve["inlayHints"] !== false, + formatter: carve["formatter"] === "migration" ? "migration" : "conservative", + severities: severitySettings(carve["severities"]) }; } -function prepareRename(source, position) { - const token = tokenAt(source, position); - return token ? { range: tokenRange(token), placeholder: token.label } : null; +function severitySettings(value) { + if (!value || typeof value !== "object" || Array.isArray(value)) + return {}; + const allowed = /* @__PURE__ */ new Set(["error", "warning", "information", "hint", "off"]); + return Object.fromEntries(Object.entries(value).filter((entry) => allowed.has(String(entry[1])))); } -function renameEdits(uri, source, position, newName) { - const target = tokenAt(source, position); - if (!target) - return null; - const trimmed = newName.trim(); - if (trimmed === "" || /[[\]\s]/.test(trimmed)) - return null; - const edits = collectTokens(source).filter((token) => token.kind === target.kind && token.label === target.label).map((token) => ({ range: tokenRange(token), newText: trimmed })); - return { changes: { [uri]: edits } }; +function readProjectSettings(roots) { + for (const root of roots) { + try { + const parsed = JSON.parse((0, import_node_fs6.readFileSync)(import_node_path7.default.join(root, ".carverc.json"), "utf8")); + return readCarveSettings(parsed); + } catch (error) { + const code = error.code; + if (code === "ENOENT") + continue; + return null; + } + } + return null; } // dist/server.js -var connection = (0, import_node5.createConnection)(import_node5.ProposedFeatures.all); -var documents = new import_node5.TextDocuments(TextDocument); -connection.onInitialize(() => ({ - capabilities: { - textDocumentSync: import_node5.TextDocumentSyncKind.Incremental, - documentSymbolProvider: true, - hoverProvider: true, - codeActionProvider: true, - documentFormattingProvider: true, - foldingRangeProvider: true, - definitionProvider: true, - referencesProvider: true, - renameProvider: { prepareProvider: true }, - codeLensProvider: { resolveProvider: false }, - completionProvider: { - triggerCharacters: [":", "#", "^", "["] - } - // Semantic tokens are intentionally NOT advertised. Editor colouring is owned by the - // TextMate grammar (carve-grammars / the intellij-carve bundle); a second semantic-token - // layer over the same text only duplicated and fought it - clients merged the two and - // painted partial/incorrect ranges (a `{#top}` id showing as a hashtag, etc.). The - // builder in ./semantic.ts is kept (and tested) for any consumer that opts in explicitly. - } -})); -documents.onDidOpen((event) => validate(event.document)); -documents.onDidChangeContent((event) => validate(event.document)); +var connection = (0, import_node12.createConnection)(import_node12.ProposedFeatures.all); +var documents = new import_node12.TextDocuments(TextDocument); +var includeSettings = DEFAULT_INCLUDE_SETTINGS; +var carveSettings = DEFAULT_CARVE_SETTINGS; +var workspaceTrusted = false; +var workspaceRoots = []; +var clientOwnsCarveSettings = false; +var includeCache = new IncludeSourceCache(); +var includeParseCache = new IncludeParseCache(); +var dependencyIndex = new DependencyIndex(); +var workspaceIndex = new WorkspaceIndex(); +var semanticBuilders = /* @__PURE__ */ new Map(); +var analysisCache = new VersionedCache(); +var watcherRegistration; +var watcherRefresh = Promise.resolve(); +connection.onInitialize((params) => { + includeSettings = readIncludeSettings(params.initializationOptions); + workspaceTrusted = readWorkspaceTrusted(params.initializationOptions); + const folders = (params.workspaceFolders ?? []).map((folder) => fsPath(folder.uri)); + const legacyRoot = params.rootUri != null ? fsPath(params.rootUri) : void 0; + workspaceRoots = [...folders, legacyRoot].filter((root) => root !== void 0); + clientOwnsCarveSettings = Boolean(params.initializationOptions?.carve); + carveSettings = clientOwnsCarveSettings ? readCarveSettings(params.initializationOptions) : readProjectSettings(workspaceRoots) ?? DEFAULT_CARVE_SETTINGS; + return { + capabilities: { + textDocumentSync: import_node12.TextDocumentSyncKind.Incremental, + documentSymbolProvider: true, + workspaceSymbolProvider: true, + hoverProvider: true, + codeActionProvider: true, + documentFormattingProvider: true, + documentRangeFormattingProvider: true, + documentOnTypeFormattingProvider: { firstTriggerCharacter: "\n" }, + foldingRangeProvider: true, + definitionProvider: true, + documentLinkProvider: { resolveProvider: false }, + documentHighlightProvider: true, + selectionRangeProvider: true, + inlayHintProvider: true, + executeCommandProvider: { commands: ["carve.previewHtml", "carve.showAst"] }, + referencesProvider: true, + renameProvider: { prepareProvider: true }, + codeLensProvider: { resolveProvider: false }, + completionProvider: { + triggerCharacters: [":", "#", "^", "[", "@", "{"] + }, + semanticTokensProvider: { + legend: { + tokenTypes: [...semanticTokenTypes], + tokenModifiers: [...semanticTokenModifiers] + }, + full: { delta: true }, + range: true + }, + diagnosticProvider: { + identifier: "carve", + interFileDependencies: true, + workspaceDiagnostics: false + } + } + }; +}); +connection.onInitialized(() => { + void connection.client.register(import_node12.DidChangeConfigurationNotification.type, void 0); + const loaded = indexWorkspace(workspaceIndex, workspaceRoots); + if (loaded.truncated) + connection.console.warn(`Carve workspace index stopped at ${loaded.files} files / ${loaded.bytes} bytes.`); + void connection.client.register(import_node12.DidChangeWatchedFilesNotification.type, { + watchers: [{ globPattern: "**/*.crv" }, { globPattern: "**/.carverc.json" }] + }); +}); +connection.onDidChangeConfiguration((change2) => { + includeSettings = readIncludeSettings(change2.settings); + const supplied = Boolean(change2.settings?.carve); + if (supplied) + clientOwnsCarveSettings = true; + carveSettings = supplied || clientOwnsCarveSettings ? readCarveSettings(change2.settings) : readProjectSettings(workspaceRoots) ?? DEFAULT_CARVE_SETTINGS; + analysisCache.clear(); + for (const document of documents.all()) + diagnostics.schedule(document.uri, document.version); +}); +var diagnostics = new DiagnosticScheduler({ + run: (uri) => { + const document = documents.get(uri); + if (document === void 0) + return; + validate(document); + } +}); +documents.onDidOpen((event) => { + workspaceIndex.update(event.document.uri, event.document.getText(), event.document.version); + diagnostics.flush(event.document.uri, event.document.version); +}); +documents.onDidChangeContent((event) => { + workspaceIndex.update(event.document.uri, event.document.getText(), event.document.version); + diagnostics.schedule(event.document.uri, event.document.version); +}); documents.onDidClose((event) => { + diagnostics.cancel(event.document.uri); + const target = fsPath(event.document.uri); + try { + if (!target) + throw new Error("not a file URI"); + workspaceIndex.update(event.document.uri, (0, import_node_fs7.readFileSync)(target, "utf8"), `disk:${(0, import_node_fs7.statSync)(target).mtimeMs}`); + } catch { + workspaceIndex.remove(event.document.uri); + } + analysisCache.remove(event.document.uri); + semanticBuilders.delete(event.document.uri); + if (dependencyIndex.remove(event.document.uri)) + refreshWatchers(); connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] }); }); -connection.onRequest(import_node5.DocumentSymbolRequest.type, (params) => { +connection.onDidChangeWatchedFiles((params) => { + const affected = /* @__PURE__ */ new Set(); + for (const change2 of params.changes) { + const target = fsPath(change2.uri); + if (target === void 0) + continue; + includeCache.invalidate(target); + includeParseCache.invalidate(target); + if (target.endsWith(".carverc.json") && !clientOwnsCarveSettings) { + carveSettings = readProjectSettings(workspaceRoots) ?? DEFAULT_CARVE_SETTINGS; + analysisCache.clear(); + for (const document of documents.all()) + diagnostics.schedule(document.uri, document.version); + } + if (change2.uri.endsWith(".crv") && !documents.get(change2.uri)) { + if (change2.type === import_node12.FileChangeType.Deleted) + workspaceIndex.remove(change2.uri); + else { + try { + workspaceIndex.update(change2.uri, (0, import_node_fs7.readFileSync)(target, "utf8"), `disk:${(0, import_node_fs7.statSync)(target).mtimeMs}`); + } catch { + workspaceIndex.remove(change2.uri); + } + } + } + for (const uri of dependencyIndex.documentsFor(target)) + affected.add(uri); + } + for (const uri of affected) { + const document = documents.get(uri); + if (document) { + analysisCache.remove(uri); + validate(document); + } + } +}); +connection.onRequest(import_node12.DocumentSymbolRequest.type, (params) => { + const document = documents.get(params.textDocument.uri); + if (!document) + return []; + const includes = includeOptions(document); + const analysis = analysisFor(document, includes); + return analysis.includedSymbols.length > 0 ? [...flattenSymbols(analysis.symbols, document.uri), ...analysis.includedSymbols] : analysis.symbols; +}); +connection.onRequest(import_node12.WorkspaceSymbolRequest.type, (params) => workspaceIndex.symbols(params.query)); +connection.languages.diagnostics.on((params) => { + const document = documents.get(params.textDocument.uri); + return { + kind: import_node12.DocumentDiagnosticReportKind.Full, + items: document ? analysisFor(document).diagnostics : [] + }; +}); +connection.onRequest(import_node12.DocumentLinkRequest.type, (params) => { + const document = documents.get(params.textDocument.uri); + return document ? documentLinks(document.uri, document.getText()) : []; +}); +connection.onRequest(import_node12.DocumentHighlightRequest.type, (params) => { + const document = documents.get(params.textDocument.uri); + return document ? documentHighlights(document.uri, document.getText(), params.position) : []; +}); +connection.onRequest(import_node12.SelectionRangeRequest.type, (params) => { + const document = documents.get(params.textDocument.uri); + return document ? selectionRanges(document.uri, document.getText(), params.positions) : []; +}); +connection.onRequest(import_node12.InlayHintRequest.type, (params) => { + if (!carveSettings.inlayHints) + return []; const document = documents.get(params.textDocument.uri); - return document ? analyzeCarve(document.getText()).symbols : []; + return document ? inlayHints(document.getText(), params.range) : []; +}); +connection.onRequest(import_node12.ExecuteCommandRequest.type, async (params) => { + const uri = typeof params.arguments?.[0] === "string" ? params.arguments[0] : void 0; + const document = uri ? documents.get(uri) : void 0; + if (!document) + return null; + const engine = await Promise.resolve().then(() => (init_dist2(), dist_exports)); + if (params.command === "carve.previewHtml") + return engine.carveToHtml(document.getText()); + if (params.command === "carve.showAst") + return engine.carveToAstJson(document.getText()); + return null; }); -connection.onRequest(import_node5.HoverRequest.type, (params) => { +connection.onRequest(import_node12.HoverRequest.type, (params) => { const document = documents.get(params.textDocument.uri); return document ? hoverAt(document.getText(), params.position) : null; }); -connection.onRequest(import_node5.CodeActionRequest.type, (params) => { +connection.onRequest(import_node12.CodeActionRequest.type, (params) => { const document = documents.get(params.textDocument.uri); - return document ? migrationCodeActions(params.textDocument.uri, document.getText(), params.context.diagnostics) : []; + return document ? [ + ...migrationCodeActions(params.textDocument.uri, document.getText(), params.context.diagnostics), + ...lintCodeActions(params.textDocument.uri, document.getText(), params.context.diagnostics) + ] : []; }); -connection.onRequest(import_node5.CompletionRequest.type, (params) => { +connection.onRequest(import_node12.CompletionRequest.type, (params) => { const document = documents.get(params.textDocument.uri); - return document ? completionAt(document.getText(), params.position) : []; + return document ? [ + ...includeCompletions(document.getText(), params.position, includeOptions(document)), + ...completionAt(document.getText(), params.position, { workspaceTokens: workspaceIndex.tokens() }) + ] : []; }); -connection.onRequest(import_node5.DocumentFormattingRequest.type, (params) => { +connection.onRequest(import_node12.DocumentFormattingRequest.type, (params) => { const document = documents.get(params.textDocument.uri); if (!document) return []; const text = document.getText(); - const formatted = formatDocument(text); + const formatted = carveSettings.formatter === "migration" ? carveToCarve(text) : formatDocument(text); if (formatted === text) return []; return [ @@ -16034,36 +45501,154 @@ connection.onRequest(import_node5.DocumentFormattingRequest.type, (params) => { } ]; }); -connection.onRequest(import_node5.FoldingRangeRequest.type, (params) => { +connection.onRequest(import_node12.DocumentRangeFormattingRequest.type, (params) => { + const document = documents.get(params.textDocument.uri); + if (!document) + return []; + const newText = formatRange(document.getText(), params.range.start.line, params.range.end.line); + const lines = document.getText().replace(/\r\n?/g, "\n").split("\n"); + return [{ + range: { + start: { line: params.range.start.line, character: 0 }, + end: { line: params.range.end.line, character: (lines[params.range.end.line] ?? "").length } + }, + newText + }]; +}); +connection.onRequest(import_node12.DocumentOnTypeFormattingRequest.type, (params) => { + if (params.ch !== "\n") + return []; + const document = documents.get(params.textDocument.uri); + if (!document) + return []; + const prefix = continuationPrefix(document.getText(), params.position.line); + return prefix ? [{ range: { start: params.position, end: params.position }, newText: prefix }] : []; +}); +connection.onRequest(import_node12.FoldingRangeRequest.type, (params) => { const document = documents.get(params.textDocument.uri); return document ? foldingRanges(document.getText()) : []; }); -connection.onRequest(import_node5.PrepareRenameRequest.type, (params) => { +connection.onRequest(import_node12.PrepareRenameRequest.type, (params) => { const document = documents.get(params.textDocument.uri); - return document ? prepareRename(document.getText(), params.position) : null; + if (!document) + return null; + const local = prepareRename(document.getText(), params.position); + if (local) + return local; + const token = workspaceIndex.tokenAt(document.uri, params.position); + return token ? { range: token.range, placeholder: token.key } : null; }); -connection.onRequest(import_node5.RenameRequest.type, (params) => { +connection.onRequest(import_node12.RenameRequest.type, (params) => { const document = documents.get(params.textDocument.uri); - return document ? renameEdits(params.textDocument.uri, document.getText(), params.position, params.newName) : null; + if (!document) + return null; + return workspaceIndex.rename(document.uri, params.position, params.newName) ?? renameEdits(params.textDocument.uri, document.getText(), params.position, params.newName); }); -connection.onRequest(import_node5.CodeLensRequest.type, (params) => { +connection.onRequest(import_node12.CodeLensRequest.type, (params) => { const document = documents.get(params.textDocument.uri); return document ? codeLenses(document.getText()) : []; }); -connection.onRequest(import_node5.DefinitionRequest.type, (params) => { +connection.onRequest(import_node12.DefinitionRequest.type, (params) => { + const document = documents.get(params.textDocument.uri); + if (!document) + return null; + const local = definitionAt(params.textDocument.uri, document.getText(), params.position, includeOptions(document)); + if (local) + return local; + const token = workspaceIndex.tokenAt(document.uri, params.position); + const target = token ? workspaceIndex.definitions(token.kind, token.key)[0] : void 0; + return target ? { uri: target.uri, range: target.range } : null; +}); +connection.onRequest(import_node12.ReferencesRequest.type, (params) => { const document = documents.get(params.textDocument.uri); - return document ? definitionAt(params.textDocument.uri, document.getText(), params.position) : null; + if (!document) + return null; + const token = workspaceIndex.tokenAt(document.uri, params.position); + if (token) + return workspaceIndex.references(token.kind, token.key, params.context.includeDeclaration); + return referencesAt(params.textDocument.uri, document.getText(), params.position, params.context); +}); +connection.languages.semanticTokens.on((params) => { + const document = documents.get(params.textDocument.uri); + if (!document) + return { data: [] }; + const builder = new import_node12.SemanticTokensBuilder(); + semanticBuilders.set(document.uri, builder); + return buildSemanticTokens(document.getText(), builder); +}); +connection.languages.semanticTokens.onDelta((params) => { + const document = documents.get(params.textDocument.uri); + if (!document) + return { data: [] }; + const builder = semanticBuilders.get(document.uri) ?? new import_node12.SemanticTokensBuilder(); + semanticBuilders.set(document.uri, builder); + return updateSemanticTokens(document.getText(), builder, params.previousResultId); }); -connection.onRequest(import_node5.ReferencesRequest.type, (params) => { +connection.languages.semanticTokens.onRange((params) => { const document = documents.get(params.textDocument.uri); - return document ? referencesAt(params.textDocument.uri, document.getText(), params.position, params.context) : null; + return document ? buildSemanticTokensRange(document.getText(), params.range.start.line, params.range.end.line) : { data: [] }; }); function validate(document) { - const analysis = analyzeCarve(document.getText()); + const includes = includeOptions(document); + const analysis = analysisFor(document, includes); + const changed = dependencyIndex.update(document.uri, analysis.dependencies.flatMap((dependency) => dependency.watch === void 0 ? [] : [dependency.watch])); + if (changed) + refreshWatchers(); connection.sendDiagnostics({ uri: document.uri, diagnostics: analysis.diagnostics }); } +function analysisFor(document, includes = includeOptions(document)) { + return analysisCache.getOrCreate(document.uri, document.version, () => analyzeCarve(document.getText(), { + uri: document.uri, + lint: { + platforms: carveSettings.platforms, + extensions: carveSettings.extensions, + severities: carveSettings.severities + }, + ...includes ? { includes } : {}, + includedParseCache: includeParseCache + })); +} +function includeOptions(document) { + return includeOptionsFor({ + uri: document.uri, + settings: includeSettings, + workspaceTrusted, + workspaceRoots, + cache: includeCache + }); +} +function refreshWatchers() { + const paths = dependencyIndex.watchedPaths(); + watcherRefresh = watcherRefresh.then(async () => { + watcherRegistration?.dispose(); + watcherRegistration = void 0; + if (paths.length === 0) + return; + watcherRegistration = await connection.client.register(import_node12.DidChangeWatchedFilesNotification.type, { + watchers: paths.map(watcherFor) + }); + }).catch((error) => { + connection.console.warn(`Could not register include watchers: ${String(error)}`); + }); +} +function flattenSymbols(symbols, uri) { + const result = []; + const visit4 = (items, containerName) => { + for (const symbol of items) { + result.push({ + name: symbol.name, + kind: symbol.kind, + location: { uri, range: symbol.range }, + ...containerName === void 0 ? {} : { containerName } + }); + visit4(symbol.children ?? [], symbol.name); + } + }; + visit4(symbols); + return result; +} documents.listen(connection); connection.listen(); \ No newline at end of file diff --git a/src/test/kotlin/org/markupcarve/carve/CarvePluginDescriptorTest.kt b/src/test/kotlin/org/markupcarve/carve/CarvePluginDescriptorTest.kt new file mode 100644 index 0000000..69362d1 --- /dev/null +++ b/src/test/kotlin/org/markupcarve/carve/CarvePluginDescriptorTest.kt @@ -0,0 +1,78 @@ +package org.markupcarve.carve + +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import java.io.File + +/** + * Pins WHERE the preview extension points are registered. + * + * JCEF is not part of `com.intellij.modules.platform`: it is its own plugin, + * `com.intellij.modules.jcef`, whose content module carries + * `com.intellij.ui.jcef.JBCefBrowser`. A plugin that does not depend on it does + * not get the class, and registering `CarvePreviewEditorProvider` in the main + * descriptor therefore threw `NoClassDefFoundError` on the first `.crv` file + * opened - and because the provider hides the default editor, that took the + * whole editor with it, not just the preview (#88). + * + * The registration lives in the optional `carve-jcef.xml` for that reason, so + * an IDE without JCEF simply opens the text editor. The failure mode this test + * exists for is a preview extension point being added back to `plugin.xml`, + * where it looks identical and works on every machine that happens to have + * JCEF loaded. + */ +class CarvePluginDescriptorTest { + + private val metaInf = File("src/main/resources/META-INF") + private val pluginXml = File(metaInf, "plugin.xml").readText() + private val jcefXml = File(metaInf, "carve-jcef.xml").readText() + + @Test + fun previewIsRegisteredBehindTheJcefDependency() { + assertTrue( + "plugin.xml must declare the optional JCEF dependency that loads carve-jcef.xml", + Regex("""com\.intellij\.modules\.jcef""") + .containsMatchIn(pluginXml), + ) + assertTrue( + "carve-jcef.xml must register the preview editor provider", + jcefXml.contains("org.markupcarve.carve.preview.CarvePreviewEditorProvider"), + ) + assertTrue( + "carve-jcef.xml must register the preview tool window", + jcefXml.contains("org.markupcarve.carve.preview.CarvePreviewToolWindowFactory"), + ) + } + + @Test + fun theMainDescriptorRegistersNothingFromThePreviewPackage() { + val offenders = Regex("""org\.markupcarve\.carve\.preview\.\w+""") + .findAll(pluginXml) + .map { it.value } + .toList() + assertTrue( + "plugin.xml must not register a preview class - it needs JCEF, which the platform module does not provide: $offenders", + offenders.isEmpty(), + ) + } + + @Test + fun onlyThePreviewPanelTouchesJcef() { + val users = File("src/main/kotlin").walkTopDown() + .filter { it.isFile && it.extension == "kt" } + .filter { it.readText().contains("com.intellij.ui.jcef") || it.readText().contains("import org.cef.") } + .map { it.name } + .toSortedSet() + assertTrue( + "JCEF may only be reached from CarvePreviewPanel, which carve-jcef.xml gates; found $users", + users == sortedSetOf("CarvePreviewPanel.kt"), + ) + assertFalse( + "the toggle action must not reach JCEF - it looks the tool window up by id and tolerates its absence", + File("src/main/kotlin/org/markupcarve/carve/actions/TogglePreviewAction.kt") + .readText() + .contains("jcef"), + ) + } +} diff --git a/src/test/kotlin/org/markupcarve/carve/corpus/CarveCorpusCategories.kt b/src/test/kotlin/org/markupcarve/carve/corpus/CarveCorpusCategories.kt index 0e014b7..11bf85d 100644 --- a/src/test/kotlin/org/markupcarve/carve/corpus/CarveCorpusCategories.kt +++ b/src/test/kotlin/org/markupcarve/carve/corpus/CarveCorpusCategories.kt @@ -784,6 +784,56 @@ object CarveCorpusCategories { "Whether the opener is demoted depends on what folds into it, which needs the block parser. Both documents tokenize IDENTICALLY apart from a blank line, so there is nothing for a golden to assert; the div and list tokens are pinned by `admonitions` and `lists`, and the div-parented list marker is the same artifact as the category above.", "a-blank-line-before-a-sibling-marker-separates-the-items-whatever-consumed-it" to "What consumed the blank line before a sibling marker is block bookkeeping with no token of its own. The three documents produce 7 scopes and no new one beyond that same div-parented list marker; the markers themselves are pinned by `lists`.", + "a-boolean-attribute-does-not-start-with-an-underscore" to + "MEASURED FALSE POSITIVE (#87): `{_foo}` is not an attribute block - a boolean attribute may not start with an underscore - and the whole line renders as prose, while the grammar scopes it `meta.attributes`. The key-value forms beside it (`_k=1`, `_=\"on click\"`) are real attributes and are scoped correctly, so a golden would pin the wrong answer on the one case the category exists for.", + "a-braced-hyphen-pair-is-an-en-dash" to + "MEASURED FALSE POSITIVE (#85): `{--}` renders as an en dash and the critic rule claims it as a deletion; the flag-shaped bare `---` stays literal and the typography rule converts it. `{---}` and `{-x-}` really are deletions and are scoped correctly.", + "a-collected-definition-closes-the-item-paragraph" to + "Whether an indented definition is collected, and what its collection closes, is block context. The tokens are the list marker and the definition line, pinned by `lists` and `reference-link`.", + "a-continuation-marker-attaches-only-a-flush-left-block" to + "Which block a `+` attaches to is block context; the marker itself is pinned by `list-continuation-marker`.", + "a-heading-at-an-item-s-content-column-leaves-no-paragraph-open" to + "An indented heading inside an item is a heading and the same line at the top of a document is a paragraph; this grammar has no container model to tell them apart. The marker-line form is the one it can decide, and CarveMarkerLineBlockOpenerTest pins it.", + "a-hyphen-run-opening-a-word-after-whitespace-is-a-flag" to + "MEASURED FALSE POSITIVE (#85): `--oneline` and `--force-with-lease` stay literal after whitespace and the typography rule converts them. The `` variant does convert and the grammar agrees there.", + "a-lazy-marker-line-s-definition-defines-nothing-in-any-container" to + "Whether a definition on a lazy marker line registers is block context; both documents tokenize as the quote, marker and definition line the covered categories already pin.", + "a-marker-line-link-definition-is-collected-where-no-paragraph-is-open" to + "Collection depends on whether a paragraph is open above, which a line-based grammar cannot see; the definition line and the marker are pinned by `reference-link` and `lists`.", + "a-quote-is-reached-by-its-marker-and-a-column-never-reaches-into-one" to + "Which container an indented line belongs to is block context. The quote marker on the item's marker line is the part this grammar decides, and CarveMarkerLineQuoteTest pins it.", + "a-raw-block-keeps-the-blank-line-at-the-end-of-its-payload-too" to + "Which blank lines survive in a raw payload is render-time; the payload is one raw run either way, pinned by `a-multi-line-raw-block-is-placed-at-its-opening-and-verbatim-after-it`.", + "a-reference-definition-cannot-take-its-destination-from-the-next-line" to + "A definition with no destination on its own line stays prose - the absence of a match is the point, and the matching form is pinned by `reference-link`.", + "a-resumed-lazy-run-belongs-to-the-innermost-marker-line-item" to + "Which item a resumed lazy run belongs to is block context; every document tokenizes as the markers `lists` pins plus bare text runs.", + "a-table-alignment-run-carries-two-independent-axes" to + "Alignment and vertical alignment are render-time styles. The run has no scope of its own - it stays inside the cell text - and the markers around it are pinned by `tables`.", + "a-table-cell-can-inherit-horizontal-alignment" to + "Inheritance down a column is render-time and needs the whole table; the cell and marker tokens are the ones `tables` pins.", + "a-table-cell-s-marker-run-ends-at-a-space" to + "MEASURED FALSE POSITIVE (#86): `|=hot= is the reading |` is an ordinary cell holding a highlight span, and the grammar scopes the leading `|=` as a header marker.", + "a-terminal-comment-in-a-quote-leaves-no-paragraph-open" to + "What a terminal comment leaves open is block context; the comment line itself is pinned by `comments`.", + "a-terminal-comment-line-still-leaves-an-empty-verse-line" to + "Whether the emptied line survives inside a line block is render-time; the comment and the container are pinned by `comments` and the line-block categories.", + "a-vertical-table-marker-needs-a-horizontal-partner" to + "MEASURED FALSE POSITIVE (#86): `|=^ Top` and `|=v Bottom` render as plain cells whose text starts with the marker run, and only `|=<^ Paired` is a header; the grammar scopes all five as header markers.", + "an-all-blank-raw-payload-still-emits-its-line" to + "Whether an all-blank payload emits a line is render-time; the fence and its payload carry the raw-block scopes either way.", + "an-empty-brace-pair-is-not-a-construct" to + "MEASURED FALSE POSITIVE (#85): every empty pair renders as literal text and the grammar scopes all but `{,,}` as its construct. The non-empty forms in the second paragraph are real constructs and are scoped correctly.", + "an-unclosed-inline-literal-reaches-the-end-of-its-block" to + "The literal rule is a closed span by design, so an unclosed opener takes no scope at all rather than leaking into the following paragraphs; that trade was made deliberately and there is nothing to assert but the absence.", + "an-unterminated-fence-at-a-content-column-opens-no-block-so-the-paragraph-stays-open" to + "Whether a fence at an item's content column opens a block depends on the column it sits at, which is block context; CarveUnclosedFenceTest pins what this grammar does with each fence.", + "pipe-tables-can-state-head-and-foot-row-counts" to + "Head and foot row counts are render-time - which rows land in thead and tfoot leaves no token behind. The attribute line and the rows are pinned by `attributes` and `tables`.", + "table-columns-carry-alignment-vertical-alignment-and-widths" to + "A colgroup built from an attribute line is render-time; the attribute line tokenizes as the quoted values `attributes` already pins.", + "the-doubled-run-is-the-canonical-arrow-in-both-families" to + "The arrow scopes are pinned by `smart-typography-arrows-and-symbols`. The one delta is a MEASURED FALSE POSITIVE (#85): `key => value` stays literal and the typography rule converts the `=>`.", ) /** diff --git a/src/test/resources/corpus-tokens/list-continuation-marker-5.tokens b/src/test/resources/corpus-tokens/list-continuation-marker-5.tokens index 55fb3a4..f4831fb 100644 --- a/src/test/resources/corpus-tokens/list-continuation-marker-5.tokens +++ b/src/test/resources/corpus-tokens/list-continuation-marker-5.tokens @@ -1,11 +1,6 @@ - -> text.carve markup.list.unnumbered.carve keyword.control.list.begin.carve -> text.carve markup.list.unnumbered.carve a\n -> text.carve - -> text.carve markup.list.unnumbered.carve -- -> text.carve markup.list.unnumbered.carve keyword.control.list.begin.carve - -> text.carve markup.list.unnumbered.carve -b\n -> text.carve - -> text.carve markup.list.continuation.carve + -> text.carve markup.list.continuation.carve keyword.control.list.continuation.carve \n -> text.carve markup.list.continuation.carve - c\n -> text.carve +c\n -> text.carve diff --git a/src/test/resources/corpus-tokens/smart-typography-arrows-and-symbols.tokens b/src/test/resources/corpus-tokens/smart-typography-arrows-and-symbols.tokens index 2a67d51..742b6c2 100644 --- a/src/test/resources/corpus-tokens/smart-typography-arrows-and-symbols.tokens +++ b/src/test/resources/corpus-tokens/smart-typography-arrows-and-symbols.tokens @@ -1,13 +1,14 @@ Flow: a -> text.carve --> -> text.carve constant.character.entity.typography.carve - b -> text.carve +-- -> text.carve constant.character.entity.typography.carve +> b -> text.carve +<- -> text.carve constant.character.entity.typography.carve +- c -> text.carve <- -> text.carve constant.character.entity.typography.carve - c -> text.carve -<-> -> text.carve constant.character.entity.typography.carve - d -> text.carve -= -> text.carve markup.changed.carve keyword.control.highlight.carve -> e; x ! -> text.carve markup.changed.carve markup.changed.carve -= -> text.carve markup.changed.carve keyword.control.highlight.carve +-> -> text.carve constant.character.entity.typography.carve + d = -> text.carve +=> -> text.carve constant.character.entity.typography.carve + e; x -> text.carve +!= -> text.carve constant.character.entity.typography.carve y, p -> text.carve <= -> text.carve constant.character.entity.typography.carve q, r -> text.carve