@wdprlib/render 2.0.0 → 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.
Files changed (58) hide show
  1. package/dist/index.cjs +11 -387
  2. package/dist/index.js +2 -378
  3. package/package.json +5 -3
  4. package/src/context.ts +422 -0
  5. package/src/elements/bibliography.ts +123 -0
  6. package/src/elements/clear-float.ts +27 -0
  7. package/src/elements/code.ts +49 -0
  8. package/src/elements/collapsible.ts +105 -0
  9. package/src/elements/color.ts +32 -0
  10. package/src/elements/container.ts +302 -0
  11. package/src/elements/date.ts +59 -0
  12. package/src/elements/embed-block.ts +327 -0
  13. package/src/elements/embed.ts +166 -0
  14. package/src/elements/expr.ts +102 -0
  15. package/src/elements/footnote.ts +76 -0
  16. package/src/elements/html.ts +79 -0
  17. package/src/elements/iframe.ts +44 -0
  18. package/src/elements/iftags.ts +118 -0
  19. package/src/elements/image.ts +154 -0
  20. package/src/elements/include.ts +43 -0
  21. package/src/elements/index.ts +35 -0
  22. package/src/elements/line-break.ts +22 -0
  23. package/src/elements/link.ts +201 -0
  24. package/src/elements/list.ts +241 -0
  25. package/src/elements/math.ts +177 -0
  26. package/src/elements/module/backlinks.ts +28 -0
  27. package/src/elements/module/categories.ts +27 -0
  28. package/src/elements/module/index.ts +67 -0
  29. package/src/elements/module/join.ts +33 -0
  30. package/src/elements/module/listpages.ts +27 -0
  31. package/src/elements/module/listusers.ts +27 -0
  32. package/src/elements/module/page-tree.ts +27 -0
  33. package/src/elements/module/rate.ts +44 -0
  34. package/src/elements/tab-view.ts +75 -0
  35. package/src/elements/table.ts +101 -0
  36. package/src/elements/text.ts +57 -0
  37. package/src/elements/toc.ts +147 -0
  38. package/src/elements/user.ts +79 -0
  39. package/src/escape.ts +829 -0
  40. package/src/hash.ts +62 -0
  41. package/src/index.ts +26 -0
  42. package/src/libs/highlighter/engine.ts +352 -0
  43. package/src/libs/highlighter/index.ts +70 -0
  44. package/src/libs/highlighter/languages/cpp.ts +345 -0
  45. package/src/libs/highlighter/languages/css.ts +104 -0
  46. package/src/libs/highlighter/languages/diff.ts +154 -0
  47. package/src/libs/highlighter/languages/dtd.ts +99 -0
  48. package/src/libs/highlighter/languages/html.ts +59 -0
  49. package/src/libs/highlighter/languages/java.ts +251 -0
  50. package/src/libs/highlighter/languages/javascript.ts +213 -0
  51. package/src/libs/highlighter/languages/php.ts +433 -0
  52. package/src/libs/highlighter/languages/python.ts +308 -0
  53. package/src/libs/highlighter/languages/ruby.ts +360 -0
  54. package/src/libs/highlighter/languages/sql.ts +125 -0
  55. package/src/libs/highlighter/languages/xml.ts +68 -0
  56. package/src/libs/highlighter/types.ts +44 -0
  57. package/src/render.ts +231 -0
  58. package/src/types.ts +140 -0
package/dist/index.cjs CHANGED
@@ -44,14 +44,14 @@ var __export = (target, all) => {
44
44
  var exports_src = {};
45
45
  __export(exports_src, {
46
46
  renderToHtml: () => renderToHtml,
47
- createSettings: () => import_ast4.createSettings,
48
- DEFAULT_SETTINGS: () => import_ast4.DEFAULT_SETTINGS,
47
+ createSettings: () => import_ast5.createSettings,
48
+ DEFAULT_SETTINGS: () => import_ast5.DEFAULT_SETTINGS,
49
49
  DEFAULT_EMBED_ALLOWLIST: () => DEFAULT_EMBED_ALLOWLIST
50
50
  });
51
51
  module.exports = __toCommonJS(exports_src);
52
52
 
53
53
  // packages/render/src/render.ts
54
- var import_ast3 = require("@wdprlib/ast");
54
+ var import_ast4 = require("@wdprlib/ast");
55
55
 
56
56
  // packages/render/src/context.ts
57
57
  var import_ast = require("@wdprlib/ast");
@@ -4821,392 +4821,22 @@ function formatDate(date, format) {
4821
4821
  return format.replace(/%Y/g, String(date.getFullYear())).replace(/%m/g, String(date.getMonth() + 1).padStart(2, "0")).replace(/%d/g, String(date.getDate()).padStart(2, "0")).replace(/%H/g, String(date.getHours()).padStart(2, "0")).replace(/%M/g, String(date.getMinutes()).padStart(2, "0")).replace(/%S/g, String(date.getSeconds()).padStart(2, "0"));
4822
4822
  }
4823
4823
 
4824
- // packages/render/src/utils/expr-eval.ts
4825
- var FALSE_VALUES = new Set(["false", "null", "", "0"]);
4826
- function isTruthy(value) {
4827
- return !FALSE_VALUES.has(value.toLowerCase().trim());
4828
- }
4829
- var MAX_EXPRESSION_LENGTH = 256;
4830
- function isTruthyNum(n) {
4831
- return n !== 0 && !Number.isNaN(n);
4832
- }
4833
- function evaluateExpression(expr) {
4834
- try {
4835
- if (expr.length > MAX_EXPRESSION_LENGTH) {
4836
- return { success: false, error: "expression too long" };
4837
- }
4838
- if (expr.trim() === "") {
4839
- return { success: false, error: "empty expression" };
4840
- }
4841
- const tokens = tokenize2(expr);
4842
- if (tokens.length <= 1) {
4843
- return { success: false, error: "empty expression" };
4844
- }
4845
- const parser = new ExprParser(tokens);
4846
- const result = parser.parse();
4847
- if (!Number.isFinite(result)) {
4848
- return { success: false, error: "division by zero" };
4849
- }
4850
- return { success: true, value: result };
4851
- } catch (e) {
4852
- const msg = e instanceof Error ? e.message : "unknown error";
4853
- return { success: false, error: msg };
4854
- }
4855
- }
4856
- function tokenize2(expr) {
4857
- const tokens = [];
4858
- let i = 0;
4859
- while (i < expr.length) {
4860
- const ch = expr[i];
4861
- if (/\s/.test(ch)) {
4862
- i++;
4863
- continue;
4864
- }
4865
- if (/\d/.test(ch) || ch === "." && /\d/.test(expr[i + 1] ?? "")) {
4866
- let numStr = "";
4867
- let hasDot = false;
4868
- while (i < expr.length) {
4869
- const c = expr[i];
4870
- if (c === ".") {
4871
- if (hasDot)
4872
- break;
4873
- hasDot = true;
4874
- } else if (!/\d/.test(c)) {
4875
- break;
4876
- }
4877
- numStr += c;
4878
- i++;
4879
- }
4880
- const num = parseFloat(numStr);
4881
- if (!Number.isFinite(num)) {
4882
- throw new Error("Invalid number");
4883
- }
4884
- tokens.push({ kind: "NUMBER", value: num });
4885
- continue;
4886
- }
4887
- if (/[a-zA-Z_]/.test(ch)) {
4888
- let id = "";
4889
- while (i < expr.length) {
4890
- const c = expr[i];
4891
- if (!/[a-zA-Z0-9_]/.test(c))
4892
- break;
4893
- id += c;
4894
- i++;
4895
- }
4896
- tokens.push({ kind: "IDENTIFIER", value: id.toLowerCase() });
4897
- continue;
4898
- }
4899
- if (ch === "<" && expr[i + 1] === "=") {
4900
- tokens.push({ kind: "LE", value: "<=" });
4901
- i += 2;
4902
- continue;
4903
- }
4904
- if (ch === ">" && expr[i + 1] === "=") {
4905
- tokens.push({ kind: "GE", value: ">=" });
4906
- i += 2;
4907
- continue;
4908
- }
4909
- if (ch === "!" && expr[i + 1] === "=") {
4910
- tokens.push({ kind: "NE", value: "!=" });
4911
- i += 2;
4912
- continue;
4913
- }
4914
- if (ch === "<" && expr[i + 1] === ">") {
4915
- tokens.push({ kind: "NE", value: "<>" });
4916
- i += 2;
4917
- continue;
4918
- }
4919
- switch (ch) {
4920
- case "+":
4921
- tokens.push({ kind: "PLUS", value: "+" });
4922
- break;
4923
- case "-":
4924
- tokens.push({ kind: "MINUS", value: "-" });
4925
- break;
4926
- case "*":
4927
- tokens.push({ kind: "STAR", value: "*" });
4928
- break;
4929
- case "/":
4930
- tokens.push({ kind: "SLASH", value: "/" });
4931
- break;
4932
- case "%":
4933
- tokens.push({ kind: "PERCENT", value: "%" });
4934
- break;
4935
- case "^":
4936
- tokens.push({ kind: "CARET", value: "^" });
4937
- break;
4938
- case "(":
4939
- tokens.push({ kind: "LPAREN", value: "(" });
4940
- break;
4941
- case ")":
4942
- tokens.push({ kind: "RPAREN", value: ")" });
4943
- break;
4944
- case ",":
4945
- tokens.push({ kind: "COMMA", value: "," });
4946
- break;
4947
- case "<":
4948
- tokens.push({ kind: "LT", value: "<" });
4949
- break;
4950
- case ">":
4951
- tokens.push({ kind: "GT", value: ">" });
4952
- break;
4953
- case "=":
4954
- tokens.push({ kind: "EQ", value: "=" });
4955
- break;
4956
- default:
4957
- throw new Error(`Unknown character: ${ch}`);
4958
- }
4959
- i++;
4960
- }
4961
- tokens.push({ kind: "EOF", value: "" });
4962
- return tokens;
4963
- }
4964
-
4965
- class ExprParser {
4966
- tokens;
4967
- pos = 0;
4968
- constructor(tokens) {
4969
- this.tokens = tokens;
4970
- }
4971
- parse() {
4972
- const result = this.parseOr();
4973
- if (this.current().kind !== "EOF") {
4974
- throw new Error("too many values in the stack");
4975
- }
4976
- return result;
4977
- }
4978
- current() {
4979
- return this.tokens[this.pos] ?? { kind: "EOF", value: "" };
4980
- }
4981
- advance() {
4982
- const token = this.current();
4983
- this.pos++;
4984
- return token;
4985
- }
4986
- parseOr() {
4987
- let left = this.parseAnd();
4988
- while (this.current().kind === "IDENTIFIER" && this.current().value === "or") {
4989
- this.advance();
4990
- const right = this.parseAnd();
4991
- left = isTruthyNum(left) || isTruthyNum(right) ? 1 : 0;
4992
- }
4993
- return left;
4994
- }
4995
- parseAnd() {
4996
- let left = this.parseNot();
4997
- while (this.current().kind === "IDENTIFIER" && this.current().value === "and") {
4998
- this.advance();
4999
- const right = this.parseNot();
5000
- left = isTruthyNum(left) && isTruthyNum(right) ? 1 : 0;
5001
- }
5002
- return left;
5003
- }
5004
- parseNot() {
5005
- if (this.current().kind === "IDENTIFIER" && this.current().value === "not") {
5006
- this.advance();
5007
- const value = this.parseNot();
5008
- return isTruthyNum(value) ? 0 : 1;
5009
- }
5010
- return this.parseComparison();
5011
- }
5012
- parseComparison() {
5013
- let left = this.parseAddition();
5014
- const kind = this.current().kind;
5015
- if (kind === "LT" || kind === "GT" || kind === "LE" || kind === "GE" || kind === "EQ" || kind === "NE") {
5016
- this.advance();
5017
- const right = this.parseAddition();
5018
- switch (kind) {
5019
- case "LT":
5020
- return left < right ? 1 : 0;
5021
- case "GT":
5022
- return left > right ? 1 : 0;
5023
- case "LE":
5024
- return left <= right ? 1 : 0;
5025
- case "GE":
5026
- return left >= right ? 1 : 0;
5027
- case "EQ":
5028
- return left === right ? 1 : 0;
5029
- case "NE":
5030
- return left !== right ? 1 : 0;
5031
- }
5032
- }
5033
- return left;
5034
- }
5035
- parseAddition() {
5036
- let left = this.parseMultiplication();
5037
- while (true) {
5038
- const kind = this.current().kind;
5039
- if (kind === "PLUS") {
5040
- this.advance();
5041
- left = left + this.parseMultiplication();
5042
- } else if (kind === "MINUS") {
5043
- this.advance();
5044
- left = left - this.parseMultiplication();
5045
- } else {
5046
- break;
5047
- }
5048
- }
5049
- return left;
5050
- }
5051
- parseMultiplication() {
5052
- let left = this.parsePower();
5053
- while (true) {
5054
- const kind = this.current().kind;
5055
- if (kind === "STAR") {
5056
- this.advance();
5057
- left = left * this.parsePower();
5058
- } else if (kind === "SLASH") {
5059
- this.advance();
5060
- left = left / this.parsePower();
5061
- } else if (kind === "PERCENT") {
5062
- this.advance();
5063
- left = left % this.parsePower();
5064
- } else {
5065
- break;
5066
- }
5067
- }
5068
- return left;
5069
- }
5070
- parsePower() {
5071
- const left = this.parseUnary();
5072
- if (this.current().kind === "CARET") {
5073
- this.advance();
5074
- const right = this.parsePower();
5075
- return Math.pow(left, right);
5076
- }
5077
- return left;
5078
- }
5079
- parseUnary() {
5080
- const kind = this.current().kind;
5081
- if (kind === "MINUS") {
5082
- this.advance();
5083
- return -this.parseUnary();
5084
- }
5085
- if (kind === "PLUS") {
5086
- this.advance();
5087
- return +this.parseUnary();
5088
- }
5089
- return this.parsePrimary();
5090
- }
5091
- parsePrimary() {
5092
- const token = this.current();
5093
- if (token.kind === "NUMBER") {
5094
- this.advance();
5095
- return token.value;
5096
- }
5097
- if (token.kind === "LPAREN") {
5098
- this.advance();
5099
- const value = this.parseOr();
5100
- if (this.current().kind !== "RPAREN") {
5101
- throw new Error("Expected )");
5102
- }
5103
- this.advance();
5104
- return value;
5105
- }
5106
- if (token.kind === "IDENTIFIER") {
5107
- const name = token.value;
5108
- this.advance();
5109
- if (this.current().kind === "LPAREN") {
5110
- return this.parseFunctionCall(name);
5111
- }
5112
- throw new Error(`undefined constant "${name}"`);
5113
- }
5114
- throw new Error("Expected expression");
5115
- }
5116
- parseFunctionCall(name) {
5117
- if (this.current().kind !== "LPAREN") {
5118
- throw new Error("Expected (");
5119
- }
5120
- this.advance();
5121
- const args = [];
5122
- if (this.current().kind !== "RPAREN") {
5123
- args.push(this.parseOr());
5124
- while (this.current().kind === "COMMA") {
5125
- this.advance();
5126
- args.push(this.parseOr());
5127
- }
5128
- }
5129
- if (this.current().kind !== "RPAREN") {
5130
- throw new Error("Expected )");
5131
- }
5132
- this.advance();
5133
- return this.callFunction(name, args);
5134
- }
5135
- callFunction(name, args) {
5136
- switch (name) {
5137
- case "abs":
5138
- this.checkArgs(name, args, 1);
5139
- return Math.abs(args[0]);
5140
- case "min":
5141
- this.checkArgsMin(name, args, 1);
5142
- return Math.min(...args);
5143
- case "max":
5144
- this.checkArgsMin(name, args, 1);
5145
- return Math.max(...args);
5146
- case "floor":
5147
- this.checkArgs(name, args, 1);
5148
- return Math.floor(args[0]);
5149
- case "ceil":
5150
- this.checkArgs(name, args, 1);
5151
- return Math.ceil(args[0]);
5152
- case "round":
5153
- this.checkArgs(name, args, 1);
5154
- return Math.round(args[0]);
5155
- case "sqrt":
5156
- this.checkArgs(name, args, 1);
5157
- return Math.sqrt(args[0]);
5158
- case "sin":
5159
- this.checkArgs(name, args, 1);
5160
- return Math.sin(args[0]);
5161
- case "cos":
5162
- this.checkArgs(name, args, 1);
5163
- return Math.cos(args[0]);
5164
- case "tan":
5165
- this.checkArgs(name, args, 1);
5166
- return Math.tan(args[0]);
5167
- case "ln":
5168
- this.checkArgs(name, args, 1);
5169
- return Math.log(args[0]);
5170
- case "log":
5171
- this.checkArgs(name, args, 1);
5172
- return Math.log10(args[0]);
5173
- case "exp":
5174
- this.checkArgs(name, args, 1);
5175
- return Math.exp(args[0]);
5176
- case "pow":
5177
- this.checkArgs(name, args, 2);
5178
- return Math.pow(args[0], args[1]);
5179
- default:
5180
- throw new Error(`undefined function "${name}"`);
5181
- }
5182
- }
5183
- checkArgs(name, args, expected) {
5184
- if (args.length !== expected) {
5185
- throw new Error(`${name}() expects ${expected} argument(s), got ${args.length}`);
5186
- }
5187
- }
5188
- checkArgsMin(name, args, min) {
5189
- if (args.length < min) {
5190
- throw new Error(`${name}() expects at least ${min} argument(s), got ${args.length}`);
5191
- }
5192
- }
5193
- }
5194
-
5195
4824
  // packages/render/src/elements/expr.ts
4825
+ var import_ast3 = require("@wdprlib/ast");
5196
4826
  function renderExpr(ctx, data) {
5197
- const result = evaluateExpression(data.expression);
4827
+ const result = import_ast3.evaluateExpression(data.expression);
5198
4828
  if (result.success) {
5199
- ctx.pushEscaped(formatNumber(result.value));
4829
+ ctx.pushEscaped(import_ast3.formatExprValue(result.value));
5200
4830
  } else if (result.error !== "empty expression") {
5201
4831
  ctx.pushEscaped(`run-time error: ${result.error}`);
5202
4832
  }
5203
4833
  }
5204
4834
  function renderIf(ctx, data) {
5205
- const elements = isTruthy(data.condition) ? data.then : data.else;
4835
+ const elements = import_ast3.isTruthy(data.condition) ? data.then : data.else;
5206
4836
  renderBranchElements(ctx, elements);
5207
4837
  }
5208
4838
  function renderIfExpr(ctx, data) {
5209
- const result = evaluateExpression(data.expression);
4839
+ const result = import_ast3.evaluateExpression(data.expression);
5210
4840
  if (!result.success) {
5211
4841
  ctx.pushEscaped(`run-time error: ${result.error}`);
5212
4842
  return;
@@ -5226,12 +4856,6 @@ function renderBranchElements(ctx, elements) {
5226
4856
  }
5227
4857
  renderElements(ctx, elements.slice(0, lastIdx + 1));
5228
4858
  }
5229
- function formatNumber(n) {
5230
- if (Number.isInteger(n)) {
5231
- return String(n);
5232
- }
5233
- return n.toFixed(6).replace(/\.?0+$/, "");
5234
- }
5235
4859
 
5236
4860
  // packages/render/src/render.ts
5237
4861
  function renderToHtml(tree, options = {}) {
@@ -5239,8 +4863,8 @@ function renderToHtml(tree, options = {}) {
5239
4863
  renderElements(ctx, tree.elements);
5240
4864
  if (ctx.settings.allowStyleElements && tree.styles?.length) {
5241
4865
  for (const style of tree.styles) {
5242
- if (style.startsWith(import_ast3.STYLE_SLOT_PREFIX)) {
5243
- const slotId = parseInt(style.slice(import_ast3.STYLE_SLOT_PREFIX.length), 10);
4866
+ if (style.startsWith(import_ast4.STYLE_SLOT_PREFIX)) {
4867
+ const slotId = parseInt(style.slice(import_ast4.STYLE_SLOT_PREFIX.length), 10);
5244
4868
  for (const css of ctx.getStyleSlotContents(slotId)) {
5245
4869
  ctx.push(`<style>${escapeStyleContent(css)}</style>`);
5246
4870
  }
@@ -5397,4 +5021,4 @@ function renderElement(ctx, element) {
5397
5021
  }
5398
5022
 
5399
5023
  // packages/render/src/index.ts
5400
- var import_ast4 = require("@wdprlib/ast");
5024
+ var import_ast5 = require("@wdprlib/ast");