xmlui 0.9.21 → 0.9.25

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 (102) hide show
  1. package/dist/apiInterceptorWorker-CFF3bC6o.mjs +818 -0
  2. package/dist/{index-B3CWFAxa.mjs → index-DtxDGaqF.mjs} +11942 -3291
  3. package/dist/index.css +1301 -564
  4. package/dist/language-server-web-worker.mjs +1 -1
  5. package/dist/language-server.mjs +1 -1
  6. package/dist/lint-CYAUfk0_.mjs +168 -0
  7. package/dist/metadata-utils-CCIMqe69.mjs +466 -0
  8. package/dist/scripts/package.json +252 -0
  9. package/dist/scripts/src/components/App/AppLayoutContext.js +0 -1
  10. package/dist/scripts/src/components/App/AppNative.js +21 -9
  11. package/dist/scripts/src/components/AppHeader/AppHeader.js +1 -1
  12. package/dist/scripts/src/components/AutoComplete/AutoComplete.js +5 -2
  13. package/dist/scripts/src/components/AutoComplete/AutoCompleteNative.js +13 -10
  14. package/dist/scripts/src/components/Bookmark/BookmarkNative.js +5 -1
  15. package/dist/scripts/src/components/CodeBlock/CodeBlock.js +31 -0
  16. package/dist/scripts/src/components/CodeBlock/CodeBlockNative.js +82 -0
  17. package/dist/scripts/src/components/ComponentProvider.js +5 -0
  18. package/dist/scripts/src/components/DatePicker/DatePickerNative.js +1 -0
  19. package/dist/scripts/src/components/Form/FormContext.js +5 -4
  20. package/dist/scripts/src/components/Form/FormNative.js +41 -43
  21. package/dist/scripts/src/components/Form/formActions.js +1 -1
  22. package/dist/scripts/src/components/FormItem/FormItem.js +6 -3
  23. package/dist/scripts/src/components/FormItem/FormItemNative.js +56 -15
  24. package/dist/scripts/src/components/FormItem/ItemWithLabel.js +1 -1
  25. package/dist/scripts/src/components/Heading/Heading.js +13 -0
  26. package/dist/scripts/src/components/Heading/HeadingNative.js +1 -1
  27. package/dist/scripts/src/components/HtmlTags/HtmlTags.js +7 -3
  28. package/dist/scripts/src/components/Icon/DarkToLightIcon.js +10 -0
  29. package/dist/scripts/src/components/Icon/LightToDark.js +10 -0
  30. package/dist/scripts/src/components/IconProvider.js +4 -0
  31. package/dist/scripts/src/components/Image/ImageNative.js +1 -1
  32. package/dist/scripts/src/components/Items/ItemsNative.js +8 -6
  33. package/dist/scripts/src/components/Link/Link.js +5 -5
  34. package/dist/scripts/src/components/List/ListNative.js +1 -1
  35. package/dist/scripts/src/components/Markdown/Markdown.js +52 -16
  36. package/dist/scripts/src/components/Markdown/MarkdownNative.js +34 -73
  37. package/dist/scripts/src/components/Markdown/highlight-code.js +160 -0
  38. package/dist/scripts/src/components/Markdown/parse-binding-expr.js +60 -0
  39. package/dist/scripts/src/components/Markdown/utils.js +282 -0
  40. package/dist/scripts/src/components/ModalDialog/ConfirmationModalContextProvider.js +116 -0
  41. package/dist/scripts/src/components/ModalDialog/Dialog.js +20 -0
  42. package/dist/scripts/src/components/NavGroup/NavGroupNative.js +4 -5
  43. package/dist/scripts/src/components/NestedApp/NestedApp.js +61 -0
  44. package/dist/scripts/src/components/NestedApp/NestedAppNative.js +125 -0
  45. package/dist/scripts/src/components/NestedApp/Tooltip.js +46 -0
  46. package/dist/scripts/src/components/NumberBox/NumberBox.js +4 -1
  47. package/dist/scripts/src/components/NumberBox/NumberBoxNative.js +2 -2
  48. package/dist/scripts/src/components/Option/Option.js +3 -2
  49. package/dist/scripts/src/components/Select/Select.js +5 -3
  50. package/dist/scripts/src/components/Select/SelectNative.js +53 -40
  51. package/dist/scripts/src/components/SelectionStore/SelectionStore.js +1 -1
  52. package/dist/scripts/src/components/Spinner/Spinner.js +0 -1
  53. package/dist/scripts/src/components/TableOfContents/TableOfContents.js +1 -0
  54. package/dist/scripts/src/components/Text/Text.js +12 -1
  55. package/dist/scripts/src/components/Text/TextNative.js +5 -1
  56. package/dist/scripts/src/components/TextBox/TextBox.js +6 -1
  57. package/dist/scripts/src/components/TextBox/TextBoxNative.js +2 -2
  58. package/dist/scripts/src/components/Theme/ThemeNative.js +7 -3
  59. package/dist/scripts/src/components/ToneChangerButton/ToneChangerButton.js +1 -3
  60. package/dist/scripts/src/components-core/RestApiProxy.js +10 -7
  61. package/dist/scripts/src/components-core/TableOfContentsContext.js +1 -1
  62. package/dist/scripts/src/components-core/appContext/date-functions.js +23 -0
  63. package/dist/scripts/src/components-core/appContext/math-function.js +27 -0
  64. package/dist/scripts/src/components-core/appContext/misc-utils.js +13 -0
  65. package/dist/scripts/src/components-core/interception/ApiInterceptor.js +199 -0
  66. package/dist/scripts/src/components-core/interception/ApiInterceptorProvider.js +94 -0
  67. package/dist/scripts/src/components-core/interception/Backend.js +128 -0
  68. package/dist/scripts/src/components-core/interception/Errors.js +129 -0
  69. package/dist/scripts/src/components-core/interception/InMemoryDb.js +41 -0
  70. package/dist/scripts/src/components-core/interception/IndexedDb.js +207 -0
  71. package/dist/scripts/src/components-core/interception/ReadonlyCollection.js +145 -0
  72. package/dist/scripts/src/components-core/interception/abstractions.js +2 -0
  73. package/dist/scripts/src/components-core/interception/apiInterceptorWorker.js +46 -0
  74. package/dist/scripts/src/components-core/interception/useApiInterceptorContext.js +9 -0
  75. package/dist/scripts/src/components-core/rendering/AppContent.js +336 -0
  76. package/dist/scripts/src/components-core/rendering/AppRoot.js +84 -0
  77. package/dist/scripts/src/components-core/rendering/AppWrapper.js +49 -0
  78. package/dist/scripts/src/components-core/rendering/ComponentAdapter.js +17 -7
  79. package/dist/scripts/src/components-core/rendering/Container.js +2 -1
  80. package/dist/scripts/src/components-core/theming/ThemeProvider.js +2 -7
  81. package/dist/scripts/src/components-core/theming/themes/root.js +1 -0
  82. package/dist/scripts/src/components-core/utils/date-utils.js +78 -0
  83. package/dist/scripts/src/components-core/utils/hooks.js +26 -0
  84. package/dist/scripts/src/components-core/utils/misc.js +1 -1
  85. package/dist/scripts/src/components-core/utils/request-params.js +70 -0
  86. package/dist/scripts/src/logging/LoggerContext.js +22 -0
  87. package/dist/scripts/src/logging/LoggerInitializer.js +14 -0
  88. package/dist/scripts/src/logging/LoggerService.js +60 -0
  89. package/dist/scripts/src/parsers/xmlui-parser/transform.js +7 -0
  90. package/dist/{server-common-DW5h7Q34.mjs → server-common-9TiLMTJj.mjs} +106 -98
  91. package/dist/style.css +3314 -2823
  92. package/dist/{lint-EcgF-9Wr.mjs → transform-DC0Gy6qw.mjs} +1246 -540
  93. package/dist/xmlui-metadata.mjs +2850 -2665
  94. package/dist/xmlui-metadata.umd.js +2850 -2665
  95. package/dist/xmlui-parser.d.ts +49 -4
  96. package/dist/xmlui-parser.mjs +49 -48
  97. package/dist/xmlui-standalone.umd.js +34674 -31457
  98. package/dist/xmlui.d.ts +3 -1
  99. package/dist/xmlui.mjs +10 -10
  100. package/package.json +3 -1
  101. package/dist/apiInterceptorWorker-7aKQ2rBj.mjs +0 -8447
  102. package/dist/parser-CBXS8ft2.mjs +0 -1196
@@ -10,12 +10,19 @@ const ComponentDefs_1 = require("../../abstractions/ComponentDefs");
10
10
  const renderers_1 = require("../../components-core/renderers");
11
11
  const themeVars_1 = require("../../components-core/theming/themeVars");
12
12
  const MarkdownNative_1 = require("./MarkdownNative");
13
+ const react_1 = require("react");
14
+ const parse_binding_expr_1 = require("./parse-binding-expr");
15
+ const utils_1 = require("./utils");
13
16
  const COMP = "Markdown";
14
17
  exports.MarkdownMd = (0, ComponentDefs_1.createMetadata)({
15
18
  description: `\`${COMP}\` displays plain text styled using markdown syntax.`,
16
19
  themeVars: (0, themeVars_1.parseScssVar)(Markdown_module_scss_1.default.themeVars),
17
20
  props: {
18
21
  content: (0, ComponentDefs_1.d)("This property sets the markdown content to display."),
22
+ codeHighlighter: {
23
+ description: "This property sets the code highlighter to use.",
24
+ isInternal: true,
25
+ },
19
26
  removeIndents: {
20
27
  description: "This boolean property specifies whether leading indents should be " +
21
28
  "removed from the markdown content. If set to `true`, the shortest " +
@@ -26,26 +33,33 @@ exports.MarkdownMd = (0, ComponentDefs_1.createMetadata)({
26
33
  },
27
34
  },
28
35
  defaultThemeVars: {
29
- "backgroundColor-Admonition": "$color-warn-300",
30
- "borderRadius-Admonition": "$space-4",
31
- "iconSize-Admonition": "$space-6",
32
- "padding-Admonition": "$space-4",
33
- "marginBottom-Admonition": "$space-4",
34
- "marginLeft-Admonition-content": "$space-2",
35
- "backgroundColor-Blockquote": "$color-warn-200",
36
+ "backgroundColor-Admonition": "$color-primary-100",
37
+ "borderRadius-Admonition": "$space-2",
38
+ "border-Admonition": "1px solid $color-primary-300",
39
+ "iconSize-Admonition": "$space-5",
40
+ "paddingLeft-Admonition": "$space-2",
41
+ "paddingRight-Admonition": "$space-6",
42
+ "paddingTop-Admonition": "$space-3",
43
+ "paddingBottom-Admonition": "$space-2",
44
+ "marginLeft-Admonition-content": "$space-1_5",
45
+ "marginTop-Admonition": "$space-7",
46
+ "marginBottom-Admonition": "$space-7",
47
+ "marginTop-Blockquote": "$space-7",
48
+ "marginBottom-Blockquote": "$space-7",
49
+ "paddingHorizontal-Blockquote": "$space-6",
50
+ "paddingTop-Blockquote": "$space-3",
51
+ "paddingBottom-Blockquote": "$space-2_5",
52
+ "backgroundColor-Blockquote": "$color-surface-100",
36
53
  "accentWidth-Blockquote": "3px",
37
54
  "accentColor-Blockquote": "$color-surface-500",
38
- "padding-Blockquote": "$space-2",
39
- "marginBottom-Blockquote": "$space-4",
40
- "marginBottom-Text-codefence": "$space-2",
41
- "marginBottom-Text-markdown": "$space-2",
42
- "marginTop-HtmlLi": "$space-2",
43
- "marginBottom-HtmlLi": "$space-2",
55
+ "marginTop-HtmlLi": "$space-2_5",
56
+ "marginBottom-HtmlLi": "$space-2_5",
44
57
  light: {
45
58
  // --- No light-specific theme vars
46
59
  },
47
60
  dark: {
48
- // --- No dark-specific theme vars
61
+ "backgroundColor-Blockquote": "$color-surface-50",
62
+ "backgroundColor-Admonition": "$color-primary-200",
49
63
  },
50
64
  },
51
65
  });
@@ -56,7 +70,7 @@ exports.markdownComponentRenderer = (0, renderers_1.createComponentRenderer)(COM
56
70
  if (!renderedChildren) {
57
71
  renderedChildren = extractValue.asString(node.props.content);
58
72
  }
59
- // 2. "data" property fallback)
73
+ // 2. "data" property fallback
60
74
  if (!renderedChildren) {
61
75
  renderedChildren = extractValue.asString(node.props.data);
62
76
  }
@@ -69,7 +83,29 @@ exports.markdownComponentRenderer = (0, renderers_1.createComponentRenderer)(COM
69
83
  }
70
84
  });
71
85
  }
72
- return ((0, jsx_runtime_1.jsx)(MarkdownNative_1.Markdown, { style: layoutCss, removeIndents: extractValue.asOptionalBoolean(node.props.removeIndents, true), extractValue: extractValue, children: renderedChildren }));
86
+ return ((0, jsx_runtime_1.jsx)(TransformedMarkdown, { style: layoutCss, removeIndents: extractValue.asOptionalBoolean(node.props.removeIndents, true), codeHighlighter: extractValue(node.props.codeHighlighter), extractValue: extractValue, children: renderedChildren }));
73
87
  });
88
+ const TransformedMarkdown = ({ children, removeIndents, style, extractValue, codeHighlighter, }) => {
89
+ const markdownContent = (0, react_1.useMemo)(() => {
90
+ if (typeof children !== "string") {
91
+ return null;
92
+ }
93
+ // --- Resolve binding expression values
94
+ // --- Resolve xmlui playground definitions
95
+ let resolvedMd = children;
96
+ while (true) {
97
+ const nextPlayground = (0, utils_1.observePlaygroundPattern)(resolvedMd);
98
+ if (!nextPlayground)
99
+ break;
100
+ resolvedMd =
101
+ resolvedMd.slice(0, nextPlayground[0]) +
102
+ (0, utils_1.convertPlaygroundPatternToMarkdown)(nextPlayground[2]) +
103
+ resolvedMd.slice(nextPlayground[1]);
104
+ }
105
+ resolvedMd = (0, parse_binding_expr_1.parseBindingExpression)(resolvedMd, extractValue);
106
+ return resolvedMd;
107
+ }, [children, extractValue]);
108
+ return ((0, jsx_runtime_1.jsx)(MarkdownNative_1.Markdown, { removeIndents: removeIndents, codeHighlighter: codeHighlighter, style: style, children: markdownContent }));
109
+ };
74
110
  var MarkdownNative_2 = require("./MarkdownNative");
75
111
  Object.defineProperty(exports, "Markdown", { enumerable: true, get: function () { return MarkdownNative_2.Markdown; } });
@@ -18,23 +18,38 @@ exports.Markdown = void 0;
18
18
  const jsx_runtime_1 = require("react/jsx-runtime");
19
19
  const react_1 = require("react");
20
20
  const react_2 = __importDefault(require("react"));
21
- const react_markdown_1 = __importDefault(require("react-markdown"));
21
+ const react_markdown_1 = require("react-markdown");
22
22
  const remark_gfm_1 = __importDefault(require("remark-gfm"));
23
23
  const rehype_raw_1 = __importDefault(require("rehype-raw"));
24
- const unist_util_visit_1 = require("unist-util-visit");
25
24
  const Markdown_module_scss_1 = __importDefault(require("./Markdown.module.scss"));
26
25
  const HtmlTags_module_scss_1 = __importDefault(require("../HtmlTags/HtmlTags.module.scss"));
27
26
  const HeadingNative_1 = require("../Heading/HeadingNative");
28
27
  const TextNative_1 = require("../Text/TextNative");
29
28
  const LinkNative_1 = require("../Link/LinkNative");
30
29
  const Toggle_1 = require("../Toggle/Toggle");
31
- const ScriptingSourceTree_1 = require("../../abstractions/scripting/ScriptingSourceTree");
32
- exports.Markdown = (0, react_1.memo)(function Markdown({ extractValue, removeIndents = true, children, style, }) {
30
+ const NestedAppNative_1 = require("../NestedApp/NestedAppNative");
31
+ const highlight_code_1 = require("./highlight-code");
32
+ const ThemeContext_1 = require("../../components-core/theming/ThemeContext");
33
+ const CodeBlockNative_1 = require("../CodeBlock/CodeBlockNative");
34
+ function PreTagComponent({ id, children, codeHighlighter }) {
35
+ // TEMP: After ironing out theming for syntax highlighting, this should be removed
36
+ const { activeThemeTone } = (0, ThemeContext_1.useTheme)();
37
+ const defaultCodefence = ((0, jsx_runtime_1.jsx)(CodeBlockNative_1.CodeBlock, { children: (0, jsx_runtime_1.jsx)(TextNative_1.Text, { uid: id, variant: "codefence", children: children }) }));
38
+ if (!codeHighlighter) {
39
+ return defaultCodefence;
40
+ }
41
+ const highlighterResult = (0, highlight_code_1.parseMetaAndHighlightCode)(children, codeHighlighter, activeThemeTone);
42
+ if (!highlighterResult) {
43
+ return defaultCodefence;
44
+ }
45
+ return ((0, jsx_runtime_1.jsx)(CodeBlockNative_1.CodeBlock, { meta: highlighterResult.meta, textToCopy: highlighterResult.codeStr, children: (0, jsx_runtime_1.jsx)(TextNative_1.Text, { uid: id, variant: "codefence", syntaxHighlightClasses: highlighterResult.classNames, dangerouslySetInnerHTML: { __html: highlighterResult.cleanedHtmlStr } }) }));
46
+ }
47
+ exports.Markdown = (0, react_1.memo)(function Markdown({ removeIndents = true, children, style, codeHighlighter, }) {
33
48
  if (typeof children !== "string") {
34
49
  return null;
35
50
  }
36
51
  children = removeIndents ? removeTextIndents(children) : children;
37
- return ((0, jsx_runtime_1.jsx)("div", { className: Markdown_module_scss_1.default.markdownContent, style: Object.assign({}, style), children: (0, jsx_runtime_1.jsx)(react_markdown_1.default, { remarkPlugins: [remark_gfm_1.default, [bindingExpression, { extractValue }]], rehypePlugins: [rehype_raw_1.default], components: {
52
+ return ((0, jsx_runtime_1.jsx)("div", { className: Markdown_module_scss_1.default.markdownContent, style: Object.assign({}, style), children: (0, jsx_runtime_1.jsx)(react_markdown_1.MarkdownHooks, { remarkPlugins: [remark_gfm_1.default, CodeBlockNative_1.markdownCodeBlockParser], rehypePlugins: [rehype_raw_1.default], components: {
38
53
  details(_a) {
39
54
  var { children, node } = _a, props = __rest(_a, ["children", "node"]);
40
55
  return ((0, jsx_runtime_1.jsx)("details", Object.assign({ className: HtmlTags_module_scss_1.default.htmlDetails }, props, { children: children })));
@@ -48,7 +63,7 @@ exports.Markdown = (0, react_1.memo)(function Markdown({ extractValue, removeInd
48
63
  const src = props === null || props === void 0 ? void 0 : props.src;
49
64
  const popOut = props === null || props === void 0 ? void 0 : props["data-popout"];
50
65
  if (popOut) {
51
- return ((0, jsx_runtime_1.jsx)("a", { href: src, target: "_blank", children: (0, jsx_runtime_1.jsx)("img", Object.assign({ className: HtmlTags_module_scss_1.default.htmlImage }, props, { children: children })) }));
66
+ return ((0, jsx_runtime_1.jsx)("a", { href: src, target: "_blank", rel: "noreferrer", children: (0, jsx_runtime_1.jsx)("img", Object.assign({ className: HtmlTags_module_scss_1.default.htmlImage }, props, { children: children })) }));
52
67
  }
53
68
  else {
54
69
  return ((0, jsx_runtime_1.jsx)("img", Object.assign({ className: HtmlTags_module_scss_1.default.htmlImage }, props, { children: children })));
@@ -79,7 +94,7 @@ exports.Markdown = (0, react_1.memo)(function Markdown({ extractValue, removeInd
79
94
  return ((0, jsx_runtime_1.jsx)(TextNative_1.Text, { uid: id, variant: "code", children: children }));
80
95
  },
81
96
  pre({ id, children }) {
82
- return ((0, jsx_runtime_1.jsx)(TextNative_1.Text, { uid: id, variant: "codefence", children: children }));
97
+ return (0, jsx_runtime_1.jsx)(PreTagComponent, { id: id, codeHighlighter: codeHighlighter, children: children });
83
98
  },
84
99
  strong({ id, children }) {
85
100
  return ((0, jsx_runtime_1.jsx)(TextNative_1.Text, { uid: id, variant: "strong", children: children }));
@@ -110,8 +125,7 @@ exports.Markdown = (0, react_1.memo)(function Markdown({ extractValue, removeInd
110
125
  },
111
126
  a(_a) {
112
127
  var { children, href } = _a, props = __rest(_a, ["children", "href"]);
113
- const allowedProps = ["style", "disabled", "active", "icon", "onClick"];
114
- return ((0, jsx_runtime_1.jsx)(LinkNative_1.LocalLink, Object.assign({ to: href }, allowedProps, { children: children })));
128
+ return ((0, jsx_runtime_1.jsx)(LinkNative_1.LocalLink, Object.assign({ to: href }, props, { children: children })));
115
129
  },
116
130
  // TODO: somehow get the label from the containing li element
117
131
  input({ disabled, checked }) {
@@ -138,6 +152,17 @@ exports.Markdown = (0, react_1.memo)(function Markdown({ extractValue, removeInd
138
152
  tfoot({ children }) {
139
153
  return (0, jsx_runtime_1.jsx)("tfoot", { className: HtmlTags_module_scss_1.default.htmlTfoot, children: children });
140
154
  },
155
+ samp(_a) {
156
+ var props = __rest(_a, []);
157
+ const nestedProps = props;
158
+ const dataContentBase64 = props === null || props === void 0 ? void 0 : props["data-pg-content"];
159
+ if (dataContentBase64 !== undefined) {
160
+ const jsonContent = atob(dataContentBase64);
161
+ const appProps = JSON.parse(jsonContent);
162
+ return ((0, jsx_runtime_1.jsx)(NestedAppNative_1.NestedApp, { app: appProps.app, config: appProps.config, components: appProps.components, api: appProps.api, activeTheme: appProps.activeTheme, activeTone: appProps.activeTone, title: appProps.name, height: appProps.height, allowPlaygroundPopup: !appProps.noPopup }));
163
+ }
164
+ return ((0, jsx_runtime_1.jsx)(NestedAppNative_1.NestedApp, { app: nestedProps.app, config: nestedProps.config, components: nestedProps.components, api: nestedProps.api, activeTheme: nestedProps.activeTheme, activeTone: nestedProps.activeTone, title: nestedProps.title, height: nestedProps.height, allowPlaygroundPopup: true }));
165
+ },
141
166
  }, children: children }) }));
142
167
  });
143
168
  function removeTextIndents(input) {
@@ -225,67 +250,3 @@ const OrderedList = ({ children, style }) => {
225
250
  const ListItem = ({ children, style }) => {
226
251
  return ((0, jsx_runtime_1.jsx)("li", { className: Markdown_module_scss_1.default.listItem, style: style, children: children }));
227
252
  };
228
- /**
229
- * Finds and evaluates given binding expressions in markdown text.
230
- * The binding expressions are of the form `${...}$`.
231
- * @param extractValue The function to resolve binding expressions
232
- * @returns visitor function that processes the binding expressions
233
- */
234
- function bindingExpression({ extractValue }) {
235
- return (tree) => {
236
- (0, unist_util_visit_1.visit)(tree, "text", (node) => {
237
- return detectBindingExpression(node);
238
- });
239
- };
240
- function detectBindingExpression(node) {
241
- // Remove empty ${} expressions first
242
- node.value = node.value.replace(/\$\{\s*\}/g, "");
243
- const regex = /\$\{((?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*)\}/g;
244
- const parts = node.value.split(regex);
245
- if (parts.length > 1) {
246
- node.type = "html";
247
- node.value = parts
248
- .map((part, index) => {
249
- const extracted = index % 2 === 0 ? part : extractValue(`{${part}}`);
250
- const resultExpr = mapByType(extracted);
251
- // The result expression might be an object, in that case we stringify it here,
252
- // at the last step, so that there are no unnecessary apostrophes
253
- return typeof resultExpr === "object" && resultExpr !== null
254
- ? JSON.stringify(resultExpr)
255
- : resultExpr;
256
- })
257
- .join("");
258
- }
259
- }
260
- function mapByType(extracted) {
261
- if (extracted === null) {
262
- return null;
263
- }
264
- else if (extracted === undefined || typeof extracted === "undefined") {
265
- return undefined;
266
- }
267
- else if (typeof extracted === "object") {
268
- const arrowFuncResult = parseArrowFunc(extracted);
269
- if (arrowFuncResult) {
270
- return arrowFuncResult;
271
- }
272
- if (Array.isArray(extracted)) {
273
- return extracted;
274
- }
275
- return Object.fromEntries(Object.entries(extracted).map(([key, value]) => {
276
- return [key, mapByType(value)];
277
- }));
278
- }
279
- else {
280
- return extracted;
281
- }
282
- }
283
- function parseArrowFunc(extracted) {
284
- if (extracted.hasOwnProperty("type") &&
285
- extracted.type === ScriptingSourceTree_1.T_ARROW_EXPRESSION &&
286
- (extracted === null || extracted === void 0 ? void 0 : extracted._ARROW_EXPR_)) {
287
- return "[xmlui function]";
288
- }
289
- return "";
290
- }
291
- }
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.CodeHighlighterMetaKeysData = exports.CodeHighlighterMetaKeys = void 0;
15
+ exports.parseMetaAndHighlightCode = parseMetaAndHighlightCode;
16
+ const react_1 = require("react");
17
+ /**
18
+ * This function handles two things:
19
+ * 1. The extraction of meta information from code blocks and exposing them as data-meta attributes
20
+ * 2. The highlighting of code blocks providing the highlighter function with meta information
21
+ * @param node The React node containing the code block
22
+ * @param codeHighlighter The highlighter object containing the highlight function and the available languages
23
+ * @returns CSS class names for the codefence and the HTML string with highlighted code tokens
24
+ */
25
+ function parseMetaAndHighlightCode(node, codeHighlighter, themeTone) {
26
+ const codeStr = mapTextContent(node);
27
+ const meta = extractMetaFromChildren(node, exports.CodeHighlighterMetaKeysData, codeStr.split("\n").length);
28
+ const { language } = meta, restMeta = __rest(meta, ["language"]);
29
+ if (language && codeHighlighter.availableLangs.includes(language)) {
30
+ // NOTE: Keep in mind, at this point, we are working with the markdown text
31
+ const htmlCodeStr = codeHighlighter.highlight(codeStr, language, restMeta, themeTone);
32
+ const match = htmlCodeStr.match(/<pre\b[^>]*\bclass\s*=\s*["']([^"']*)["'][^>]*>/i);
33
+ const classNames = match ? match[1] : null;
34
+ // NOTE: Why remove the <pre>?
35
+ // Shiki appends <pre> tags to the highlighted code,
36
+ // so we would get <pre><pre><code>...</code></pre></pre>
37
+ let cleanedHtmlStr = htmlCodeStr.replace(/<pre\b[^>]*>|<\/pre>/gi, "");
38
+ const numberedRowClass = meta.rowNumbers ? "numbered" : "";
39
+ cleanedHtmlStr = cleanedHtmlStr.replaceAll(/<span class="line"/g, `<span class="line ${numberedRowClass}"`);
40
+ return { classNames, cleanedHtmlStr, codeStr, meta };
41
+ }
42
+ return null;
43
+ }
44
+ function mapTextContent(node) {
45
+ if (typeof node === "string") {
46
+ return transformCodeLines(node);
47
+ }
48
+ if ((0, react_1.isValidElement)(node) && node.props && node.props.children) {
49
+ if (Array.isArray(node.props.children)) {
50
+ return node.props.children.map(mapTextContent).join("");
51
+ }
52
+ return mapTextContent(node.props.children);
53
+ }
54
+ return "";
55
+ // ---
56
+ function transformCodeLines(node) {
57
+ const splitNode = node.split(/\r?\n/);
58
+ for (let i = 0; i < splitNode.length; i++) {
59
+ // Backslash before a codefence indicates an escaped codefence
60
+ // -> don't render the backslash
61
+ if (splitNode[i].startsWith("\\```")) {
62
+ splitNode[i] = splitNode[i].replace("\\```", "```");
63
+ }
64
+ }
65
+ // Remove empty lines from start and end
66
+ let startTrimIdx = 0;
67
+ let endTrimIdx = splitNode.length - 1;
68
+ for (let i = 0; i < splitNode.length; i++) {
69
+ if (splitNode[i].trim() !== "") {
70
+ startTrimIdx = i;
71
+ break;
72
+ }
73
+ }
74
+ for (let i = splitNode.length - 1; i >= 0; i--) {
75
+ if (splitNode[i].trim() !== "") {
76
+ endTrimIdx = i;
77
+ break;
78
+ }
79
+ }
80
+ splitNode.splice(0, startTrimIdx);
81
+ splitNode.splice(endTrimIdx + 1);
82
+ return splitNode.join("\n");
83
+ }
84
+ }
85
+ function extractMetaFromChildren(node, keys, codeLength = 0) {
86
+ if (!node)
87
+ return {};
88
+ if (typeof node === "string")
89
+ return {};
90
+ if (typeof node === "number")
91
+ return {};
92
+ if (typeof node === "boolean")
93
+ return {};
94
+ if (Array.isArray(node))
95
+ return {};
96
+ if ((0, react_1.isValidElement)(node) &&
97
+ node.props &&
98
+ node.props.children &&
99
+ typeof node.props.children === "string") {
100
+ const meta = Object.entries(node.props)
101
+ .filter(([key, _]) => keys.includes(key))
102
+ .reduce((acc, [key, value]) => {
103
+ acc[key] = value;
104
+ return acc;
105
+ }, {});
106
+ return {
107
+ [exports.CodeHighlighterMetaKeys.language.prop]: meta[exports.CodeHighlighterMetaKeys.language.data],
108
+ [exports.CodeHighlighterMetaKeys.copy.prop]: parseBoolean(meta[exports.CodeHighlighterMetaKeys.copy.data]),
109
+ [exports.CodeHighlighterMetaKeys.filename.prop]: meta[exports.CodeHighlighterMetaKeys.filename.data],
110
+ [exports.CodeHighlighterMetaKeys.rowNumbers.prop]: parseBoolean(meta[exports.CodeHighlighterMetaKeys.rowNumbers.data]),
111
+ [exports.CodeHighlighterMetaKeys.highlightRows.prop]: meta[exports.CodeHighlighterMetaKeys.highlightRows.data]
112
+ ? parseRowHighlights(meta[exports.CodeHighlighterMetaKeys.highlightRows.data], codeLength)
113
+ : [],
114
+ [exports.CodeHighlighterMetaKeys.highlightSubstrings.prop]: [], // TODO
115
+ };
116
+ }
117
+ return {};
118
+ }
119
+ function parseBoolean(str) {
120
+ if (str === "true")
121
+ return true;
122
+ if (str === "false")
123
+ return false;
124
+ return false;
125
+ }
126
+ function parseRowHighlights(str, codeLines) {
127
+ if (str === "")
128
+ return [];
129
+ return str
130
+ .split(",")
131
+ .map((item) => {
132
+ item = item.trim();
133
+ const splitted = item.split("-");
134
+ const start = Number.isNaN(parseInt(splitted[0], 10)) ? -1 : parseInt(splitted[0], 10);
135
+ let end = 0;
136
+ if (splitted.length === 1) {
137
+ end = Number.isNaN(start + 1) ? -1 : start + 1;
138
+ }
139
+ else {
140
+ end = Number.isNaN(parseInt(splitted[1], 10)) ? -1 : parseInt(splitted[1], 10);
141
+ }
142
+ return { start, end };
143
+ })
144
+ .filter((item) => {
145
+ if (item.start === -1 || item.end === -1)
146
+ return false;
147
+ if (item.start > codeLines || item.end > codeLines)
148
+ return false;
149
+ return true;
150
+ });
151
+ }
152
+ exports.CodeHighlighterMetaKeys = {
153
+ language: { data: "data-language", prop: "language" },
154
+ copy: { data: "data-copy", prop: "copy" },
155
+ filename: { data: "data-filename", prop: "filename" },
156
+ rowNumbers: { data: "data-row-numbers", prop: "rowNumbers" },
157
+ highlightRows: { data: "data-highlight-rows", prop: "highlightRows" },
158
+ highlightSubstrings: { data: "data-highlight-substrings", prop: "highlightSubstrings" },
159
+ };
160
+ exports.CodeHighlighterMetaKeysData = Object.values(exports.CodeHighlighterMetaKeys).map((item) => item.data);
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseBindingExpression = parseBindingExpression;
4
+ const ScriptingSourceTree_1 = require("../../abstractions/scripting/ScriptingSourceTree");
5
+ /**
6
+ * Finds and evaluates given binding expressions in markdown text.
7
+ * The binding expressions are of the form `@{...}`.
8
+ * @param text The markdown text
9
+ * @param extractValue The function to resolve binding expressions
10
+ * @returns the parsed text with resolved binding expressions
11
+ */
12
+ function parseBindingExpression(text, extractValue) {
13
+ // Remove empty @{} expressions first
14
+ text = text.replaceAll(/(?<!\\)\@\{\s*\}/g, "");
15
+ // The (?<!\\) is a "negative lookbehind" in regex that ensures that
16
+ // if escaping the @{...} expression like this: \@{...}, we don't match it
17
+ const regex = /(?<!\\)\@\{((?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*)\}/g;
18
+ const result = text.replace(regex, (_, expr) => {
19
+ const extracted = extractValue(`{${expr}}`);
20
+ const resultExpr = mapByType(extracted);
21
+ // The result expression might be an object, in that case we stringify it here,
22
+ // at the last step, so that there are no unnecessary apostrophes
23
+ return typeof resultExpr === "object" && resultExpr !== null
24
+ ? JSON.stringify(resultExpr)
25
+ : resultExpr;
26
+ });
27
+ return result;
28
+ // ---
29
+ function mapByType(extracted) {
30
+ if (extracted === null) {
31
+ return null;
32
+ }
33
+ else if (extracted === undefined || typeof extracted === "undefined") {
34
+ return undefined;
35
+ }
36
+ else if (typeof extracted === "object") {
37
+ const arrowFuncResult = parseArrowFunc(extracted);
38
+ if (arrowFuncResult) {
39
+ return arrowFuncResult;
40
+ }
41
+ if (Array.isArray(extracted)) {
42
+ return extracted;
43
+ }
44
+ return Object.fromEntries(Object.entries(extracted).map(([key, value]) => {
45
+ return [key, mapByType(value)];
46
+ }));
47
+ }
48
+ else {
49
+ return extracted;
50
+ }
51
+ }
52
+ function parseArrowFunc(extracted) {
53
+ if (extracted.hasOwnProperty("type") &&
54
+ extracted.type === ScriptingSourceTree_1.T_ARROW_EXPRESSION &&
55
+ (extracted === null || extracted === void 0 ? void 0 : extracted._ARROW_EXPR_)) {
56
+ return "[xmlui function]";
57
+ }
58
+ return "";
59
+ }
60
+ }