@wdprlib/parser 0.1.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.
@@ -0,0 +1,743 @@
1
+ import { Position as Position2, Point, Version as Version2, Element as Element6, SyntaxTree as SyntaxTree4, ContainerType, ContainerData, AttributeMap, VariableMap, Alignment, LinkType, LinkLocation, LinkLabel, PageRef as PageRef2, ImageSource, FloatAlignment, ListType, ListItem, ListData, CodeBlockData as CodeBlockData2, TabData, TableCell, TableRow, TableData, DefinitionListItem, Module as Module4, CollapsibleData, ClearFloat, AnchorTarget, HeaderType, AlignType, HeadingLevel, Heading, DateItem, Embed, TocEntry as TocEntry2 } from "@wdprlib/ast";
2
+ import { createPoint, createPosition, text, container, paragraph, bold, italics, heading, lineBreak, horizontalRule, link, list, listItemElements, listItemSubList } from "@wdprlib/ast";
3
+ import { Position } from "@wdprlib/ast";
4
+ /**
5
+ * Token types for Wikidot markup
6
+ */
7
+ type TokenType = "EOF" | "TEXT" | "IDENTIFIER" | "NEWLINE" | "WHITESPACE" | "BLOCK_OPEN" | "BLOCK_CLOSE" | "BLOCK_END_OPEN" | "BOLD_MARKER" | "ITALIC_MARKER" | "UNDERLINE_MARKER" | "STRIKE_MARKER" | "SUPER_MARKER" | "SUB_MARKER" | "MONO_MARKER" | "MONO_CLOSE" | "HEADING_MARKER" | "HR_MARKER" | "LIST_BULLET" | "LIST_NUMBER" | "BLOCKQUOTE_MARKER" | "TABLE_MARKER" | "TABLE_HEADER" | "TABLE_LEFT" | "TABLE_CENTER" | "TABLE_RIGHT" | "CODE_OPEN" | "CODE_CLOSE" | "LINK_OPEN" | "LINK_CLOSE" | "BRACKET_OPEN" | "BRACKET_CLOSE" | "BRACKET_ANCHOR" | "BRACKET_STAR" | "PIPE" | "EQUALS" | "COLON" | "SLASH" | "STAR" | "HASH" | "AT" | "AMPERSAND" | "BACKSLASH" | "QUOTED_STRING" | "RAW_OPEN" | "RAW_CLOSE" | "RAW_BLOCK_OPEN" | "RAW_BLOCK_CLOSE" | "COLOR_MARKER" | "UNDERSCORE" | "COMMENT_OPEN" | "COMMENT_CLOSE" | "CLEAR_FLOAT" | "CLEAR_FLOAT_LEFT" | "CLEAR_FLOAT_RIGHT" | "LEFT_DOUBLE_ANGLE" | "RIGHT_DOUBLE_ANGLE";
8
+ /**
9
+ * Token
10
+ */
11
+ interface Token {
12
+ type: TokenType;
13
+ value: string;
14
+ position: Position;
15
+ /** Whether this token appears at the start of a line */
16
+ lineStart: boolean;
17
+ }
18
+ /**
19
+ * Create a token
20
+ */
21
+ declare function createToken(type: TokenType, value: string, position: Position, lineStart?: boolean): Token;
22
+ /**
23
+ * Lexer options
24
+ */
25
+ interface LexerOptions {
26
+ /** Track position information */
27
+ trackPositions?: boolean;
28
+ }
29
+ /**
30
+ * Wikidot markup lexer
31
+ */
32
+ declare class Lexer {
33
+ private state;
34
+ private options;
35
+ constructor(source: string, options?: LexerOptions);
36
+ /**
37
+ * Tokenize the entire source
38
+ */
39
+ tokenize(): Token[];
40
+ /**
41
+ * Check if at end of source
42
+ */
43
+ private isAtEnd;
44
+ /**
45
+ * Get current character
46
+ */
47
+ private current;
48
+ /**
49
+ * Check if source matches pattern at current position
50
+ */
51
+ private match;
52
+ /**
53
+ * Advance position by n characters
54
+ */
55
+ private advance;
56
+ /**
57
+ * Add token
58
+ */
59
+ private addToken;
60
+ /**
61
+ * Scan a single token
62
+ */
63
+ private scanToken;
64
+ /**
65
+ * Check if character is alphanumeric (for identifier tokens)
66
+ */
67
+ private isAlphanumeric;
68
+ }
69
+ /**
70
+ * Tokenize source string
71
+ */
72
+ declare function tokenize(source: string, options?: LexerOptions): Token[];
73
+ import { SyntaxTree } from "@wdprlib/ast";
74
+ /**
75
+ * Parser options
76
+ */
77
+ interface ParserOptions {
78
+ /** Wikidot version */
79
+ version?: "wikidot";
80
+ /** Track position information */
81
+ trackPositions?: boolean;
82
+ }
83
+ /**
84
+ * Wikidot markup parser
85
+ */
86
+ declare class Parser {
87
+ private ctx;
88
+ constructor(tokens: Token[], options?: ParserOptions);
89
+ /**
90
+ * Parse tokens into SyntaxTree
91
+ */
92
+ parse(): SyntaxTree;
93
+ /**
94
+ * Check if at end of tokens
95
+ */
96
+ private isAtEnd;
97
+ /**
98
+ * Get current token
99
+ */
100
+ private currentToken;
101
+ /**
102
+ * Create EOF token
103
+ */
104
+ private eofToken;
105
+ /**
106
+ * Skip whitespace tokens
107
+ */
108
+ private skipWhitespace;
109
+ /**
110
+ * Parse block element(s)
111
+ * Returns an array because some rules (like list) may return multiple elements
112
+ */
113
+ private parseBlock;
114
+ }
115
+ /**
116
+ * Parse source string into SyntaxTree
117
+ */
118
+ declare function parse(source: string, options?: ParserOptions): SyntaxTree;
119
+ import { Element as Element2 } from "@wdprlib/ast";
120
+ /**
121
+ * Parser function type for re-parsing substituted templates
122
+ * Used by ListPages and ListUsers modules
123
+ */
124
+ type ParseFunction = (input: string) => {
125
+ elements: Element2[];
126
+ };
127
+ /**
128
+ * ListUsers module types
129
+ */
130
+ /**
131
+ * Supported template variables
132
+ */
133
+ type ListUsersVariable = "number" | "title" | "name";
134
+ /**
135
+ * User data provided by external source
136
+ */
137
+ interface ListUsersUserData {
138
+ number: number;
139
+ title: string;
140
+ name: string;
141
+ }
142
+ /**
143
+ * Data requirement for a single ListUsers module
144
+ */
145
+ interface ListUsersDataRequirement {
146
+ id: number;
147
+ users: string;
148
+ neededVariables: ListUsersVariable[];
149
+ }
150
+ /**
151
+ * External data for a single ListUsers module
152
+ * Note: ListUsers returns only the logged-in user
153
+ */
154
+ interface ListUsersExternalData {
155
+ user: ListUsersUserData;
156
+ }
157
+ /**
158
+ * Callback to fetch data for a ListUsers module
159
+ */
160
+ type ListUsersDataFetcher = (requirement: ListUsersDataRequirement) => ListUsersExternalData | null | undefined | Promise<ListUsersExternalData | null | undefined>;
161
+ /**
162
+ * Context passed to compiled template
163
+ */
164
+ interface ListUsersVariableContext {
165
+ user: ListUsersUserData;
166
+ }
167
+ /**
168
+ * Compiled template function
169
+ */
170
+ type ListUsersCompiledTemplate = (ctx: ListUsersVariableContext) => string;
171
+ /**
172
+ * ListPages module types
173
+ */
174
+ /**
175
+ * ListPages query parameters for page selection
176
+ *
177
+ * @security All string fields contain **untrusted user input** from wikitext.
178
+ * When using these values in database queries:
179
+ * - **NEVER** interpolate directly into SQL/NoSQL query strings
180
+ * - **ALWAYS** use parameterized queries or prepared statements
181
+ * - For ORDER BY clauses, use a whitelist of allowed column names
182
+ *
183
+ * @example Safe usage with SQL
184
+ * ```typescript
185
+ * // GOOD: Parameterized query
186
+ * db.query("SELECT * FROM pages WHERE category = ?", [query.category]);
187
+ *
188
+ * // BAD: String interpolation (SQL injection vulnerable!)
189
+ * db.query(`SELECT * FROM pages WHERE category = '${query.category}'`);
190
+ * ```
191
+ */
192
+ interface ListPagesQuery {
193
+ /** Page type selector */
194
+ pagetype?: "normal" | "hidden" | "*";
195
+ /**
196
+ * Category selector
197
+ * @untrusted User input - use parameterized queries
198
+ */
199
+ category?: string;
200
+ /**
201
+ * Tag selector (e.g., "+fruit -admin")
202
+ * @untrusted User input - use parameterized queries
203
+ */
204
+ tags?: string;
205
+ /**
206
+ * Parent page selector
207
+ * @untrusted User input - use parameterized queries
208
+ */
209
+ parent?: string;
210
+ /**
211
+ * Link target selector
212
+ * @untrusted User input - use parameterized queries
213
+ */
214
+ linkTo?: string;
215
+ /**
216
+ * Created date selector
217
+ * @untrusted User input - use parameterized queries
218
+ */
219
+ createdAt?: string;
220
+ /**
221
+ * Updated date selector
222
+ * @untrusted User input - use parameterized queries
223
+ */
224
+ updatedAt?: string;
225
+ /**
226
+ * Author selector
227
+ * @untrusted User input - use parameterized queries
228
+ */
229
+ createdBy?: string;
230
+ /**
231
+ * Rating selector
232
+ * @untrusted User input - use parameterized queries
233
+ */
234
+ rating?: string;
235
+ /**
236
+ * Votes selector
237
+ * @untrusted User input - use parameterized queries
238
+ */
239
+ votes?: string;
240
+ /**
241
+ * Page name selector
242
+ * @untrusted User input - use parameterized queries
243
+ */
244
+ name?: string;
245
+ /**
246
+ * Full page name selector (category:name)
247
+ * @untrusted User input - use parameterized queries
248
+ */
249
+ fullname?: string;
250
+ /** Range selector relative to current page */
251
+ range?: "." | "before" | "after" | "others";
252
+ /**
253
+ * Data form field selectors
254
+ * @untrusted Both keys and values are user input
255
+ */
256
+ dataFormFields?: Record<string, string>;
257
+ /**
258
+ * Ordering specification
259
+ * @untrusted User input - use whitelist validation for ORDER BY
260
+ */
261
+ order?: string;
262
+ /** Pagination offset */
263
+ offset?: number;
264
+ /** Maximum number of results */
265
+ limit?: number;
266
+ /** Results per page */
267
+ perPage?: number;
268
+ /** Reverse order */
269
+ reverse?: boolean;
270
+ }
271
+ /**
272
+ * All supported ListPages template variables
273
+ */
274
+ type ListPagesVariable = "created_at" | "created_by" | "created_by_unix" | "created_by_id" | "created_by_linked" | "updated_at" | "updated_by" | "updated_by_unix" | "updated_by_id" | "updated_by_linked" | "commented_at" | "commented_by" | "commented_by_unix" | "commented_by_id" | "commented_by_linked" | "name" | "category" | "fullname" | "title" | "title_linked" | "link" | "parent_name" | "parent_category" | "parent_fullname" | "parent_title" | "parent_title_linked" | "content" | "content_n" | "preview" | "preview_n" | "summary" | "first_paragraph" | "tags" | "tags_linked" | "_tags" | "_tags_linked" | "form_data" | "form_raw" | "form_label" | "form_hint" | "children" | "comments" | "size" | "rating" | "rating_votes" | "rating_percent" | "revisions" | "index" | "total" | "limit" | "total_or_limit" | "site_title" | "site_name" | "site_domain";
275
+ /**
276
+ * Data requirement for a single ListPages module
277
+ */
278
+ interface ListPagesDataRequirement {
279
+ /** Unique identifier for this module instance */
280
+ id: number;
281
+ /** Query parameters */
282
+ query: ListPagesQuery;
283
+ /** Variables used in the template */
284
+ neededVariables: ListPagesVariable[];
285
+ /** Indices needed for content{n} */
286
+ contentSectionIndices?: number[];
287
+ /** Lengths needed for preview(n) */
288
+ previewLengths?: number[];
289
+ /** Field names needed for form_data{field} etc */
290
+ formFields?: string[];
291
+ /** Prefix for tags_linked|prefix */
292
+ tagsLinkPrefix?: string;
293
+ /** Prefix for _tags_linked|prefix */
294
+ hiddenTagsLinkPrefix?: string;
295
+ /**
296
+ * URL attribute prefix for multiple ListPages modules
297
+ * When set, URL parameters are prefixed (e.g., "page2" -> "/page2_limit/1")
298
+ */
299
+ urlAttrPrefix?: string;
300
+ /**
301
+ * Raw attribute values before URL resolution
302
+ * Contains original string values that may include "@URL" or "@URL|default" format
303
+ * External applications should use these to resolve URL parameters
304
+ */
305
+ rawAttributes: Record<string, string>;
306
+ }
307
+ /**
308
+ * All data requirements from parsing
309
+ */
310
+ interface DataRequirements {
311
+ listPages: ListPagesDataRequirement[];
312
+ listUsers: ListUsersDataRequirement[];
313
+ }
314
+ /**
315
+ * User information
316
+ */
317
+ interface UserInfo {
318
+ id: number;
319
+ name: string;
320
+ unixName: string;
321
+ }
322
+ /**
323
+ * Page data provided by external source
324
+ */
325
+ interface PageData {
326
+ name: string;
327
+ category: string;
328
+ fullname: string;
329
+ title: string;
330
+ createdAt: Date;
331
+ createdBy?: UserInfo;
332
+ updatedAt: Date;
333
+ updatedBy?: UserInfo;
334
+ commentedAt?: Date;
335
+ commentedBy?: UserInfo;
336
+ parentName?: string;
337
+ parentCategory?: string;
338
+ parentFullname?: string;
339
+ parentTitle?: string;
340
+ content?: string;
341
+ tags: string[];
342
+ hiddenTags: string[];
343
+ formData?: Record<string, string>;
344
+ formRaw?: Record<string, string>;
345
+ formLabel?: Record<string, string>;
346
+ formHint?: Record<string, string>;
347
+ children: number;
348
+ comments: number;
349
+ size: number;
350
+ rating: number;
351
+ ratingVotes: number;
352
+ ratingPercent?: number;
353
+ revisions: number;
354
+ }
355
+ /**
356
+ * Site context information
357
+ */
358
+ interface SiteContext {
359
+ title: string;
360
+ name: string;
361
+ domain: string;
362
+ }
363
+ /**
364
+ * External data for a single ListPages module
365
+ */
366
+ interface ListPagesExternalData {
367
+ pages: PageData[];
368
+ totalCount: number;
369
+ site: SiteContext;
370
+ }
371
+ /**
372
+ * Callback to fetch data for a ListPages module
373
+ *
374
+ * Called by resolveModules for each ListPages module in the AST.
375
+ * Receives a normalized query with all @URL parameters resolved.
376
+ * Return null/undefined to skip the module (outputs nothing).
377
+ *
378
+ * @param query - Normalized query with structured types (tags, category, order, etc.)
379
+ * @param requirement - Original data requirement (for accessing id, neededVariables, etc.)
380
+ */
381
+ type ListPagesDataFetcher = (query: NormalizedListPagesQuery, requirement: ListPagesDataRequirement) => ListPagesExternalData | null | undefined | Promise<ListPagesExternalData | null | undefined>;
382
+ /**
383
+ * Context passed to compiled template
384
+ */
385
+ interface VariableContext {
386
+ page: PageData;
387
+ index: number;
388
+ total: number;
389
+ limit?: number;
390
+ site: SiteContext;
391
+ }
392
+ /**
393
+ * Compiled template function
394
+ */
395
+ type CompiledTemplate = (ctx: VariableContext) => string;
396
+ /**
397
+ * Normalized tags selector
398
+ */
399
+ interface NormalizedTags {
400
+ /** AND conditions - pages must have ALL of these tags (+tag) */
401
+ all: string[];
402
+ /** OR conditions - pages must have ANY of these tags (no prefix) */
403
+ any: string[];
404
+ /** NOT conditions - pages must NOT have these tags (-tag) */
405
+ none: string[];
406
+ /** Special selector */
407
+ special: "same-visible" | "same-all" | "none" | null;
408
+ }
409
+ /**
410
+ * Normalized category selector
411
+ */
412
+ interface NormalizedCategory {
413
+ /** Categories to include */
414
+ include: string[];
415
+ /** Categories to exclude (-category) */
416
+ exclude: string[];
417
+ /** Select all categories (*) */
418
+ all: boolean;
419
+ /** Select current category (.) */
420
+ current: boolean;
421
+ }
422
+ /**
423
+ * Order field options
424
+ */
425
+ type OrderField = "created_at" | "updated_at" | "title" | "fullname" | "rating" | "votes" | "revisions" | "comments" | "size" | "random";
426
+ /**
427
+ * Order direction
428
+ */
429
+ type OrderDirection = "asc" | "desc";
430
+ /**
431
+ * Normalized order specification
432
+ */
433
+ interface NormalizedOrder {
434
+ field: OrderField;
435
+ direction: OrderDirection;
436
+ }
437
+ /**
438
+ * Normalized parent selector
439
+ */
440
+ type NormalizedParent = {
441
+ type: "none";
442
+ } | {
443
+ type: "same";
444
+ } | {
445
+ type: "different";
446
+ } | {
447
+ type: "children";
448
+ } | {
449
+ type: "page";
450
+ name: string;
451
+ };
452
+ /**
453
+ * Date comparison operators
454
+ */
455
+ type DateComparisonOp = "=" | "<" | ">" | "<=" | ">=" | "<>";
456
+ /**
457
+ * Normalized date selector
458
+ */
459
+ type NormalizedDateSelector = {
460
+ type: "year";
461
+ year: number;
462
+ } | {
463
+ type: "month";
464
+ year: number;
465
+ month: number;
466
+ } | {
467
+ type: "comparison";
468
+ op: DateComparisonOp;
469
+ date: string;
470
+ } | {
471
+ type: "relative";
472
+ unit: "day" | "week" | "month";
473
+ count: number;
474
+ };
475
+ /**
476
+ * Numeric comparison operators
477
+ */
478
+ type NumericComparisonOp = "=" | "<" | ">" | "<=" | ">=";
479
+ /**
480
+ * Normalized numeric selector (for rating/votes)
481
+ */
482
+ interface NormalizedNumericSelector {
483
+ op: NumericComparisonOp;
484
+ value: number;
485
+ }
486
+ /**
487
+ * Fully normalized ListPages query
488
+ *
489
+ * All string fields are parsed and structured into type-safe objects.
490
+ * Use `normalizeQuery()` to convert from `ListPagesQuery`.
491
+ *
492
+ * Note: This is structural normalization, not full validation.
493
+ * Invalid inputs are either rejected (return undefined) or ignored.
494
+ */
495
+ interface NormalizedListPagesQuery {
496
+ pagetype?: "normal" | "hidden" | "*";
497
+ category?: NormalizedCategory;
498
+ tags?: NormalizedTags;
499
+ parent?: NormalizedParent;
500
+ linkTo?: string;
501
+ createdAt?: NormalizedDateSelector;
502
+ updatedAt?: NormalizedDateSelector;
503
+ createdBy?: string;
504
+ rating?: NormalizedNumericSelector;
505
+ votes?: NormalizedNumericSelector;
506
+ name?: string;
507
+ fullname?: string;
508
+ range?: "." | "before" | "after" | "others";
509
+ dataFormFields?: Record<string, string>;
510
+ order?: NormalizedOrder;
511
+ offset?: number;
512
+ limit?: number;
513
+ perPage?: number;
514
+ reverse?: boolean;
515
+ }
516
+ /**
517
+ * Callback to get current page's tags
518
+ *
519
+ * Called during resolve phase to evaluate [[iftags]] conditions.
520
+ *
521
+ * @returns Array of tag names for the current page
522
+ */
523
+ type IfTagsResolver = () => string[];
524
+ /**
525
+ * Data provider interface for resolving modules that require external data
526
+ *
527
+ * All callbacks are optional - if not provided, the corresponding
528
+ * module/syntax will be output as-is in the AST without resolution.
529
+ *
530
+ * Note: Include resolution is handled separately via resolveIncludes().
531
+ */
532
+ interface DataProvider {
533
+ /**
534
+ * Fetch data for ListPages module
535
+ * Called during resolve phase with query parameters
536
+ *
537
+ * @security `req.query` / `req.rawAttributes` are **untrusted user input** from wikitext.
538
+ * When building database queries:
539
+ * - **NEVER** interpolate them into SQL strings
540
+ * - **ALWAYS** use parameterized queries / prepared statements
541
+ * - For `order` (ORDER BY), use a whitelist of allowed column names
542
+ */
543
+ fetchListPages?: ListPagesDataFetcher;
544
+ /**
545
+ * Fetch data for ListUsers module
546
+ * Called during resolve phase with user query parameters
547
+ */
548
+ fetchListUsers?: ListUsersDataFetcher;
549
+ /**
550
+ * Get current page's tags for iftags evaluation
551
+ * Called during resolve phase to evaluate [[iftags]] conditions
552
+ */
553
+ getPageTags?: IfTagsResolver;
554
+ }
555
+ import { SyntaxTree as SyntaxTree2 } from "@wdprlib/ast";
556
+ /**
557
+ * Result of extraction including compiled templates
558
+ */
559
+ interface ExtractionResult {
560
+ /** Data requirements for external fetching */
561
+ requirements: DataRequirements;
562
+ /** Pre-compiled ListPages templates keyed by module id */
563
+ compiledListPagesTemplates: Map<number, CompiledTemplate>;
564
+ /** Pre-compiled ListUsers templates keyed by module id */
565
+ compiledListUsersTemplates: Map<number, ListUsersCompiledTemplate>;
566
+ }
567
+ /**
568
+ * Extract data requirements from a parsed AST
569
+ */
570
+ declare function extractDataRequirements(ast: SyntaxTree2): ExtractionResult;
571
+ /**
572
+ * Compile a template string into an executable function
573
+ */
574
+ declare function compileTemplate(template: string): CompiledTemplate;
575
+ /**
576
+ * Parse tags string into structured format
577
+ *
578
+ * Syntax:
579
+ * - `+tag`: AND condition (must have this tag)
580
+ * - `-tag`: NOT condition (must not have this tag)
581
+ * - `tag`: OR condition (any of these tags)
582
+ * - `=`: same visible tags as current page
583
+ * - `==`: exact same tags as current page
584
+ * - `-`: pages with no tags
585
+ */
586
+ declare function parseTags(value: string): NormalizedTags;
587
+ /**
588
+ * Parse category string into structured format
589
+ *
590
+ * Syntax:
591
+ * - `*`: all categories
592
+ * - `.`: current category
593
+ * - `-category`: exclude category
594
+ * - `category`: include category
595
+ * - Multiple categories separated by comma, semicolon, or whitespace
596
+ */
597
+ declare function parseCategory(value: string): NormalizedCategory;
598
+ /**
599
+ * Parse order string into structured format
600
+ *
601
+ * Supports both formats:
602
+ * - camelCase: `dateCreatedDesc`, `titleAsc`, `ratingDesc`
603
+ * - Space-separated: `created_at desc`, `title asc`
604
+ *
605
+ * Default: { field: "created_at", direction: "desc" }
606
+ */
607
+ declare function parseOrder(value: string): NormalizedOrder;
608
+ /**
609
+ * Parse parent string into structured format
610
+ *
611
+ * Syntax:
612
+ * - `-`: orphan pages (no parent)
613
+ * - `=`: sibling pages (same parent as current)
614
+ * - `-=`: pages with different parent
615
+ * - `.`: children of current page
616
+ * - `page-name`: children of specific page
617
+ *
618
+ * Returns undefined for empty/whitespace-only input.
619
+ */
620
+ declare function parseParent(value: string): NormalizedParent | undefined;
621
+ /**
622
+ * Parse date selector string into structured format
623
+ *
624
+ * Syntax:
625
+ * - `yyyy`: year only
626
+ * - `yyyy.mm`: year and month
627
+ * - `>=yyyy.mm.dd`: comparison with date
628
+ * - `last 7 days`: relative date
629
+ */
630
+ declare function parseDateSelector(value: string): NormalizedDateSelector | undefined;
631
+ /**
632
+ * Parse numeric selector string into structured format
633
+ *
634
+ * Syntax:
635
+ * - `5`: equals 5
636
+ * - `>=10`: greater than or equal to 10
637
+ * - `<0`: less than 0
638
+ *
639
+ * Returns undefined for non-numeric or infinite values.
640
+ */
641
+ declare function parseNumericSelector(value: string): NormalizedNumericSelector | undefined;
642
+ /**
643
+ * Normalize a ListPagesQuery into structured types
644
+ *
645
+ * @param query - Raw query with string fields
646
+ * @returns Normalized query with structured types
647
+ */
648
+ declare function normalizeQuery(query: ListPagesQuery): NormalizedListPagesQuery;
649
+ import { PageRef } from "@wdprlib/ast";
650
+ /**
651
+ * Callback to fetch page content for include resolution.
652
+ * Returns the wikitext source of the page, or null if the page does not exist.
653
+ *
654
+ * @security The fetcher is called with user-provided page references.
655
+ * Implementations should validate and sanitize page references before
656
+ * using them in database queries or file system access.
657
+ */
658
+ type IncludeFetcher = (pageRef: PageRef) => string | null;
659
+ /**
660
+ * Options for resolveIncludes
661
+ */
662
+ interface ResolveIncludesOptions {
663
+ /** Maximum recursion depth for nested includes (default: 5) */
664
+ maxDepth?: number;
665
+ }
666
+ /**
667
+ * Expand all [[include]] directives in the source text.
668
+ *
669
+ * Include directives are treated as macro expansions: `[[include page]]`
670
+ * is replaced with the fetched page content (after variable substitution).
671
+ * The result is a single expanded text that can be parsed as a whole,
672
+ * allowing block structures (like div) to span across include boundaries.
673
+ *
674
+ * @example
675
+ * ```ts
676
+ * const expanded = resolveIncludes(source, fetcher);
677
+ * const ast = parse(expanded);
678
+ * ```
679
+ */
680
+ declare function resolveIncludes(source: string, fetcher: IncludeFetcher, options?: ResolveIncludesOptions): string;
681
+ /**
682
+ * Compile a template string into an executable function
683
+ */
684
+ declare function compileListUsersTemplate(template: string): ListUsersCompiledTemplate;
685
+ /**
686
+ * Extract needed variables from a template string
687
+ */
688
+ declare function extractListUsersVariables(template: string): ListUsersVariable[];
689
+ import { Element as Element5, Module as Module3 } from "@wdprlib/ast";
690
+ /**
691
+ * ListUsers module data type
692
+ */
693
+ type ListUsersModuleData = Extract<Module3, {
694
+ module: "list-users";
695
+ }>;
696
+ /**
697
+ * Type guard for list-users module
698
+ */
699
+ declare function isListUsersModule(module: Module3): module is ListUsersModuleData;
700
+ /**
701
+ * Resolve a single ListUsers module
702
+ * Note: ListUsers returns only the logged-in user
703
+ */
704
+ declare function resolveListUsers(_module: ListUsersModuleData, data: ListUsersExternalData, compiledTemplate: ListUsersCompiledTemplate, parse: ParseFunction): Element5[];
705
+ import { SyntaxTree as SyntaxTree3 } from "@wdprlib/ast";
706
+ /**
707
+ * Options for resolving modules
708
+ */
709
+ interface ResolveOptions {
710
+ /** Parser function for re-parsing templates */
711
+ parse: ParseFunction;
712
+ /** Pre-compiled templates for ListPages */
713
+ compiledListPagesTemplates: Map<number, CompiledTemplate>;
714
+ /** Pre-compiled templates for ListUsers */
715
+ compiledListUsersTemplates?: Map<number, ListUsersCompiledTemplate>;
716
+ /** Data requirements grouped by module type */
717
+ requirements: {
718
+ listPages?: ListPagesDataRequirement[];
719
+ listUsers?: ListUsersDataRequirement[];
720
+ };
721
+ /**
722
+ * URL path for @URL parameter resolution (HPC support)
723
+ * Format: "/page-name/param/value/param/value"
724
+ * Example: "/scp-001/offset/10/page2_limit/5"
725
+ */
726
+ urlPath?: string;
727
+ }
728
+ /**
729
+ * Resolve all modules in the AST
730
+ *
731
+ * Fetches data for each module using the provided callback,
732
+ * then expands the modules with the fetched data.
733
+ *
734
+ * Handles:
735
+ * - ListPages: fetches page data and expands templates
736
+ * - IfTags: evaluates tag conditions and includes/excludes content
737
+ *
738
+ * @param ast - Parsed AST
739
+ * @param dataProvider - Callback provider to fetch data for each module
740
+ * @param options - Resolution options including requirements
741
+ */
742
+ declare function resolveModules(ast: SyntaxTree3, dataProvider: DataProvider, options: ResolveOptions): Promise<SyntaxTree3>;
743
+ export { tokenize, text, resolveModules, resolveListUsers, resolveIncludes, parseTags, parseParent, parseOrder, parseNumericSelector, parseDateSelector, parseCategory, parse, paragraph, normalizeQuery, listItemSubList, listItemElements, list, link, lineBreak, italics, isListUsersModule, horizontalRule, heading, extractListUsersVariables, extractDataRequirements, createToken, createPosition, createPoint, container, compileTemplate, compileListUsersTemplate, bold, Version2 as Version, VariableMap, VariableContext, UserInfo, TokenType, Token, TocEntry2 as TocEntry, TableRow, TableData, TableCell, TabData, SyntaxTree4 as SyntaxTree, SiteContext, ResolveOptions, ResolveIncludesOptions, Position2 as Position, Point, ParserOptions, Parser, ParseFunction, PageRef2 as PageRef, PageData, NormalizedTags, NormalizedParent, NormalizedOrder, NormalizedNumericSelector, NormalizedListPagesQuery, NormalizedDateSelector, NormalizedCategory, Module4 as Module, ListUsersVariableContext, ListUsersVariable, ListUsersUserData, ListUsersExternalData, ListUsersDataRequirement, ListUsersDataFetcher, ListUsersCompiledTemplate, ListType, ListPagesVariable, ListPagesQuery, ListPagesExternalData, ListPagesDataRequirement, ListPagesDataFetcher, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LexerOptions, Lexer, IncludeFetcher, ImageSource, HeadingLevel, Heading, HeaderType, FloatAlignment, ExtractionResult, Embed, Element6 as Element, DefinitionListItem, DateItem, DataRequirements, DataProvider, ContainerType, ContainerData, CompiledTemplate, CollapsibleData, CodeBlockData2 as CodeBlockData, ClearFloat, AttributeMap, AnchorTarget, Alignment, AlignType };