@wdprlib/ast 1.2.1 → 2.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.
- package/dist/index.cjs +397 -3
- package/dist/index.d.cts +71 -7
- package/dist/index.d.ts +71 -7
- package/dist/index.js +397 -3
- package/package.json +4 -2
- package/src/constants.ts +12 -0
- package/src/diagnostic.ts +104 -0
- package/src/element.ts +1287 -0
- package/src/expr-eval.ts +586 -0
- package/src/index.ts +119 -0
- package/src/position.ts +73 -0
- package/src/settings.ts +157 -0
package/dist/index.cjs
CHANGED
|
@@ -38,6 +38,7 @@ __export(exports_src, {
|
|
|
38
38
|
link: () => link,
|
|
39
39
|
lineBreak: () => lineBreak,
|
|
40
40
|
italics: () => italics,
|
|
41
|
+
isTruthy: () => isTruthy,
|
|
41
42
|
isStringContainerType: () => isStringContainerType,
|
|
42
43
|
isParagraphSafe: () => isParagraphSafe,
|
|
43
44
|
isHeaderType: () => isHeaderType,
|
|
@@ -45,6 +46,8 @@ __export(exports_src, {
|
|
|
45
46
|
isAlignType: () => isAlignType,
|
|
46
47
|
horizontalRule: () => horizontalRule,
|
|
47
48
|
heading: () => heading,
|
|
49
|
+
formatExprValue: () => formatExprValue,
|
|
50
|
+
evaluateExpression: () => evaluateExpression,
|
|
48
51
|
createSettings: () => createSettings,
|
|
49
52
|
createPosition: () => createPosition,
|
|
50
53
|
createPoint: () => createPoint,
|
|
@@ -250,6 +253,394 @@ function isParagraphSafe(element) {
|
|
|
250
253
|
}
|
|
251
254
|
// packages/ast/src/constants.ts
|
|
252
255
|
var STYLE_SLOT_PREFIX = "\x00__IFTAGS_SLOT__";
|
|
256
|
+
// packages/ast/src/expr-eval.ts
|
|
257
|
+
var FALSE_VALUES = new Set(["false", "null", "", "0"]);
|
|
258
|
+
function isTruthy(value) {
|
|
259
|
+
return !FALSE_VALUES.has(value.toLowerCase().trim());
|
|
260
|
+
}
|
|
261
|
+
var MAX_EXPRESSION_LENGTH = 256;
|
|
262
|
+
function isTruthyNum(n) {
|
|
263
|
+
return n !== 0 && !Number.isNaN(n);
|
|
264
|
+
}
|
|
265
|
+
function formatExprValue(n) {
|
|
266
|
+
return String(n);
|
|
267
|
+
}
|
|
268
|
+
function evaluateExpression(expr) {
|
|
269
|
+
try {
|
|
270
|
+
if (expr.length > MAX_EXPRESSION_LENGTH) {
|
|
271
|
+
return { success: false, error: "expression too long" };
|
|
272
|
+
}
|
|
273
|
+
if (expr.trim() === "") {
|
|
274
|
+
return { success: false, error: "empty expression" };
|
|
275
|
+
}
|
|
276
|
+
const tokens = tokenize(expr);
|
|
277
|
+
if (tokens.length <= 1) {
|
|
278
|
+
return { success: false, error: "empty expression" };
|
|
279
|
+
}
|
|
280
|
+
const parser = new ExprParser(tokens);
|
|
281
|
+
const result = parser.parse();
|
|
282
|
+
if (!Number.isFinite(result)) {
|
|
283
|
+
return { success: false, error: "division by zero" };
|
|
284
|
+
}
|
|
285
|
+
return { success: true, value: result };
|
|
286
|
+
} catch (e) {
|
|
287
|
+
const msg = e instanceof Error ? e.message : "unknown error";
|
|
288
|
+
return { success: false, error: msg };
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function tokenize(expr) {
|
|
292
|
+
const tokens = [];
|
|
293
|
+
let i = 0;
|
|
294
|
+
while (i < expr.length) {
|
|
295
|
+
const ch = expr[i];
|
|
296
|
+
if (/\s/.test(ch)) {
|
|
297
|
+
i++;
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
if (/\d/.test(ch) || ch === "." && /\d/.test(expr[i + 1] ?? "")) {
|
|
301
|
+
let numStr = "";
|
|
302
|
+
let hasDot = false;
|
|
303
|
+
while (i < expr.length) {
|
|
304
|
+
const c = expr[i];
|
|
305
|
+
if (c === ".") {
|
|
306
|
+
if (hasDot)
|
|
307
|
+
break;
|
|
308
|
+
hasDot = true;
|
|
309
|
+
} else if (!/\d/.test(c)) {
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
numStr += c;
|
|
313
|
+
i++;
|
|
314
|
+
}
|
|
315
|
+
const num = parseFloat(numStr);
|
|
316
|
+
if (!Number.isFinite(num)) {
|
|
317
|
+
throw new Error("Invalid number");
|
|
318
|
+
}
|
|
319
|
+
tokens.push({ kind: "NUMBER", value: num });
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
if (/[a-zA-Z_]/.test(ch)) {
|
|
323
|
+
let id = "";
|
|
324
|
+
while (i < expr.length) {
|
|
325
|
+
const c = expr[i];
|
|
326
|
+
if (!/[a-zA-Z0-9_]/.test(c))
|
|
327
|
+
break;
|
|
328
|
+
id += c;
|
|
329
|
+
i++;
|
|
330
|
+
}
|
|
331
|
+
tokens.push({ kind: "IDENTIFIER", value: id.toLowerCase() });
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (ch === "<" && expr[i + 1] === "=") {
|
|
335
|
+
tokens.push({ kind: "LE", value: "<=" });
|
|
336
|
+
i += 2;
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (ch === ">" && expr[i + 1] === "=") {
|
|
340
|
+
tokens.push({ kind: "GE", value: ">=" });
|
|
341
|
+
i += 2;
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (ch === "!" && expr[i + 1] === "=") {
|
|
345
|
+
tokens.push({ kind: "NE", value: "!=" });
|
|
346
|
+
i += 2;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
if (ch === "<" && expr[i + 1] === ">") {
|
|
350
|
+
tokens.push({ kind: "NE", value: "<>" });
|
|
351
|
+
i += 2;
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (ch === "!") {
|
|
355
|
+
tokens.push({ kind: "BANG", value: "!" });
|
|
356
|
+
i++;
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
switch (ch) {
|
|
360
|
+
case "+":
|
|
361
|
+
tokens.push({ kind: "PLUS", value: "+" });
|
|
362
|
+
break;
|
|
363
|
+
case "-":
|
|
364
|
+
tokens.push({ kind: "MINUS", value: "-" });
|
|
365
|
+
break;
|
|
366
|
+
case "*":
|
|
367
|
+
tokens.push({ kind: "STAR", value: "*" });
|
|
368
|
+
break;
|
|
369
|
+
case "/":
|
|
370
|
+
tokens.push({ kind: "SLASH", value: "/" });
|
|
371
|
+
break;
|
|
372
|
+
case "%":
|
|
373
|
+
tokens.push({ kind: "PERCENT", value: "%" });
|
|
374
|
+
break;
|
|
375
|
+
case "^":
|
|
376
|
+
tokens.push({ kind: "CARET", value: "^" });
|
|
377
|
+
break;
|
|
378
|
+
case "(":
|
|
379
|
+
tokens.push({ kind: "LPAREN", value: "(" });
|
|
380
|
+
break;
|
|
381
|
+
case ")":
|
|
382
|
+
tokens.push({ kind: "RPAREN", value: ")" });
|
|
383
|
+
break;
|
|
384
|
+
case ",":
|
|
385
|
+
tokens.push({ kind: "COMMA", value: "," });
|
|
386
|
+
break;
|
|
387
|
+
case "<":
|
|
388
|
+
tokens.push({ kind: "LT", value: "<" });
|
|
389
|
+
break;
|
|
390
|
+
case ">":
|
|
391
|
+
tokens.push({ kind: "GT", value: ">" });
|
|
392
|
+
break;
|
|
393
|
+
case "=":
|
|
394
|
+
tokens.push({ kind: "EQ", value: "=" });
|
|
395
|
+
break;
|
|
396
|
+
default:
|
|
397
|
+
throw new Error(`Unknown character: ${ch}`);
|
|
398
|
+
}
|
|
399
|
+
i++;
|
|
400
|
+
}
|
|
401
|
+
tokens.push({ kind: "EOF", value: "" });
|
|
402
|
+
return tokens;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
class ExprParser {
|
|
406
|
+
tokens;
|
|
407
|
+
pos = 0;
|
|
408
|
+
constructor(tokens) {
|
|
409
|
+
this.tokens = tokens;
|
|
410
|
+
}
|
|
411
|
+
parse() {
|
|
412
|
+
const result = this.parseOr();
|
|
413
|
+
if (this.current().kind !== "EOF") {
|
|
414
|
+
throw new Error("too many values in the stack");
|
|
415
|
+
}
|
|
416
|
+
return result;
|
|
417
|
+
}
|
|
418
|
+
current() {
|
|
419
|
+
return this.tokens[this.pos] ?? { kind: "EOF", value: "" };
|
|
420
|
+
}
|
|
421
|
+
advance() {
|
|
422
|
+
const token = this.current();
|
|
423
|
+
this.pos++;
|
|
424
|
+
return token;
|
|
425
|
+
}
|
|
426
|
+
parseOr() {
|
|
427
|
+
let left = this.parseAnd();
|
|
428
|
+
while (this.current().kind === "IDENTIFIER" && this.current().value === "or") {
|
|
429
|
+
this.advance();
|
|
430
|
+
const right = this.parseAnd();
|
|
431
|
+
left = isTruthyNum(left) || isTruthyNum(right) ? 1 : 0;
|
|
432
|
+
}
|
|
433
|
+
return left;
|
|
434
|
+
}
|
|
435
|
+
parseAnd() {
|
|
436
|
+
let left = this.parseNot();
|
|
437
|
+
while (this.current().kind === "IDENTIFIER" && this.current().value === "and") {
|
|
438
|
+
this.advance();
|
|
439
|
+
const right = this.parseNot();
|
|
440
|
+
left = isTruthyNum(left) && isTruthyNum(right) ? 1 : 0;
|
|
441
|
+
}
|
|
442
|
+
return left;
|
|
443
|
+
}
|
|
444
|
+
parseNot() {
|
|
445
|
+
const cur = this.current();
|
|
446
|
+
if (cur.kind === "IDENTIFIER" && cur.value === "not" || cur.kind === "BANG") {
|
|
447
|
+
this.advance();
|
|
448
|
+
const value = this.parseNot();
|
|
449
|
+
return isTruthyNum(value) ? 0 : 1;
|
|
450
|
+
}
|
|
451
|
+
return this.parseComparison();
|
|
452
|
+
}
|
|
453
|
+
parseComparison() {
|
|
454
|
+
let left = this.parseAddition();
|
|
455
|
+
const kind = this.current().kind;
|
|
456
|
+
if (kind === "LT" || kind === "GT" || kind === "LE" || kind === "GE" || kind === "EQ" || kind === "NE") {
|
|
457
|
+
this.advance();
|
|
458
|
+
const right = this.parseAddition();
|
|
459
|
+
switch (kind) {
|
|
460
|
+
case "LT":
|
|
461
|
+
return left < right ? 1 : 0;
|
|
462
|
+
case "GT":
|
|
463
|
+
return left > right ? 1 : 0;
|
|
464
|
+
case "LE":
|
|
465
|
+
return left <= right ? 1 : 0;
|
|
466
|
+
case "GE":
|
|
467
|
+
return left >= right ? 1 : 0;
|
|
468
|
+
case "EQ":
|
|
469
|
+
return left === right ? 1 : 0;
|
|
470
|
+
case "NE":
|
|
471
|
+
return left !== right ? 1 : 0;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return left;
|
|
475
|
+
}
|
|
476
|
+
parseAddition() {
|
|
477
|
+
let left = this.parseMultiplication();
|
|
478
|
+
while (true) {
|
|
479
|
+
const kind = this.current().kind;
|
|
480
|
+
if (kind === "PLUS") {
|
|
481
|
+
this.advance();
|
|
482
|
+
left = left + this.parseMultiplication();
|
|
483
|
+
} else if (kind === "MINUS") {
|
|
484
|
+
this.advance();
|
|
485
|
+
left = left - this.parseMultiplication();
|
|
486
|
+
} else {
|
|
487
|
+
break;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return left;
|
|
491
|
+
}
|
|
492
|
+
parseMultiplication() {
|
|
493
|
+
let left = this.parsePower();
|
|
494
|
+
while (true) {
|
|
495
|
+
const kind = this.current().kind;
|
|
496
|
+
if (kind === "STAR") {
|
|
497
|
+
this.advance();
|
|
498
|
+
left = left * this.parsePower();
|
|
499
|
+
} else if (kind === "SLASH") {
|
|
500
|
+
this.advance();
|
|
501
|
+
left = left / this.parsePower();
|
|
502
|
+
} else if (kind === "PERCENT") {
|
|
503
|
+
this.advance();
|
|
504
|
+
left = left % this.parsePower();
|
|
505
|
+
} else {
|
|
506
|
+
break;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return left;
|
|
510
|
+
}
|
|
511
|
+
parsePower() {
|
|
512
|
+
const left = this.parseUnary();
|
|
513
|
+
if (this.current().kind === "CARET") {
|
|
514
|
+
this.advance();
|
|
515
|
+
const right = this.parsePower();
|
|
516
|
+
return Math.pow(left, right);
|
|
517
|
+
}
|
|
518
|
+
return left;
|
|
519
|
+
}
|
|
520
|
+
parseUnary() {
|
|
521
|
+
const kind = this.current().kind;
|
|
522
|
+
if (kind === "MINUS") {
|
|
523
|
+
this.advance();
|
|
524
|
+
return -this.parseUnary();
|
|
525
|
+
}
|
|
526
|
+
if (kind === "PLUS") {
|
|
527
|
+
this.advance();
|
|
528
|
+
return +this.parseUnary();
|
|
529
|
+
}
|
|
530
|
+
if (kind === "BANG") {
|
|
531
|
+
this.advance();
|
|
532
|
+
const value = this.parseUnary();
|
|
533
|
+
return isTruthyNum(value) ? 0 : 1;
|
|
534
|
+
}
|
|
535
|
+
return this.parsePrimary();
|
|
536
|
+
}
|
|
537
|
+
parsePrimary() {
|
|
538
|
+
const token = this.current();
|
|
539
|
+
if (token.kind === "NUMBER") {
|
|
540
|
+
this.advance();
|
|
541
|
+
return token.value;
|
|
542
|
+
}
|
|
543
|
+
if (token.kind === "LPAREN") {
|
|
544
|
+
this.advance();
|
|
545
|
+
const value = this.parseOr();
|
|
546
|
+
if (this.current().kind !== "RPAREN") {
|
|
547
|
+
throw new Error("Expected )");
|
|
548
|
+
}
|
|
549
|
+
this.advance();
|
|
550
|
+
return value;
|
|
551
|
+
}
|
|
552
|
+
if (token.kind === "IDENTIFIER") {
|
|
553
|
+
const name = token.value;
|
|
554
|
+
this.advance();
|
|
555
|
+
if (this.current().kind === "LPAREN") {
|
|
556
|
+
return this.parseFunctionCall(name);
|
|
557
|
+
}
|
|
558
|
+
if (name === "true")
|
|
559
|
+
return 1;
|
|
560
|
+
if (name === "false")
|
|
561
|
+
return 0;
|
|
562
|
+
throw new Error(`undefined constant "${name}"`);
|
|
563
|
+
}
|
|
564
|
+
throw new Error("Expected expression");
|
|
565
|
+
}
|
|
566
|
+
parseFunctionCall(name) {
|
|
567
|
+
if (this.current().kind !== "LPAREN") {
|
|
568
|
+
throw new Error("Expected (");
|
|
569
|
+
}
|
|
570
|
+
this.advance();
|
|
571
|
+
const args = [];
|
|
572
|
+
if (this.current().kind !== "RPAREN") {
|
|
573
|
+
args.push(this.parseOr());
|
|
574
|
+
while (this.current().kind === "COMMA") {
|
|
575
|
+
this.advance();
|
|
576
|
+
args.push(this.parseOr());
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (this.current().kind !== "RPAREN") {
|
|
580
|
+
throw new Error("Expected )");
|
|
581
|
+
}
|
|
582
|
+
this.advance();
|
|
583
|
+
return this.callFunction(name, args);
|
|
584
|
+
}
|
|
585
|
+
callFunction(name, args) {
|
|
586
|
+
switch (name) {
|
|
587
|
+
case "abs":
|
|
588
|
+
this.checkArgs(name, args, 1);
|
|
589
|
+
return Math.abs(args[0]);
|
|
590
|
+
case "min":
|
|
591
|
+
this.checkArgsMin(name, args, 1);
|
|
592
|
+
return Math.min(...args);
|
|
593
|
+
case "max":
|
|
594
|
+
this.checkArgsMin(name, args, 1);
|
|
595
|
+
return Math.max(...args);
|
|
596
|
+
case "floor":
|
|
597
|
+
this.checkArgs(name, args, 1);
|
|
598
|
+
return Math.floor(args[0]);
|
|
599
|
+
case "ceil":
|
|
600
|
+
this.checkArgs(name, args, 1);
|
|
601
|
+
return Math.ceil(args[0]);
|
|
602
|
+
case "round":
|
|
603
|
+
this.checkArgs(name, args, 1);
|
|
604
|
+
return Math.round(args[0]);
|
|
605
|
+
case "sqrt":
|
|
606
|
+
this.checkArgs(name, args, 1);
|
|
607
|
+
return Math.sqrt(args[0]);
|
|
608
|
+
case "sin":
|
|
609
|
+
this.checkArgs(name, args, 1);
|
|
610
|
+
return Math.sin(args[0]);
|
|
611
|
+
case "cos":
|
|
612
|
+
this.checkArgs(name, args, 1);
|
|
613
|
+
return Math.cos(args[0]);
|
|
614
|
+
case "tan":
|
|
615
|
+
this.checkArgs(name, args, 1);
|
|
616
|
+
return Math.tan(args[0]);
|
|
617
|
+
case "ln":
|
|
618
|
+
this.checkArgs(name, args, 1);
|
|
619
|
+
return Math.log(args[0]);
|
|
620
|
+
case "log":
|
|
621
|
+
this.checkArgs(name, args, 1);
|
|
622
|
+
return Math.log10(args[0]);
|
|
623
|
+
case "exp":
|
|
624
|
+
this.checkArgs(name, args, 1);
|
|
625
|
+
return Math.exp(args[0]);
|
|
626
|
+
case "pow":
|
|
627
|
+
this.checkArgs(name, args, 2);
|
|
628
|
+
return Math.pow(args[0], args[1]);
|
|
629
|
+
default:
|
|
630
|
+
throw new Error(`undefined function "${name}"`);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
checkArgs(name, args, expected) {
|
|
634
|
+
if (args.length !== expected) {
|
|
635
|
+
throw new Error(`${name}() expects ${expected} argument(s), got ${args.length}`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
checkArgsMin(name, args, min) {
|
|
639
|
+
if (args.length < min) {
|
|
640
|
+
throw new Error(`${name}() expects at least ${min} argument(s), got ${args.length}`);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
253
644
|
// packages/ast/src/settings.ts
|
|
254
645
|
function createSettings(mode) {
|
|
255
646
|
switch (mode) {
|
|
@@ -259,7 +650,8 @@ function createSettings(mode) {
|
|
|
259
650
|
enablePageSyntax: true,
|
|
260
651
|
allowLocalPaths: true,
|
|
261
652
|
useTrueIds: true,
|
|
262
|
-
allowStyleElements: true
|
|
653
|
+
allowStyleElements: true,
|
|
654
|
+
allowHtmlBlocks: true
|
|
263
655
|
};
|
|
264
656
|
case "draft":
|
|
265
657
|
return {
|
|
@@ -267,7 +659,8 @@ function createSettings(mode) {
|
|
|
267
659
|
enablePageSyntax: true,
|
|
268
660
|
allowLocalPaths: true,
|
|
269
661
|
useTrueIds: false,
|
|
270
|
-
allowStyleElements: false
|
|
662
|
+
allowStyleElements: false,
|
|
663
|
+
allowHtmlBlocks: false
|
|
271
664
|
};
|
|
272
665
|
case "forum-post":
|
|
273
666
|
case "direct-message":
|
|
@@ -276,7 +669,8 @@ function createSettings(mode) {
|
|
|
276
669
|
enablePageSyntax: false,
|
|
277
670
|
allowLocalPaths: false,
|
|
278
671
|
useTrueIds: false,
|
|
279
|
-
allowStyleElements: false
|
|
672
|
+
allowStyleElements: false,
|
|
673
|
+
allowHtmlBlocks: false
|
|
280
674
|
};
|
|
281
675
|
}
|
|
282
676
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1154,12 +1154,12 @@ declare const STYLE_SLOT_PREFIX = "\0__IFTAGS_SLOT__";
|
|
|
1154
1154
|
* {@link WikitextSettings}. The modes correspond to the places where
|
|
1155
1155
|
* user-authored wikitext can appear on a Wikidot site.
|
|
1156
1156
|
*
|
|
1157
|
-
* | Mode | Page syntax | Local paths | True IDs | Style elements |
|
|
1158
|
-
*
|
|
1159
|
-
* | `"page"` | yes | yes | yes | yes |
|
|
1160
|
-
* | `"draft"` | yes | yes | no | no |
|
|
1161
|
-
* | `"forum-post"` | no | no | no | no |
|
|
1162
|
-
* | `"direct-message"` | no | no | no | no |
|
|
1157
|
+
* | Mode | Page syntax | Local paths | True IDs | Style elements | HTML blocks |
|
|
1158
|
+
* |--------------------|:-----------:|:-----------:|:--------:|:--------------:|:-----------:|
|
|
1159
|
+
* | `"page"` | yes | yes | yes | yes | yes |
|
|
1160
|
+
* | `"draft"` | yes | yes | no | no | no |
|
|
1161
|
+
* | `"forum-post"` | no | no | no | no | no |
|
|
1162
|
+
* | `"direct-message"` | no | no | no | no | no |
|
|
1163
1163
|
*
|
|
1164
1164
|
* @group Settings
|
|
1165
1165
|
*/
|
|
@@ -1210,6 +1210,25 @@ interface WikitextSettings {
|
|
|
1210
1210
|
* the CSS module is silently ignored.
|
|
1211
1211
|
*/
|
|
1212
1212
|
allowStyleElements: boolean;
|
|
1213
|
+
/**
|
|
1214
|
+
* Whether `[[html]]` blocks are recognised by the parser and rendered.
|
|
1215
|
+
*
|
|
1216
|
+
* HTML blocks embed raw HTML that the renderer serves inside a sandboxed
|
|
1217
|
+
* iframe. The capability is meaningful only in contexts that can host
|
|
1218
|
+
* the auxiliary iframe URL, so it is disabled in drafts, forum posts,
|
|
1219
|
+
* and direct messages.
|
|
1220
|
+
*
|
|
1221
|
+
* When `false`, the parser still consumes the entire `[[html]]...[[/html]]`
|
|
1222
|
+
* span (so the raw body cannot leak as text) but emits no AST node, and
|
|
1223
|
+
* the renderer skips any pre-existing `html` element it encounters.
|
|
1224
|
+
*
|
|
1225
|
+
* Wikidot's legacy `Text_Wiki` keeps `Html` in its `$disable` list by
|
|
1226
|
+
* default (`lib/Text_Wiki/Text/Wiki.php` line 145-147), so an authentic
|
|
1227
|
+
* Wikidot-compat default would be `false` even in `"page"` mode. wp
|
|
1228
|
+
* keeps `"page"` at `true` for now to preserve existing consumers; a
|
|
1229
|
+
* future change may align with Wikidot.
|
|
1230
|
+
*/
|
|
1231
|
+
allowHtmlBlocks: boolean;
|
|
1213
1232
|
}
|
|
1214
1233
|
/**
|
|
1215
1234
|
* Create a {@link WikitextSettings} with sensible defaults for the given mode.
|
|
@@ -1232,6 +1251,51 @@ declare function createSettings(mode: WikitextMode): WikitextSettings;
|
|
|
1232
1251
|
*/
|
|
1233
1252
|
declare const DEFAULT_SETTINGS: WikitextSettings;
|
|
1234
1253
|
/**
|
|
1254
|
+
* Determine whether a string value is truthy for Wikidot's `#if` construct.
|
|
1255
|
+
*
|
|
1256
|
+
* The value is lowercased and trimmed before checking against the set of
|
|
1257
|
+
* known falsy strings (`"false"`, `"null"`, `""`, `"0"`).
|
|
1258
|
+
*
|
|
1259
|
+
* @param value - The condition string to check.
|
|
1260
|
+
* @returns `true` if the value is not in the falsy set.
|
|
1261
|
+
*/
|
|
1262
|
+
declare function isTruthy(value: string): boolean;
|
|
1263
|
+
/**
|
|
1264
|
+
* Result of evaluating a mathematical expression.
|
|
1265
|
+
* Either a successful numeric value or an error message string.
|
|
1266
|
+
*/
|
|
1267
|
+
type ExprResult = {
|
|
1268
|
+
success: true;
|
|
1269
|
+
value: number;
|
|
1270
|
+
} | {
|
|
1271
|
+
success: false;
|
|
1272
|
+
error: string;
|
|
1273
|
+
};
|
|
1274
|
+
/**
|
|
1275
|
+
* Format a numeric expression result for display.
|
|
1276
|
+
*
|
|
1277
|
+
* Uses JavaScript's default `String(n)` so the full precision of the
|
|
1278
|
+
* computed value is preserved (e.g. `1/3` becomes `"0.3333333333333333"`,
|
|
1279
|
+
* matching the `Number` → `String` conversion rather than truncating to
|
|
1280
|
+
* a fixed number of decimals). Used by both the inline renderer and the
|
|
1281
|
+
* opener preprocess so the same expression produces the same string
|
|
1282
|
+
* regardless of where it appears in the source.
|
|
1283
|
+
*/
|
|
1284
|
+
declare function formatExprValue(n: number): string;
|
|
1285
|
+
/**
|
|
1286
|
+
* Evaluate a mathematical expression string and return the result.
|
|
1287
|
+
*
|
|
1288
|
+
* The expression is tokenized, parsed with a recursive descent parser,
|
|
1289
|
+
* and evaluated in a single pass. Errors produce Wikidot-compatible
|
|
1290
|
+
* messages (e.g., `"division by zero"`, `"too many values in the stack"`).
|
|
1291
|
+
*
|
|
1292
|
+
* NaN and Infinity results are treated as division-by-zero errors.
|
|
1293
|
+
*
|
|
1294
|
+
* @param expr - The expression string to evaluate.
|
|
1295
|
+
* @returns A success result with a numeric value, or an error result with a message.
|
|
1296
|
+
*/
|
|
1297
|
+
declare function evaluateExpression(expr: string): ExprResult;
|
|
1298
|
+
/**
|
|
1235
1299
|
* Identifies the source markup dialect.
|
|
1236
1300
|
*
|
|
1237
1301
|
* Currently only `"wikidot"` is supported. Included in {@link SyntaxTree}
|
|
@@ -1240,4 +1304,4 @@ declare const DEFAULT_SETTINGS: WikitextSettings;
|
|
|
1240
1304
|
* @group Core
|
|
1241
1305
|
*/
|
|
1242
1306
|
type Version = "wikidot";
|
|
1243
|
-
export { text, paragraph, listItemSubList, listItemElements, list, link, lineBreak, italics, isStringContainerType, isParagraphSafe, isHeaderType, isContainerTypeParagraphSafe, isAlignType, horizontalRule, heading, createSettings, createPosition, createPoint, container, bold, WikitextSettings, WikitextMode, Version, VariableMap, UserData, TocEntry, TableRow, TableOfContentsData, TableData, TableCell, TabData, SyntaxTree, StringContainerType, STYLE_SLOT_PREFIX, Position, Point, ParseResult, PageRef, Module, MathInlineData, MathData, ListType, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LinkData, IncludeData, ImageSource, ImageData, IframeData, IfTagsData, IfExprData, IfCondData, HtmlData, HeadingLevel, Heading, HeaderType, FootnoteBlockData, FloatAlignment, ExprData, EmbedBlockData, Embed, ElementOf, ElementName, ElementDataMap, ElementData, Element, DiagnosticSeverity, Diagnostic, DefinitionListItem, DateItem, DateData, DEFAULT_SETTINGS, ContainerType, ContainerData, ColorData, CollapsibleData, CodeBlockData, ClearFloat, BibliographyCiteData, BibliographyBlockData, AttributeMap, AnchorTarget, AnchorData, Alignment, AlignType };
|
|
1307
|
+
export { text, paragraph, listItemSubList, listItemElements, list, link, lineBreak, italics, isTruthy, isStringContainerType, isParagraphSafe, isHeaderType, isContainerTypeParagraphSafe, isAlignType, horizontalRule, heading, formatExprValue, evaluateExpression, createSettings, createPosition, createPoint, container, bold, WikitextSettings, WikitextMode, Version, VariableMap, UserData, TocEntry, TableRow, TableOfContentsData, TableData, TableCell, TabData, SyntaxTree, StringContainerType, STYLE_SLOT_PREFIX, Position, Point, ParseResult, PageRef, Module, MathInlineData, MathData, ListType, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LinkData, IncludeData, ImageSource, ImageData, IframeData, IfTagsData, IfExprData, IfCondData, HtmlData, HeadingLevel, Heading, HeaderType, FootnoteBlockData, FloatAlignment, ExprResult, ExprData, EmbedBlockData, Embed, ElementOf, ElementName, ElementDataMap, ElementData, Element, DiagnosticSeverity, Diagnostic, DefinitionListItem, DateItem, DateData, DEFAULT_SETTINGS, ContainerType, ContainerData, ColorData, CollapsibleData, CodeBlockData, ClearFloat, BibliographyCiteData, BibliographyBlockData, AttributeMap, AnchorTarget, AnchorData, Alignment, AlignType };
|
package/dist/index.d.ts
CHANGED
|
@@ -1154,12 +1154,12 @@ declare const STYLE_SLOT_PREFIX = "\0__IFTAGS_SLOT__";
|
|
|
1154
1154
|
* {@link WikitextSettings}. The modes correspond to the places where
|
|
1155
1155
|
* user-authored wikitext can appear on a Wikidot site.
|
|
1156
1156
|
*
|
|
1157
|
-
* | Mode | Page syntax | Local paths | True IDs | Style elements |
|
|
1158
|
-
*
|
|
1159
|
-
* | `"page"` | yes | yes | yes | yes |
|
|
1160
|
-
* | `"draft"` | yes | yes | no | no |
|
|
1161
|
-
* | `"forum-post"` | no | no | no | no |
|
|
1162
|
-
* | `"direct-message"` | no | no | no | no |
|
|
1157
|
+
* | Mode | Page syntax | Local paths | True IDs | Style elements | HTML blocks |
|
|
1158
|
+
* |--------------------|:-----------:|:-----------:|:--------:|:--------------:|:-----------:|
|
|
1159
|
+
* | `"page"` | yes | yes | yes | yes | yes |
|
|
1160
|
+
* | `"draft"` | yes | yes | no | no | no |
|
|
1161
|
+
* | `"forum-post"` | no | no | no | no | no |
|
|
1162
|
+
* | `"direct-message"` | no | no | no | no | no |
|
|
1163
1163
|
*
|
|
1164
1164
|
* @group Settings
|
|
1165
1165
|
*/
|
|
@@ -1210,6 +1210,25 @@ interface WikitextSettings {
|
|
|
1210
1210
|
* the CSS module is silently ignored.
|
|
1211
1211
|
*/
|
|
1212
1212
|
allowStyleElements: boolean;
|
|
1213
|
+
/**
|
|
1214
|
+
* Whether `[[html]]` blocks are recognised by the parser and rendered.
|
|
1215
|
+
*
|
|
1216
|
+
* HTML blocks embed raw HTML that the renderer serves inside a sandboxed
|
|
1217
|
+
* iframe. The capability is meaningful only in contexts that can host
|
|
1218
|
+
* the auxiliary iframe URL, so it is disabled in drafts, forum posts,
|
|
1219
|
+
* and direct messages.
|
|
1220
|
+
*
|
|
1221
|
+
* When `false`, the parser still consumes the entire `[[html]]...[[/html]]`
|
|
1222
|
+
* span (so the raw body cannot leak as text) but emits no AST node, and
|
|
1223
|
+
* the renderer skips any pre-existing `html` element it encounters.
|
|
1224
|
+
*
|
|
1225
|
+
* Wikidot's legacy `Text_Wiki` keeps `Html` in its `$disable` list by
|
|
1226
|
+
* default (`lib/Text_Wiki/Text/Wiki.php` line 145-147), so an authentic
|
|
1227
|
+
* Wikidot-compat default would be `false` even in `"page"` mode. wp
|
|
1228
|
+
* keeps `"page"` at `true` for now to preserve existing consumers; a
|
|
1229
|
+
* future change may align with Wikidot.
|
|
1230
|
+
*/
|
|
1231
|
+
allowHtmlBlocks: boolean;
|
|
1213
1232
|
}
|
|
1214
1233
|
/**
|
|
1215
1234
|
* Create a {@link WikitextSettings} with sensible defaults for the given mode.
|
|
@@ -1232,6 +1251,51 @@ declare function createSettings(mode: WikitextMode): WikitextSettings;
|
|
|
1232
1251
|
*/
|
|
1233
1252
|
declare const DEFAULT_SETTINGS: WikitextSettings;
|
|
1234
1253
|
/**
|
|
1254
|
+
* Determine whether a string value is truthy for Wikidot's `#if` construct.
|
|
1255
|
+
*
|
|
1256
|
+
* The value is lowercased and trimmed before checking against the set of
|
|
1257
|
+
* known falsy strings (`"false"`, `"null"`, `""`, `"0"`).
|
|
1258
|
+
*
|
|
1259
|
+
* @param value - The condition string to check.
|
|
1260
|
+
* @returns `true` if the value is not in the falsy set.
|
|
1261
|
+
*/
|
|
1262
|
+
declare function isTruthy(value: string): boolean;
|
|
1263
|
+
/**
|
|
1264
|
+
* Result of evaluating a mathematical expression.
|
|
1265
|
+
* Either a successful numeric value or an error message string.
|
|
1266
|
+
*/
|
|
1267
|
+
type ExprResult = {
|
|
1268
|
+
success: true;
|
|
1269
|
+
value: number;
|
|
1270
|
+
} | {
|
|
1271
|
+
success: false;
|
|
1272
|
+
error: string;
|
|
1273
|
+
};
|
|
1274
|
+
/**
|
|
1275
|
+
* Format a numeric expression result for display.
|
|
1276
|
+
*
|
|
1277
|
+
* Uses JavaScript's default `String(n)` so the full precision of the
|
|
1278
|
+
* computed value is preserved (e.g. `1/3` becomes `"0.3333333333333333"`,
|
|
1279
|
+
* matching the `Number` → `String` conversion rather than truncating to
|
|
1280
|
+
* a fixed number of decimals). Used by both the inline renderer and the
|
|
1281
|
+
* opener preprocess so the same expression produces the same string
|
|
1282
|
+
* regardless of where it appears in the source.
|
|
1283
|
+
*/
|
|
1284
|
+
declare function formatExprValue(n: number): string;
|
|
1285
|
+
/**
|
|
1286
|
+
* Evaluate a mathematical expression string and return the result.
|
|
1287
|
+
*
|
|
1288
|
+
* The expression is tokenized, parsed with a recursive descent parser,
|
|
1289
|
+
* and evaluated in a single pass. Errors produce Wikidot-compatible
|
|
1290
|
+
* messages (e.g., `"division by zero"`, `"too many values in the stack"`).
|
|
1291
|
+
*
|
|
1292
|
+
* NaN and Infinity results are treated as division-by-zero errors.
|
|
1293
|
+
*
|
|
1294
|
+
* @param expr - The expression string to evaluate.
|
|
1295
|
+
* @returns A success result with a numeric value, or an error result with a message.
|
|
1296
|
+
*/
|
|
1297
|
+
declare function evaluateExpression(expr: string): ExprResult;
|
|
1298
|
+
/**
|
|
1235
1299
|
* Identifies the source markup dialect.
|
|
1236
1300
|
*
|
|
1237
1301
|
* Currently only `"wikidot"` is supported. Included in {@link SyntaxTree}
|
|
@@ -1240,4 +1304,4 @@ declare const DEFAULT_SETTINGS: WikitextSettings;
|
|
|
1240
1304
|
* @group Core
|
|
1241
1305
|
*/
|
|
1242
1306
|
type Version = "wikidot";
|
|
1243
|
-
export { text, paragraph, listItemSubList, listItemElements, list, link, lineBreak, italics, isStringContainerType, isParagraphSafe, isHeaderType, isContainerTypeParagraphSafe, isAlignType, horizontalRule, heading, createSettings, createPosition, createPoint, container, bold, WikitextSettings, WikitextMode, Version, VariableMap, UserData, TocEntry, TableRow, TableOfContentsData, TableData, TableCell, TabData, SyntaxTree, StringContainerType, STYLE_SLOT_PREFIX, Position, Point, ParseResult, PageRef, Module, MathInlineData, MathData, ListType, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LinkData, IncludeData, ImageSource, ImageData, IframeData, IfTagsData, IfExprData, IfCondData, HtmlData, HeadingLevel, Heading, HeaderType, FootnoteBlockData, FloatAlignment, ExprData, EmbedBlockData, Embed, ElementOf, ElementName, ElementDataMap, ElementData, Element, DiagnosticSeverity, Diagnostic, DefinitionListItem, DateItem, DateData, DEFAULT_SETTINGS, ContainerType, ContainerData, ColorData, CollapsibleData, CodeBlockData, ClearFloat, BibliographyCiteData, BibliographyBlockData, AttributeMap, AnchorTarget, AnchorData, Alignment, AlignType };
|
|
1307
|
+
export { text, paragraph, listItemSubList, listItemElements, list, link, lineBreak, italics, isTruthy, isStringContainerType, isParagraphSafe, isHeaderType, isContainerTypeParagraphSafe, isAlignType, horizontalRule, heading, formatExprValue, evaluateExpression, createSettings, createPosition, createPoint, container, bold, WikitextSettings, WikitextMode, Version, VariableMap, UserData, TocEntry, TableRow, TableOfContentsData, TableData, TableCell, TabData, SyntaxTree, StringContainerType, STYLE_SLOT_PREFIX, Position, Point, ParseResult, PageRef, Module, MathInlineData, MathData, ListType, ListItem, ListData, LinkType, LinkLocation, LinkLabel, LinkData, IncludeData, ImageSource, ImageData, IframeData, IfTagsData, IfExprData, IfCondData, HtmlData, HeadingLevel, Heading, HeaderType, FootnoteBlockData, FloatAlignment, ExprResult, ExprData, EmbedBlockData, Embed, ElementOf, ElementName, ElementDataMap, ElementData, Element, DiagnosticSeverity, Diagnostic, DefinitionListItem, DateItem, DateData, DEFAULT_SETTINGS, ContainerType, ContainerData, ColorData, CollapsibleData, CodeBlockData, ClearFloat, BibliographyCiteData, BibliographyBlockData, AttributeMap, AnchorTarget, AnchorData, Alignment, AlignType };
|