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}${tag}>`;
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}${tag}>`;
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}${tag}>`;
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}${tag}>`;
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}${tag}>`;
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}${tag}>`;
const number = idx + 1;
const body = entry.inline ? [`${indent(3)}
`;
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: `#${n.target}>` };
- 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 `#id>` 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}${tag}>`;
+}
+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 #${target}> has no matching heading id; it renders as the literal text "#${target}>".`
- });
- }
- 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)}
`);
+ }
+ 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)}
`,
+ ...body,
+ `${indent(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}${name}>`;
+ }
+ 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}
- 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)}${tn}>`}`;
+}
+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
+ * `
` -> `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
+ * `