@wdprlib/parser 5.1.6 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/index.cjs +764 -452
  2. package/dist/index.d.cts +24 -4
  3. package/dist/index.d.ts +24 -4
  4. package/dist/index.js +762 -452
  5. package/package.json +2 -2
  6. package/src/build-info.generated.ts +11 -0
  7. package/src/index.ts +2 -0
  8. package/src/lexer/lexer.ts +6 -4
  9. package/src/lexer/punctuation.ts +2 -1
  10. package/src/lexer/spacing-actions.ts +15 -0
  11. package/src/lexer/state.ts +30 -4
  12. package/src/lexer/token-factory.ts +15 -2
  13. package/src/lexer/tokens.ts +4 -3
  14. package/src/parser/rules/block/blockquote/build.ts +81 -37
  15. package/src/parser/rules/block/blockquote/index.ts +5 -6
  16. package/src/parser/rules/block/blockquote/line.ts +11 -10
  17. package/src/parser/rules/block/blockquote/lines.ts +102 -4
  18. package/src/parser/rules/block/code/content.ts +0 -3
  19. package/src/parser/rules/block/code/index.ts +14 -10
  20. package/src/parser/rules/block/definition-list/index.ts +4 -10
  21. package/src/parser/rules/block/definition-list/item-value.ts +2 -11
  22. package/src/parser/rules/block/definition-list/items.ts +1 -2
  23. package/src/parser/rules/block/embed-block/index.ts +30 -30
  24. package/src/parser/rules/block/heading/index.ts +7 -0
  25. package/src/parser/rules/block/module/listpages/resolution/items.ts +2 -2
  26. package/src/parser/rules/block/module/listpages/resolution/pager.ts +43 -0
  27. package/src/parser/rules/block/module/listpages/resolution/wrapper.ts +6 -1
  28. package/src/parser/rules/block/module/listpages/resolve.ts +1 -1
  29. package/src/parser/rules/block/module/listpages/types/external-data.ts +13 -0
  30. package/src/parser/rules/block/module/listpages/url-resolution/params.ts +5 -4
  31. package/src/parser/rules/block/module/resolution/data-maps.ts +75 -3
  32. package/src/parser/rules/block/module/resolution/resolve-async.ts +12 -3
  33. package/src/parser/rules/block/paragraph/index.ts +41 -10
  34. package/src/parser/rules/block/parsing/content.ts +18 -1
  35. package/src/parser/rules/block/table/pipe/cell.ts +36 -1
  36. package/src/parser/rules/block/table/pipe/row.ts +21 -1
  37. package/src/parser/rules/block/toc/element.ts +2 -2
  38. package/src/parser/rules/block/toc/index.ts +2 -2
  39. package/src/parser/rules/block/toc/open.ts +5 -18
  40. package/src/parser/rules/contracts/scope.ts +4 -0
  41. package/src/parser/rules/inline/bold.ts +5 -5
  42. package/src/parser/rules/inline/color/syntax.ts +5 -8
  43. package/src/parser/rules/inline/formatting/close.ts +39 -0
  44. package/src/parser/rules/inline/formatting/container.ts +7 -4
  45. package/src/parser/rules/inline/index.ts +2 -0
  46. package/src/parser/rules/inline/italic.ts +5 -5
  47. package/src/parser/rules/inline/monospace.ts +5 -5
  48. package/src/parser/rules/inline/parsing/block-start-predicates.ts +2 -0
  49. package/src/parser/rules/inline/parsing/inline-content.ts +58 -4
  50. package/src/parser/rules/inline/raw/end.ts +28 -0
  51. package/src/parser/rules/inline/span/content.ts +32 -1
  52. package/src/parser/rules/inline/strikethrough/index.ts +1 -1
  53. package/src/parser/rules/inline/strikethrough/parse.ts +2 -9
  54. package/src/parser/rules/inline/strikethrough/syntax.ts +3 -20
  55. package/src/parser/rules/inline/subscript.ts +5 -5
  56. package/src/parser/rules/inline/superscript.ts +5 -5
  57. package/src/parser/rules/inline/underline/index.ts +5 -78
  58. package/src/parser/rules/tokens.ts +6 -15
  59. package/src/pipeline/process.ts +8 -1
  60. package/src/parser/rules/inline/underline/child.ts +0 -26
  61. package/src/parser/rules/inline/underline/content.ts +0 -29
@@ -1,84 +1,11 @@
1
- /**
2
- *
3
- * Parses the Wikidot underline formatting syntax: `__text__`.
4
- *
5
- * Underline text is delimited by double underscores. Unlike most
6
- * inline formatting markers (bold, italic, etc.) which require the
7
- * closing marker on the same line, underline markers can span
8
- * multiple lines within the same paragraph. The closing marker
9
- * must appear before a paragraph break (blank line).
10
- *
11
- * Single newlines within underlined content are converted to
12
- * `<br />` elements, matching Wikidot's multiline underline behavior.
13
- *
14
- * If no closing `__` is found before a paragraph break, the opening
15
- * marker is emitted as literal text.
16
- *
17
- * Empty underline (`____`) is silently discarded by Wikidot (produces
18
- * no output).
19
- *
20
- * Renders as a `<u>` element in HTML.
21
- *
22
- * Produces a `"container"` AST element with `type: "underline"`.
23
- *
24
- * @module
25
- */
26
- import type { Element } from "@wdprlib/ast";
27
- import type { InlineRule, ParseContext, RuleResult } from "../../types";
28
- import { currentToken, hasClosingMarkerBeforeParagraphBreak } from "../../types";
29
- import { createInlineContainer } from "../formatting/container";
30
- import { parseUnderlineContent } from "./content";
1
+ import type { InlineRule } from "../../types";
2
+ import { parseDelimitedContainer } from "../formatting/container";
31
3
 
32
- /**
33
- * Inline rule for parsing `__underline__` formatting.
34
- *
35
- * Triggered by an `UNDERLINE_MARKER` token (`__`). Uses
36
- * {@link hasClosingMarkerBeforeParagraphBreak} instead of the
37
- * single-line variant because Wikidot allows underline to span
38
- * multiple lines within a paragraph.
39
- *
40
- * When no closing marker is found before a paragraph break, the
41
- * opening `__` is treated as literal text.
42
- */
4
+ /** Underline can span ordinary newlines, but cannot cross its enclosing block. */
43
5
  export const underlineRule: InlineRule = {
44
6
  name: "underline",
45
7
  startTokens: ["UNDERLINE_MARKER"],
46
-
47
- /**
48
- * Attempts to parse underline formatting at the current position.
49
- *
50
- * @param ctx - Parse context with token stream and current position
51
- * @returns A successful result containing either a `"container"` element
52
- * with `type: "underline"`, an empty array (for `____`), or a
53
- * text fallback for unmatched markers
54
- */
55
- parse(ctx: ParseContext): RuleResult<Element> {
56
- const startToken = currentToken(ctx);
57
-
58
- // Check if closing marker exists before paragraph break
59
- if (!hasClosingMarkerBeforeParagraphBreak({ ...ctx, pos: ctx.pos + 1 }, "UNDERLINE_MARKER")) {
60
- return {
61
- success: true,
62
- elements: [{ element: "text", data: startToken.value }],
63
- consumed: 1,
64
- };
65
- }
66
-
67
- const { children, consumed } = parseUnderlineContent(ctx, ctx.pos + 1);
68
-
69
- // Empty underline (____) is discarded entirely in Wikidot
70
- if (children.length === 0) {
71
- return {
72
- success: true,
73
- elements: [],
74
- consumed,
75
- };
76
- }
77
-
78
- return {
79
- success: true,
80
- elements: [createInlineContainer("underline", children)],
81
- consumed,
82
- };
8
+ parse(ctx) {
9
+ return parseDelimitedContainer(ctx, "UNDERLINE_MARKER", "underline", { discardEmpty: true });
83
10
  },
84
11
  };
@@ -1,5 +1,6 @@
1
1
  import type { Token, TokenType } from "../../lexer";
2
2
  import type { ParseContext } from "./contracts";
3
+ import { getParagraphNewlineBoundary } from "./inline/parsing/paragraph-boundary";
3
4
 
4
5
  /**
5
6
  * Helper to get current token
@@ -51,7 +52,7 @@ export function hasClosingMarkerBeforeNewline(
51
52
  markerValue?: string,
52
53
  ): boolean {
53
54
  let pos = ctx.pos;
54
- while (pos < ctx.tokens.length) {
55
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
55
56
  const token = ctx.tokens[pos];
56
57
  if (!token || token.type === "NEWLINE" || token.type === "EOF") {
57
58
  return false;
@@ -76,24 +77,14 @@ export function hasClosingMarkerBeforeParagraphBreak(
76
77
  markerValue?: string,
77
78
  ): boolean {
78
79
  let pos = ctx.pos;
79
- while (pos < ctx.tokens.length) {
80
+ while (pos < (ctx.scope.inlineEnd ?? ctx.tokens.length)) {
80
81
  const token = ctx.tokens[pos];
81
82
  if (!token || token.type === "EOF") {
82
83
  return false;
83
84
  }
84
- // Check for paragraph break (NEWLINE followed by NEWLINE after optional whitespace)
85
- if (token.type === "NEWLINE") {
86
- let lookAhead = 1;
87
- while (ctx.tokens[pos + lookAhead]?.type === "WHITESPACE") {
88
- lookAhead++;
89
- }
90
- if (
91
- ctx.tokens[pos + lookAhead]?.type === "NEWLINE" ||
92
- ctx.tokens[pos + lookAhead]?.type === "EOF" ||
93
- !ctx.tokens[pos + lookAhead]
94
- ) {
95
- return false;
96
- }
85
+ if (ctx.scope.blockCloseCondition?.({ ...ctx, pos })) return false;
86
+ if (token.type === "NEWLINE" && getParagraphNewlineBoundary(ctx, pos, true).shouldBreak) {
87
+ return false;
97
88
  }
98
89
  if (token.type === markerType) {
99
90
  if (markerValue === undefined || token.value === markerValue) {
@@ -82,6 +82,12 @@ export async function processWikitext<TPage extends WikitextPageContext>(
82
82
  const dataProvider = createModuleDataProvider(options, callbackContext);
83
83
  const parseFragment = parseSource;
84
84
  let ast = initial.ast;
85
+ const paginationState = { nextUnprefixed: 1 };
86
+ const requestedPath = options.page.urlPath;
87
+ const urlPath =
88
+ !requestedPath || /^\/(?:[?#]|$)/.test(requestedPath)
89
+ ? `/${options.page.fullName}${requestedPath?.slice(1) ?? ""}`
90
+ : requestedPath;
85
91
 
86
92
  for (let pass = 0; pass < DEFAULT_MODULE_MAX_PASSES; pass++) {
87
93
  const extraction = extractDataRequirements(ast);
@@ -94,7 +100,8 @@ export async function processWikitext<TPage extends WikitextPageContext>(
94
100
  compiledListPagesTemplates: extraction.compiledListPagesTemplates,
95
101
  compiledListUsersTemplates: extraction.compiledListUsersTemplates,
96
102
  requirements: extraction.requirements,
97
- urlPath: options.page.urlPath,
103
+ urlPath,
104
+ paginationState,
98
105
  pageTags: options.page.tags,
99
106
  });
100
107
  ast = resolved.ast;
@@ -1,26 +0,0 @@
1
- import type { Element } from "@wdprlib/ast";
2
- import type { ParseContext } from "../../types";
3
- import { parseInlineUntil } from "../utils";
4
-
5
- export interface UnderlineChildResult {
6
- elements: Element[];
7
- consumed: number;
8
- }
9
-
10
- export function parseUnderlineChild(ctx: ParseContext, pos: number): UnderlineChildResult {
11
- const token = ctx.tokens[pos];
12
- if (!token) {
13
- return { elements: [], consumed: 0 };
14
- }
15
-
16
- if (token.type === "NEWLINE") {
17
- return { elements: [{ element: "line-break" }], consumed: 1 };
18
- }
19
-
20
- const result = parseInlineUntil({ ...ctx, pos }, "UNDERLINE_MARKER");
21
- if (result.elements.length > 0) {
22
- return { elements: result.elements, consumed: result.consumed };
23
- }
24
-
25
- return { elements: [{ element: "text", data: token.value }], consumed: 1 };
26
- }
@@ -1,29 +0,0 @@
1
- import type { Element } from "@wdprlib/ast";
2
- import type { ParseContext } from "../../types";
3
- import { parseUnderlineChild } from "./child";
4
-
5
- export function parseUnderlineContent(
6
- ctx: ParseContext,
7
- startPos: number,
8
- ): { children: Element[]; consumed: number } {
9
- const children: Element[] = [];
10
- let pos = startPos;
11
- let consumed = 1;
12
-
13
- while (pos < ctx.tokens.length) {
14
- const token = ctx.tokens[pos];
15
- if (!token || token.type === "EOF") break;
16
-
17
- if (token.type === "UNDERLINE_MARKER") {
18
- consumed++;
19
- break;
20
- }
21
-
22
- const child = parseUnderlineChild(ctx, pos);
23
- children.push(...child.elements);
24
- pos += child.consumed;
25
- consumed += child.consumed;
26
- }
27
-
28
- return { children, consumed };
29
- }