xmlui 0.10.8 → 0.10.11

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 (118) hide show
  1. package/dist/{metadata/apiInterceptorWorker-Bb5-fQup.mjs → lib/apiInterceptorWorker-DPgtUtdA.mjs} +5870 -3195
  2. package/dist/lib/index-BuIblMfO.mjs +50034 -0
  3. package/dist/lib/index.css +1 -1
  4. package/dist/lib/initMock-CV-9AUzP.mjs +843 -0
  5. package/dist/lib/language-server-web-worker.mjs +8 -7
  6. package/dist/lib/language-server.mjs +6 -6
  7. package/dist/lib/{metadata-utils-DrEexTX9.mjs → metadata-utils-DzONZF-e.mjs} +161 -111
  8. package/dist/lib/scss/components-core/theming/_themes.scss +6 -7
  9. package/dist/lib/{server-common-ddmPKhK6.mjs → server-common-Dsyp3-Ro.mjs} +14949 -10880
  10. package/dist/lib/syntax-monaco.mjs +14 -11
  11. package/dist/lib/syntax-textmate.d.ts +2 -2
  12. package/dist/lib/syntax-textmate.mjs +128 -109
  13. package/dist/lib/transform-CBz7TQJh.mjs +7375 -0
  14. package/dist/lib/xmlui-parser.d.ts +3 -3
  15. package/dist/lib/xmlui-parser.mjs +49 -49
  16. package/dist/lib/xmlui-serializer-Bf9bdvlV.mjs +667 -0
  17. package/dist/lib/xmlui.d.ts +16 -11
  18. package/dist/lib/xmlui.mjs +44 -44
  19. package/dist/{lib/apiInterceptorWorker-DH8wqOVq.mjs → metadata/apiInterceptorWorker-BmKP8bnq.mjs} +5432 -3502
  20. package/dist/metadata/collectedComponentMetadata-Cdi6AFD3.mjs +55851 -0
  21. package/dist/metadata/initMock-B7OlSKKb.mjs +843 -0
  22. package/dist/metadata/style.css +1 -1
  23. package/dist/metadata/xmlui-metadata.mjs +3 -3
  24. package/dist/metadata/xmlui-metadata.umd.js +207 -419
  25. package/dist/scripts/package.json +3 -1
  26. package/dist/scripts/src/components/APICall/APICall.js +4 -4
  27. package/dist/scripts/src/components/Accordion/Accordion.js +1 -1
  28. package/dist/scripts/src/components/Accordion/AccordionItemNative.js +2 -2
  29. package/dist/scripts/src/components/Animation/AnimationNative.js +259 -0
  30. package/dist/scripts/src/components/App/App.js +10 -0
  31. package/dist/scripts/src/components/App/AppNative.js +29 -9
  32. package/dist/scripts/src/components/AutoComplete/AutoComplete.js +1 -1
  33. package/dist/scripts/src/components/AutoComplete/AutoCompleteNative.js +5 -4
  34. package/dist/scripts/src/components/Breakout/BreakoutNative.js +2 -2
  35. package/dist/scripts/src/components/Button/Button.js +1 -1
  36. package/dist/scripts/src/components/Button/ButtonNative.js +4 -0
  37. package/dist/scripts/src/components/Carousel/Carousel.js +13 -20
  38. package/dist/scripts/src/components/Carousel/CarouselContext.js +11 -2
  39. package/dist/scripts/src/components/Carousel/CarouselItemNative.js +2 -2
  40. package/dist/scripts/src/components/Carousel/CarouselNative.js +2 -2
  41. package/dist/scripts/src/components/Charts/AreaChart/AreaChart.js +92 -0
  42. package/dist/scripts/src/components/Charts/AreaChart/AreaChartNative.js +127 -0
  43. package/dist/scripts/src/components/Charts/BarChart/BarChart.js +4 -4
  44. package/dist/scripts/src/components/Charts/BarChart/BarChartNative.js +90 -82
  45. package/dist/scripts/src/components/Charts/LineChart/LineChart.js +3 -3
  46. package/dist/scripts/src/components/Charts/LineChart/LineChartNative.js +5 -1
  47. package/dist/scripts/src/components/Charts/RadarChart/RadarChart.js +92 -0
  48. package/dist/scripts/src/components/Charts/RadarChart/RadarChartNative.js +125 -0
  49. package/dist/scripts/src/components/Checkbox/Checkbox.js +2 -1
  50. package/dist/scripts/src/components/ComponentProvider.js +4 -0
  51. package/dist/scripts/src/components/DataSource/DataSource.js +124 -0
  52. package/dist/scripts/src/components/DateInput/DateInput.js +7 -9
  53. package/dist/scripts/src/components/DateInput/DateInputNative.js +101 -38
  54. package/dist/scripts/src/components/DropdownMenu/DropdownMenu.js +1 -1
  55. package/dist/scripts/src/components/ExpandableItem/ExpandableItemNative.js +18 -12
  56. package/dist/scripts/src/components/Footer/Footer.js +1 -1
  57. package/dist/scripts/src/components/FormItem/FormItem.js +1 -1
  58. package/dist/scripts/src/components/FormItem/ItemWithLabel.js +3 -3
  59. package/dist/scripts/src/components/Heading/Heading.js +83 -28
  60. package/dist/scripts/src/components/Heading/HeadingNative.js +10 -1
  61. package/dist/scripts/src/components/HtmlTags/HtmlTags.js +1 -1
  62. package/dist/scripts/src/components/Image/ImageNative.js +13 -0
  63. package/dist/scripts/src/components/Input/PartialInput.js +28 -3
  64. package/dist/scripts/src/components/List/ListNative.js +6 -5
  65. package/dist/scripts/src/components/NavLink/NavLink.js +1 -1
  66. package/dist/scripts/src/components/NavPanel/NavPanelNative.js +3 -8
  67. package/dist/scripts/src/components/NumberBox/NumberBoxNative.js +2 -2
  68. package/dist/scripts/src/components/Option/Option.js +2 -2
  69. package/dist/scripts/src/components/Option/OptionNative.js +12 -1
  70. package/dist/scripts/src/components/Pagination/Pagination.js +2 -1
  71. package/dist/scripts/src/components/RadioGroup/RadioGroup.js +7 -3
  72. package/dist/scripts/src/components/RadioGroup/RadioGroupNative.js +20 -5
  73. package/dist/scripts/src/components/RadioGroup/RadioItemNative.js +2 -1
  74. package/dist/scripts/src/components/Select/Select.js +1 -1
  75. package/dist/scripts/src/components/Select/SelectNative.js +1 -1
  76. package/dist/scripts/src/components/Slider/Slider.js +10 -8
  77. package/dist/scripts/src/components/Slider/SliderNative.js +24 -21
  78. package/dist/scripts/src/components/Switch/Switch.js +2 -1
  79. package/dist/scripts/src/components/Table/Table.js +1 -1
  80. package/dist/scripts/src/components/Table/TableNative.js +18 -13
  81. package/dist/scripts/src/components/TableOfContents/TableOfContents.js +1 -1
  82. package/dist/scripts/src/components/Text/Text.js +32 -14
  83. package/dist/scripts/src/components/Text/TextNative.js +17 -5
  84. package/dist/scripts/src/components/TextArea/TextAreaNative.js +3 -3
  85. package/dist/scripts/src/components/TextBox/TextBoxNative.js +3 -3
  86. package/dist/scripts/src/components/TimeInput/TimeInput.js +10 -10
  87. package/dist/scripts/src/components/TimeInput/TimeInputNative.js +87 -38
  88. package/dist/scripts/src/components/Toggle/Toggle.js +2 -2
  89. package/dist/scripts/src/components/Tooltip/Tooltip.js +9 -9
  90. package/dist/scripts/src/components/Tooltip/TooltipNative.js +4 -4
  91. package/dist/scripts/src/components/abstractions.js +7 -3
  92. package/dist/scripts/src/components/collectedComponentMetadata.js +316 -0
  93. package/dist/scripts/src/components-core/RestApiProxy.js +3 -1
  94. package/dist/scripts/src/components-core/StandaloneApp.js +823 -0
  95. package/dist/scripts/src/components-core/interception/ApiInterceptor.js +4 -1
  96. package/dist/scripts/src/components-core/interception/Backend.js +13 -7
  97. package/dist/scripts/src/components-core/markup-check.js +279 -0
  98. package/dist/scripts/src/components-core/parts.js +0 -4
  99. package/dist/scripts/src/components-core/rendering/ComponentAdapter.js +36 -16
  100. package/dist/scripts/src/components-core/script-runner/eval-tree-async.js +4 -1
  101. package/dist/scripts/src/components-core/script-runner/eval-tree-sync.js +4 -1
  102. package/dist/scripts/src/components-core/theming/themes/root.js +30 -17
  103. package/dist/scripts/src/components-core/theming/transformThemeVars.js +14 -7
  104. package/dist/scripts/src/components-core/xmlui-parser.js +60 -43
  105. package/dist/scripts/src/index.js +120 -0
  106. package/dist/scripts/src/parsers/xmlui-parser/transform.js +15 -4
  107. package/dist/standalone/xmlui-standalone.es.d.ts +23 -15
  108. package/dist/standalone/xmlui-standalone.umd.js +319 -823
  109. package/package.json +3 -1
  110. package/src/syntax/textMate/xmlui.tmLanguage.json +2 -2
  111. package/dist/lib/index-CqzCWOUw.mjs +0 -38579
  112. package/dist/lib/initMock-C5CXs0-5.mjs +0 -568
  113. package/dist/lib/transform-SMWeyMoq.mjs +0 -5391
  114. package/dist/lib/xmlui-serializer-a0O0jFY-.mjs +0 -497
  115. package/dist/metadata/collectedComponentMetadata-DIT5VbaH.mjs +0 -42985
  116. package/dist/metadata/initMock-D6Vi9kU_.mjs +0 -568
  117. package/dist/scripts/src/components-core/ScrollContext.js +0 -11
  118. package/dist/scripts/src/components-core/utils/audio-utils.js +0 -83
@@ -0,0 +1,823 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.startApp = startApp;
16
+ const jsx_runtime_1 = require("react/jsx-runtime");
17
+ const react_1 = require("react");
18
+ const client_1 = __importDefault(require("react-dom/client"));
19
+ const js_yaml_1 = __importDefault(require("js-yaml"));
20
+ require("../index.scss");
21
+ const AppRoot_1 = require("./rendering/AppRoot");
22
+ const misc_1 = require("./utils/misc");
23
+ const ApiInterceptorProvider_1 = require("./interception/ApiInterceptorProvider");
24
+ const constants_1 = require("./constants");
25
+ const xmlui_parser_1 = require("./xmlui-parser");
26
+ const hooks_1 = require("./utils/hooks");
27
+ const fileExtensions_1 = require("../parsers/xmlui-parser/fileExtensions");
28
+ const Parser_1 = require("../parsers/scripting/Parser");
29
+ const code_behind_collect_1 = require("../parsers/scripting/code-behind-collect");
30
+ const ComponentProvider_1 = require("../components/ComponentProvider");
31
+ const markup_check_1 = require("./markup-check");
32
+ const StandaloneExtensionManager_1 = __importDefault(require("./StandaloneExtensionManager"));
33
+ const ThemeProvider_1 = require("./theming/ThemeProvider");
34
+ const lint_1 = require("../parsers/xmlui-parser/lint");
35
+ const collectedComponentMetadata_1 = require("../components/collectedComponentMetadata");
36
+ const metadata_utils_1 = require("../language-server/services/common/metadata-utils");
37
+ const MAIN_FILE = "Main." + fileExtensions_1.componentFileExtension;
38
+ const MAIN_CODE_BEHIND_FILE = "Main." + fileExtensions_1.codeBehindFileExtension;
39
+ const CONFIG_FILE = "config.json";
40
+ const metadataProvider = new metadata_utils_1.MetadataProvider(collectedComponentMetadata_1.collectedComponentMetadata);
41
+ /**
42
+ * This React component represents a standalone app that implements a web
43
+ * application with xmlui components. A StandaloneApp instance uses a
44
+ * AppRoot wrapped into an ApiInterceptor.
45
+ *
46
+ * AppRoot is responsible for rendering the app (using an internal
47
+ * representation); ApiInterceptor can emulate some backend functionality
48
+ * running in the browser.
49
+ */
50
+ function StandaloneApp({ appDef, appGlobals: globals, decorateComponentsWithTestId, debugEnabled = false, runtime, extensionManager, waitForApiInterceptor = false, children }) {
51
+ var _a;
52
+ // --- Fetch all files constituting the standalone app, including components,
53
+ // --- themes, and other artifacts. Display the app version numbers in the
54
+ // --- console.
55
+ const { standaloneApp, projectCompilation } = useStandalone(appDef, runtime, extensionManager);
56
+ usePrintVersionNumber(standaloneApp);
57
+ const { apiInterceptor, name, appGlobals, defaultTheme, defaultTone, resources, resourceMap, entryPoint, components, themes, sources, } = standaloneApp || {};
58
+ const globalProps = (0, react_1.useMemo)(() => {
59
+ return Object.assign(Object.assign({ name: name }, (appGlobals || {})), (globals || {}));
60
+ }, [appGlobals, globals, name]);
61
+ let contributes = (0, react_1.useMemo)(() => {
62
+ return {
63
+ compoundComponents: components,
64
+ themes,
65
+ };
66
+ }, [components, themes]);
67
+ if (!standaloneApp) {
68
+ // --- Problems found, the standalone app cannot run
69
+ return null;
70
+ }
71
+ // --- The app may use a mocked API already defined in `window.XMLUI_MOCK_API`
72
+ // --- or within the standalone app's definition, in `apiInterceptor`.
73
+ const mockedApi =
74
+ // @ts-ignore
75
+ typeof window !== "undefined" && window.XMLUI_MOCK_API ? window.XMLUI_MOCK_API : apiInterceptor;
76
+ // --- Components can be decorated with test IDs used in end-to-end tests.
77
+ // --- This flag checks the environment if the app runs in E2E test mode.
78
+ const shouldDecorateWithTestId = decorateComponentsWithTestId ||
79
+ // @ts-ignore
80
+ (typeof window !== "undefined" ? window.XMLUI_MOCK_TEST_ID : false);
81
+ // --- An app can turn off the default hash routing.
82
+ const useHashBasedRouting = (_a = appGlobals === null || appGlobals === void 0 ? void 0 : appGlobals.useHashBasedRouting) !== null && _a !== void 0 ? _a : true;
83
+ return ((0, jsx_runtime_1.jsx)(ApiInterceptorProvider_1.ApiInterceptorProvider, { interceptor: mockedApi, useHashBasedRouting: useHashBasedRouting, waitForApiInterceptor: waitForApiInterceptor, children: (0, jsx_runtime_1.jsx)(AppRoot_1.AppRoot, { projectCompilation: projectCompilation, decorateComponentsWithTestId: shouldDecorateWithTestId, node: entryPoint, standalone: true, debugEnabled: debugEnabled,
84
+ // @ts-ignore
85
+ routerBaseName: typeof window !== "undefined" ? window.__PUBLIC_PATH || "" : "", globalProps: globalProps, defaultTheme: defaultTheme, defaultTone: defaultTone, resources: resources, resourceMap: resourceMap, sources: sources, extensionManager: extensionManager, contributes: contributes, children: children }) }));
86
+ }
87
+ /**
88
+ * This function parses the response of a fetch retrieving the contents of a
89
+ * component markup file.
90
+ * @param response The response coming from the fetch
91
+ * @returns If parsing is successful, it returns the parsed response containing
92
+ * the component definition. Otherwise, it returns a component definition that
93
+ * displays the errors.
94
+ */
95
+ function parseComponentMarkupResponse(response) {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ if (!response.ok) {
98
+ throw new Error(`Failed to fetch ${response.url}`);
99
+ }
100
+ const code = yield response.text();
101
+ const fileId = response.url;
102
+ let { component, errors, erroneousCompoundComponentName } = (0, xmlui_parser_1.xmlUiMarkupToComponent)(code, fileId);
103
+ if (errors.length > 0) {
104
+ const compName = erroneousCompoundComponentName !== null && erroneousCompoundComponentName !== void 0 ? erroneousCompoundComponentName : response.url.substring(response.url.lastIndexOf("/") + 1, response.url.length - ".xmlui".length);
105
+ component = (0, xmlui_parser_1.errReportComponent)(errors, fileId, compName);
106
+ }
107
+ return {
108
+ component,
109
+ src: code,
110
+ file: fileId,
111
+ hasError: errors.length > 0,
112
+ };
113
+ });
114
+ }
115
+ /**
116
+ * This function parses the response of a fetch retrieving the contents of a
117
+ * code-behind file.
118
+ * @param response The response coming from the fetch
119
+ * @returns If parsing is successful, it returns the parsed response containing
120
+ * the code-behind declarations. Otherwise, it returns a component definition that
121
+ * displays the errors.
122
+ */
123
+ function parseCodeBehindResponse(response) {
124
+ return __awaiter(this, void 0, void 0, function* () {
125
+ var _a;
126
+ if (!response.ok) {
127
+ throw new Error(`Failed to fetch ${response.url}`);
128
+ }
129
+ const code = yield response.text();
130
+ const parser = new Parser_1.Parser(code);
131
+ try {
132
+ parser.parseStatements();
133
+ }
134
+ catch (e) {
135
+ console.error("Error parsing code behind", e);
136
+ // throw new Error(`Failed to fetch ${response.url}`);
137
+ if (parser.errors.length > 0) {
138
+ return {
139
+ component: (0, xmlui_parser_1.errReportScriptError)(parser.errors[0], response.url),
140
+ file: response.url,
141
+ hasError: true,
142
+ };
143
+ }
144
+ }
145
+ try {
146
+ const codeBehind = (0, code_behind_collect_1.collectCodeBehindFromSource)("Main", code);
147
+ if (Object.keys((_a = codeBehind.moduleErrors) !== null && _a !== void 0 ? _a : {}).length > 0) {
148
+ return {
149
+ component: (0, xmlui_parser_1.errReportModuleErrors)(codeBehind.moduleErrors, response.url),
150
+ file: response.url,
151
+ hasError: true,
152
+ };
153
+ }
154
+ // --- Remove the code-behind tokens from the tree shrinking the tree
155
+ (0, code_behind_collect_1.removeCodeBehindTokensFromTree)(codeBehind);
156
+ return {
157
+ src: code,
158
+ codeBehind: codeBehind,
159
+ file: response.url,
160
+ };
161
+ }
162
+ catch (e) {
163
+ console.error("Error collecting code behind", e);
164
+ }
165
+ });
166
+ }
167
+ // --- Tests is the given path matches the speified file name
168
+ function matchesFileName(path, fileName) {
169
+ return (path.endsWith(`/${fileName}.ts`) ||
170
+ path.endsWith(`/${fileName}.js`) ||
171
+ path.endsWith(`/${fileName}.${fileExtensions_1.componentFileExtension}`) ||
172
+ path.endsWith(`/${fileName}.${fileExtensions_1.codeBehindFileExtension}`));
173
+ }
174
+ // --- Tests if the given path contains the specified folder
175
+ function matchesFolder(path, folderName) {
176
+ return path.includes(`/${folderName}/`);
177
+ }
178
+ /**
179
+ * This function turns a collection of runtime file declarations into a standalone
180
+ * app description.
181
+ * @param runtime A hash object containing the runtime files. The keys are the file
182
+ * paths and the values are the file contents.
183
+ * @returns The standalone app description.
184
+ *
185
+ * When the standalone app is pre-compiled, each property in `runtime` holds such a
186
+ * pre-compiled item. Otherwise, `runtime` is an empty object.
187
+ *
188
+ * While processing the files here, we can assume they are free from compilation
189
+ * errors, as such errors would be observed in the compile phase.
190
+ */
191
+ function resolveRuntime(runtime) {
192
+ // --- Collect the components and their sources. We pass the sources to the standalone app
193
+ // --- so that it can be used for error display and debugging purposes.
194
+ const projectCompilation = {
195
+ entrypoint: {
196
+ filename: "",
197
+ definition: null,
198
+ dependencies: new Set(),
199
+ },
200
+ components: [],
201
+ themes: {},
202
+ };
203
+ const sources = {};
204
+ const componentsByFileName = {};
205
+ const codeBehindsByFileName = {};
206
+ const themes = [];
207
+ // --- Some working variables
208
+ let config;
209
+ let entryPoint;
210
+ let entryPointCodeBehind;
211
+ let apiInterceptor;
212
+ // --- Process the runtime files
213
+ for (const [key, value] of Object.entries(runtime)) {
214
+ if (matchesFileName(key, "config")) {
215
+ // --- We assume that the config file has a default export and this
216
+ // --- export is the standalone app's configuration.
217
+ config = value.default;
218
+ }
219
+ // --- We assume that the entry point is either named "Main" or "App".
220
+ if (matchesFileName(key, "Main") || matchesFileName(key, "App")) {
221
+ if (key.endsWith(fileExtensions_1.codeBehindFileExtension)) {
222
+ // --- "default" contains the functions and variables declared in the
223
+ // --- code behind file.
224
+ entryPointCodeBehind = value.default;
225
+ projectCompilation.entrypoint.codeBehindSource = value.default.src;
226
+ }
227
+ else {
228
+ projectCompilation.entrypoint.filename = key;
229
+ // --- "default" contains the component definition, the file index,
230
+ // --- and the source code.
231
+ entryPoint = value.default.component;
232
+ projectCompilation.entrypoint.definition = entryPoint;
233
+ projectCompilation.entrypoint.markupSource = value.default.src;
234
+ if (value.default.file) {
235
+ // TODO: Remove this prop
236
+ sources[value.default.file] = value.default.src;
237
+ }
238
+ }
239
+ }
240
+ // --- Use API emulation if available
241
+ if (matchesFileName(key, "api")) {
242
+ apiInterceptor = value.default;
243
+ }
244
+ // --- Collect the components and their code behinds
245
+ if (matchesFolder(key, "components")) {
246
+ if (key.endsWith(`.${fileExtensions_1.codeBehindFileExtension}`)) {
247
+ // --- "default" contains the functions and variables declared in the
248
+ // --- component's code behind file.
249
+ codeBehindsByFileName[key] = value.default;
250
+ const componentCompilationForCodeBehind = projectCompilation.components.findLast(({ filename }) => {
251
+ const idxOfCodeBehindFileExtension = key.lastIndexOf(fileExtensions_1.codeBehindFileExtension);
252
+ const idxOfComponentFileExtension = filename.lastIndexOf(fileExtensions_1.componentFileExtension);
253
+ const extensionlessFilenamesMatch = filename.substring(0, idxOfComponentFileExtension) ===
254
+ key.substring(0, idxOfCodeBehindFileExtension);
255
+ return extensionlessFilenamesMatch;
256
+ });
257
+ componentCompilationForCodeBehind.codeBehindSource = value.default.src;
258
+ }
259
+ else {
260
+ // --- "default" contains the component definition, the file index,
261
+ // --- and the source code.
262
+ componentsByFileName[key] = value.default.component;
263
+ sources[value.default.file] = value.default.src;
264
+ const componentCompilation = {
265
+ definition: value.default.component,
266
+ filename: key,
267
+ markupSource: value.default.src,
268
+ dependencies: new Set(),
269
+ };
270
+ projectCompilation.components.push(componentCompilation);
271
+ }
272
+ }
273
+ // --- Collect the themes declared with the app
274
+ if (matchesFolder(key, "themes")) {
275
+ themes.push(value.default);
276
+ }
277
+ }
278
+ // --- We have an entry point defined in the configuration file or in the main app file.
279
+ const safeEntryPoint = (config === null || config === void 0 ? void 0 : config.entryPoint) || entryPoint;
280
+ // --- We may have a code-behind file. If so, we merge the variables and functions
281
+ const entryPointWithCodeBehind = Object.assign(Object.assign({}, safeEntryPoint), { vars: Object.assign(Object.assign({}, entryPointCodeBehind === null || entryPointCodeBehind === void 0 ? void 0 : entryPointCodeBehind.vars), safeEntryPoint === null || safeEntryPoint === void 0 ? void 0 : safeEntryPoint.vars), functions: entryPointCodeBehind === null || entryPointCodeBehind === void 0 ? void 0 : entryPointCodeBehind.functions, scriptError: entryPointCodeBehind === null || entryPointCodeBehind === void 0 ? void 0 : entryPointCodeBehind.moduleErrors });
282
+ // --- Collect the component definition we pass to the rendering engine
283
+ let components = [];
284
+ if (config === null || config === void 0 ? void 0 : config.components) {
285
+ // --- We have a list of components defined in the configuration file
286
+ components = config.components;
287
+ }
288
+ else {
289
+ // --- Use the components collected from the runtime files; merge the components
290
+ // --- with their code behinds
291
+ Object.entries(componentsByFileName).forEach(([key, compound]) => {
292
+ const componentCodeBehind = codeBehindsByFileName[`${key}.xs`];
293
+ const componentWithCodeBehind = Object.assign(Object.assign({}, compound), { component: Object.assign(Object.assign({}, compound.component), { vars: Object.assign(Object.assign({}, compound.component.vars), componentCodeBehind === null || componentCodeBehind === void 0 ? void 0 : componentCodeBehind.vars), functions: componentCodeBehind === null || componentCodeBehind === void 0 ? void 0 : componentCodeBehind.functions, scriptError: componentCodeBehind === null || componentCodeBehind === void 0 ? void 0 : componentCodeBehind.moduleErrors }) });
294
+ components.push(componentWithCodeBehind);
295
+ });
296
+ }
297
+ // --- Done.
298
+ return {
299
+ standaloneApp: Object.assign(Object.assign({}, config), { entryPoint: entryPointWithCodeBehind, components, themes: (config === null || config === void 0 ? void 0 : config.themes) || themes, apiInterceptor: (config === null || config === void 0 ? void 0 : config.apiInterceptor) || apiInterceptor, sources }),
300
+ projectCompilation,
301
+ };
302
+ }
303
+ /**
304
+ * Merges app definitions
305
+ * @param resolvedRuntime Standalone app definition coming from the resolved runtime
306
+ * @param standaloneAppDef Standalode app definition coming from the source
307
+ * @returns Merged standalone app definition
308
+ */
309
+ function mergeAppDefWithRuntime(resolvedRuntime, standaloneAppDef) {
310
+ if (!standaloneAppDef) {
311
+ return resolvedRuntime;
312
+ }
313
+ return Object.assign(Object.assign({}, standaloneAppDef), { entryPoint: standaloneAppDef.entryPoint || resolvedRuntime.entryPoint, components: standaloneAppDef.components || resolvedRuntime.components, themes: standaloneAppDef.themes || resolvedRuntime.themes, apiInterceptor: standaloneAppDef.apiInterceptor || resolvedRuntime.apiInterceptor });
314
+ }
315
+ function resolvePath(basePath, relativePath) {
316
+ // Create a base URL. The 'http://dummy.com' is just a placeholder.
317
+ const baseUrl = new URL(basePath, "http://dummy.com");
318
+ // Create a new URL by resolving the relative path against the base URL.
319
+ const resolvedUrl = new URL(relativePath, baseUrl);
320
+ // Return the pathname, removing the leading slash.
321
+ return resolvedUrl.pathname.substring(1);
322
+ }
323
+ /**
324
+ * Helper function to load theme files with support for both JSON and YAML formats.
325
+ * First tries to load as JSON, if that fails, attempts to load as YAML.
326
+ * @param url The URL to fetch the theme from
327
+ * @returns A Promise resolving to the parsed theme definition
328
+ */
329
+ function loadThemeFile(url) {
330
+ return __awaiter(this, void 0, void 0, function* () {
331
+ // First try to load as JSON
332
+ try {
333
+ const response = yield fetchWithoutCache(url);
334
+ if (!response.ok) {
335
+ // If the JSON file doesn't exist, try YAML immediately
336
+ throw new Error(`Failed to fetch ${url}`);
337
+ }
338
+ // Get the content as text first
339
+ const text = yield response.text();
340
+ // Try to parse as JSON
341
+ try {
342
+ return JSON.parse(text);
343
+ }
344
+ catch (jsonParseError) {
345
+ // If JSON parsing fails, it might be a YAML file with a .json extension
346
+ // or we need to try the .yml version
347
+ console.warn(`Failed to parse ${url} as JSON, attempting YAML parsing.`);
348
+ try {
349
+ return js_yaml_1.default.load(text);
350
+ }
351
+ catch (yamlParseError) {
352
+ // If both JSON and YAML parsing fail for this file, try the .yml version
353
+ throw jsonParseError;
354
+ }
355
+ }
356
+ }
357
+ catch (jsonError) {
358
+ // If JSON file loading fails, try YAML
359
+ const yamlUrl = url.replace(/\.json$/, ".yml");
360
+ try {
361
+ const response = yield fetchWithoutCache(yamlUrl);
362
+ if (!response.ok)
363
+ throw new Error(`Failed to fetch ${yamlUrl}`);
364
+ const text = yield response.text();
365
+ return js_yaml_1.default.load(text);
366
+ }
367
+ catch (yamlError) {
368
+ console.error(`Failed to load theme file: ${url} (JSON error:`, jsonError, "YAML error:", yamlError, ")");
369
+ throw new Error(`Failed to load theme file ${url} in either JSON or YAML format`);
370
+ }
371
+ }
372
+ });
373
+ }
374
+ /**
375
+ * Fetch the up-to-date state of the source file
376
+ * @param url The URL to fetch the source file from
377
+ * @returns The source file contents response
378
+ */
379
+ function fetchWithoutCache(url) {
380
+ return __awaiter(this, void 0, void 0, function* () {
381
+ return fetch((0, misc_1.normalizePath)(url), {
382
+ headers: {
383
+ "Cache-Control": "no-cache, no-store",
384
+ },
385
+ });
386
+ });
387
+ }
388
+ /**
389
+ * Using its definition, this React hook prepares the runtime environment of a
390
+ * standalone app. It runs every time an app source file changes.
391
+ * @param standaloneAppDef The standalone app description
392
+ * @param runtime The pre-compiled runtime environment
393
+ * @returns The prepared StandaloneAppDescription if the collection is
394
+ * successful; otherwise, null.
395
+ */
396
+ function useStandalone(standaloneAppDef, runtime = constants_1.EMPTY_OBJECT, extensionManager) {
397
+ const [standaloneApp, setStandaloneApp] = (0, react_1.useState)(() => {
398
+ // --- Initialize the standalone app
399
+ const resolvedRuntime = resolveRuntime(runtime);
400
+ const appDef = mergeAppDefWithRuntime(resolvedRuntime.standaloneApp, standaloneAppDef);
401
+ // --- In dev mode or when the app is inlined (provided we do not use the standalone mode),
402
+ // --- we must have the app definition available.
403
+ if ((process.env.VITE_DEV_MODE || process.env.VITE_BUILD_MODE === "INLINE_ALL") &&
404
+ !process.env.VITE_STANDALONE) {
405
+ if (!appDef) {
406
+ throw new Error("couldn't find the application metadata");
407
+ }
408
+ return appDef;
409
+ }
410
+ // --- No standalone app yet, we need to get that from the fetched source code
411
+ return null;
412
+ });
413
+ const [projectCompilation, setProjectCompilation] = (0, react_1.useState)(null);
414
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => {
415
+ (function () {
416
+ return __awaiter(this, void 0, void 0, function* () {
417
+ var _a, _b, _c, _d, _e, _f;
418
+ const resolvedRuntime = resolveRuntime(runtime);
419
+ const appDef = mergeAppDefWithRuntime(resolvedRuntime.standaloneApp, standaloneAppDef);
420
+ // --- In dev mode or when the app is inlined (provided we do not use the standalone mode),
421
+ // --- we must have the app definition available.
422
+ if ((process.env.VITE_DEV_MODE || process.env.VITE_BUILD_MODE === "INLINE_ALL") &&
423
+ !process.env.VITE_STANDALONE) {
424
+ if (!appDef) {
425
+ throw new Error("couldn't find the application metadata");
426
+ }
427
+ const lintErrorComponent = processAppLinting(appDef, metadataProvider);
428
+ if (lintErrorComponent) {
429
+ appDef.entryPoint = lintErrorComponent;
430
+ }
431
+ discoverCompilationDependencies({
432
+ projectCompilation: resolvedRuntime.projectCompilation,
433
+ extensionManager,
434
+ });
435
+ setProjectCompilation(resolvedRuntime.projectCompilation);
436
+ setStandaloneApp(appDef);
437
+ return;
438
+ }
439
+ // --- In standalone mode, we must fetch the XMLUI app's source files,
440
+ // --- compile them, and prepare the app's definition for the rendering
441
+ // --- engine.
442
+ if (process.env.VITE_BUILD_MODE === "CONFIG_ONLY") {
443
+ // --- In config-only mode, we override the pre-compiled app definition
444
+ // --- with elements from the configuration file. Note that we do not
445
+ // --- check whether the config file's content is semantically valid.
446
+ const configResponse = yield fetchWithoutCache(CONFIG_FILE);
447
+ const config = yield configResponse.json();
448
+ const themePromises = [];
449
+ (_a = config.themes) === null || _a === void 0 ? void 0 : _a.forEach((theme) => {
450
+ themePromises.push(loadThemeFile(theme));
451
+ });
452
+ const themes = yield Promise.all(themePromises);
453
+ const newAppDef = Object.assign(Object.assign({}, appDef), { name: config.name, appGlobals: config.appGlobals, defaultTheme: config.defaultTheme, resources: config.resources, resourceMap: config.resourceMap, themes });
454
+ const lintErrorComponent = processAppLinting(newAppDef, metadataProvider);
455
+ if (lintErrorComponent) {
456
+ newAppDef.entryPoint = lintErrorComponent;
457
+ }
458
+ discoverCompilationDependencies({
459
+ projectCompilation: resolvedRuntime.projectCompilation,
460
+ extensionManager,
461
+ });
462
+ setProjectCompilation(resolvedRuntime.projectCompilation);
463
+ setStandaloneApp(newAppDef);
464
+ return;
465
+ }
466
+ // --- Fetch the main file
467
+ const entryPointPromise = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
468
+ try {
469
+ const resp = yield fetchWithoutCache(MAIN_FILE);
470
+ if (resp.ok) {
471
+ resolve(parseComponentMarkupResponse(resp));
472
+ }
473
+ else {
474
+ resolve({
475
+ component: (0, xmlui_parser_1.errReportMessage)(`Failed to load the main component (${MAIN_FILE})`),
476
+ file: MAIN_FILE,
477
+ hasError: true,
478
+ });
479
+ }
480
+ }
481
+ catch (e) {
482
+ resolve(null);
483
+ }
484
+ }));
485
+ // --- Fetch the configuration file (we do not check whether the content is semantically valid)
486
+ let config = undefined;
487
+ try {
488
+ const configResponse = yield fetchWithoutCache(CONFIG_FILE);
489
+ config = yield configResponse.json();
490
+ }
491
+ catch (e) { }
492
+ // --- Fetch the themes according to the configuration
493
+ let themePromises;
494
+ if (((_b = config === null || config === void 0 ? void 0 : config.themes) !== null && _b !== void 0 ? _b : []).length === 0 && (config === null || config === void 0 ? void 0 : config.defaultTheme)) {
495
+ // --- Special case, we have only a single "defaultTheme" in the configuration
496
+ const fetchDefaultTheme = loadThemeFile(`themes/${config === null || config === void 0 ? void 0 : config.defaultTheme}.json`);
497
+ themePromises = [fetchDefaultTheme];
498
+ }
499
+ else {
500
+ // --- In any other case, we fetch all themes defined in the configuration
501
+ themePromises = (_c = config === null || config === void 0 ? void 0 : config.themes) === null || _c === void 0 ? void 0 : _c.map((themePath) => {
502
+ return loadThemeFile(themePath);
503
+ });
504
+ }
505
+ // --- Fetch component files according to the configuration
506
+ const componentPromises = (_d = config === null || config === void 0 ? void 0 : config.components) === null || _d === void 0 ? void 0 : _d.map((componentPath) => __awaiter(this, void 0, void 0, function* () {
507
+ const value = yield fetchWithoutCache(componentPath);
508
+ if (componentPath.endsWith(`.${fileExtensions_1.componentFileExtension}`)) {
509
+ return yield parseComponentMarkupResponse(value);
510
+ }
511
+ else {
512
+ return yield parseCodeBehindResponse(value);
513
+ }
514
+ }));
515
+ // --- Let the promises resolve
516
+ const [loadedEntryPoint, loadedComponents, themes] = yield Promise.all([
517
+ entryPointPromise,
518
+ Promise.all(componentPromises || []),
519
+ Promise.all(themePromises || []),
520
+ ]);
521
+ // --- Collect the elements of the standalone app (and potential errors)
522
+ const errorComponents = [];
523
+ // --- Check if the main component has errors
524
+ if (loadedEntryPoint.hasError) {
525
+ errorComponents.push(loadedEntryPoint.component);
526
+ }
527
+ let loadedEntryPointCodeBehind = null;
528
+ if (((_e = loadedEntryPoint.component.props) === null || _e === void 0 ? void 0 : _e.codeBehind) !== undefined) {
529
+ // --- We have a code-behind file for the main component
530
+ loadedEntryPointCodeBehind = (yield new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
531
+ var _a;
532
+ try {
533
+ const resp = yield fetchWithoutCache(resolvePath(MAIN_FILE, ((_a = loadedEntryPoint.component.props) === null || _a === void 0 ? void 0 : _a.codeBehind) || MAIN_CODE_BEHIND_FILE));
534
+ const codeBehind = yield parseCodeBehindResponse(resp);
535
+ resolve(codeBehind.hasError ? codeBehind : codeBehind.codeBehind);
536
+ }
537
+ catch (e) {
538
+ resolve(null);
539
+ }
540
+ })));
541
+ if (loadedEntryPointCodeBehind.hasError) {
542
+ errorComponents.push(loadedEntryPointCodeBehind.component);
543
+ }
544
+ }
545
+ // --- Check if any of the components have markup errors
546
+ loadedComponents.forEach((compWrapper) => {
547
+ if (compWrapper.hasError) {
548
+ errorComponents.push(compWrapper.component);
549
+ }
550
+ });
551
+ // --- Collect the sources and code-behinds
552
+ const sources = {};
553
+ const codeBehinds = {};
554
+ // --- The main component source
555
+ if (loadedEntryPoint.file) {
556
+ sources[loadedEntryPoint.file] = loadedEntryPoint.src;
557
+ resolvedRuntime.projectCompilation.entrypoint.filename = MAIN_FILE;
558
+ resolvedRuntime.projectCompilation.entrypoint.definition = loadedEntryPoint.component;
559
+ resolvedRuntime.projectCompilation.entrypoint.markupSource = loadedEntryPoint.src;
560
+ if ((loadedEntryPointCodeBehind === null || loadedEntryPointCodeBehind === void 0 ? void 0 : loadedEntryPointCodeBehind.src) !== undefined) {
561
+ resolvedRuntime.projectCompilation.entrypoint.codeBehindSource =
562
+ loadedEntryPointCodeBehind.src;
563
+ }
564
+ }
565
+ // --- Components may have code-behind files
566
+ loadedComponents.forEach((compWrapper) => {
567
+ var _a;
568
+ if ((_a = compWrapper === null || compWrapper === void 0 ? void 0 : compWrapper.file) === null || _a === void 0 ? void 0 : _a.endsWith(`.${fileExtensions_1.codeBehindFileExtension}`)) {
569
+ codeBehinds[compWrapper.file] = compWrapper.codeBehind;
570
+ }
571
+ else {
572
+ if (compWrapper.file) {
573
+ sources[compWrapper.file] = compWrapper.src;
574
+ // resolvedRuntime.projectCompilation.entrypoint.filename = MAIN_FILE;
575
+ // resolvedRuntime.projectCompilation.entrypoint.definition = loadedEntryPoint.component;
576
+ // resolvedRuntime.projectCompilation.entrypoint.markupSource = loadedEntryPoint.src;
577
+ }
578
+ }
579
+ });
580
+ // --- Assemble the runtime for the main app file
581
+ const entryPointWithCodeBehind = Object.assign(Object.assign({}, loadedEntryPoint.component), { vars: Object.assign(Object.assign({}, loadedEntryPointCodeBehind === null || loadedEntryPointCodeBehind === void 0 ? void 0 : loadedEntryPointCodeBehind.vars), loadedEntryPoint.component.vars), functions: loadedEntryPointCodeBehind === null || loadedEntryPointCodeBehind === void 0 ? void 0 : loadedEntryPointCodeBehind.functions, scriptError: loadedEntryPointCodeBehind === null || loadedEntryPointCodeBehind === void 0 ? void 0 : loadedEntryPointCodeBehind.moduleErrors });
582
+ const defaultTheme = (_f = entryPointWithCodeBehind.props) === null || _f === void 0 ? void 0 : _f.defaultTheme;
583
+ // --- We test whether the default theme is not from a binding
584
+ // --- expression and is not a built-in theme already loaded. If so,
585
+ // --- we load it from the `themes` folder.
586
+ if (defaultTheme && typeof defaultTheme === "string" && !defaultTheme.includes("{")) {
587
+ if (!ThemeProvider_1.builtInThemes.find((theme) => theme.id === defaultTheme) &&
588
+ !themes.find((theme) => theme.id === defaultTheme)) {
589
+ themes.push(yield loadThemeFile(`themes/${defaultTheme}.json`));
590
+ }
591
+ }
592
+ // --- Assemble the runtime for the components
593
+ const componentsWithCodeBehinds = loadedComponents
594
+ .filter((compWrapper) => { var _a; return !((_a = compWrapper === null || compWrapper === void 0 ? void 0 : compWrapper.file) === null || _a === void 0 ? void 0 : _a.endsWith(".xmlui.xs")); })
595
+ .map((compWrapper) => {
596
+ const componentCodeBehind = codeBehinds[compWrapper.file + ".xs"];
597
+ return Object.assign(Object.assign({}, compWrapper.component), { component: Object.assign(Object.assign({}, compWrapper.component.component), { vars: Object.assign(Object.assign({}, compWrapper.component.component.vars), componentCodeBehind === null || componentCodeBehind === void 0 ? void 0 : componentCodeBehind.vars), functions: componentCodeBehind === null || componentCodeBehind === void 0 ? void 0 : componentCodeBehind.functions, scriptError: componentCodeBehind === null || componentCodeBehind === void 0 ? void 0 : componentCodeBehind.moduleErrors }) });
598
+ });
599
+ // --- We may have components that are not in the configuration file.
600
+ // --- We need to load them and their code-behinds. First, we collect
601
+ // --- the components to load.
602
+ let componentsToLoad = collectMissingComponents(entryPointWithCodeBehind, componentsWithCodeBehinds, undefined, extensionManager);
603
+ // --- Try to load the components referenced in the markup, collect
604
+ // --- those that failed
605
+ const componentsFailedToLoad = new Set();
606
+ while (componentsToLoad.size > 0) {
607
+ const componentPromises = [...componentsToLoad].map((componentPath) => __awaiter(this, void 0, void 0, function* () {
608
+ var _a, _b;
609
+ try {
610
+ // --- Promises for the component markup files
611
+ const componentPromise = fetchWithoutCache(`components/${componentPath}.${fileExtensions_1.componentFileExtension}`);
612
+ // --- Let the promises resolve
613
+ const componentMarkup = yield componentPromise;
614
+ // --- Parse the component markup and check for errors
615
+ const compWrapper = yield parseComponentMarkupResponse(componentMarkup);
616
+ if (compWrapper.hasError) {
617
+ errorComponents.push(compWrapper.component);
618
+ }
619
+ sources[compWrapper.file] = compWrapper.src;
620
+ const compCompilation = {
621
+ dependencies: new Set(),
622
+ filename: compWrapper.file,
623
+ markupSource: compWrapper.src,
624
+ definition: compWrapper.component,
625
+ };
626
+ let componentCodeBehind = null;
627
+ if ("codeBehind" in compWrapper.component &&
628
+ ((_a = compWrapper.component) === null || _a === void 0 ? void 0 : _a.codeBehind) !== undefined) {
629
+ // --- Promises for the component code-behind files
630
+ componentCodeBehind = (yield new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
631
+ var _a;
632
+ try {
633
+ const codeBehind = yield fetchWithoutCache(resolvePath(`components/${componentPath}`, ((_a = compWrapper.component) === null || _a === void 0 ? void 0 : _a.codeBehind) ||
634
+ `${componentPath}.${fileExtensions_1.codeBehindFileExtension}`));
635
+ const codeBehindWrapper = yield parseCodeBehindResponse(codeBehind);
636
+ if (codeBehindWrapper.hasError) {
637
+ errorComponents.push(codeBehindWrapper.component);
638
+ }
639
+ resolve(codeBehindWrapper.hasError
640
+ ? codeBehindWrapper.component
641
+ : codeBehindWrapper);
642
+ }
643
+ catch (_b) {
644
+ resolve(null);
645
+ }
646
+ })));
647
+ if (componentCodeBehind && "src" in componentCodeBehind) {
648
+ compCompilation.codeBehindSource = componentCodeBehind.src;
649
+ }
650
+ }
651
+ resolvedRuntime.projectCompilation.components.push(compCompilation);
652
+ const compoundComp = Object.assign(Object.assign({}, compWrapper.component), { component: Object.assign(Object.assign({}, compWrapper.component.component), { vars: Object.assign(Object.assign({}, compWrapper.component.component.vars), (_b = componentCodeBehind === null || componentCodeBehind === void 0 ? void 0 : componentCodeBehind.component) === null || _b === void 0 ? void 0 : _b.vars) }) });
653
+ if (componentCodeBehind && "codeBehind" in componentCodeBehind) {
654
+ compoundComp.component.functions = componentCodeBehind.codeBehind.functions;
655
+ compoundComp.component.scriptError = componentCodeBehind.codeBehind.moduleErrors;
656
+ }
657
+ return compoundComp;
658
+ }
659
+ catch (e) {
660
+ componentsFailedToLoad.add(componentPath);
661
+ return null;
662
+ }
663
+ }));
664
+ const componentWrappers = yield Promise.all(componentPromises);
665
+ componentsWithCodeBehinds.push(...componentWrappers.filter((comp) => !!comp));
666
+ componentsToLoad = collectMissingComponents(entryPointWithCodeBehind, componentsWithCodeBehinds, componentsFailedToLoad, extensionManager);
667
+ }
668
+ // --- Let's check for errors to display
669
+ const newAppDef = Object.assign(Object.assign({}, config), { themes,
670
+ sources, components: componentsWithCodeBehinds, entryPoint: entryPointWithCodeBehind });
671
+ const lintErrorComponent = processAppLinting(newAppDef, metadataProvider);
672
+ const errorComponent = errorComponents.length > 0
673
+ ? {
674
+ type: "VStack",
675
+ props: { gap: 0, padding: 0 },
676
+ children: errorComponents,
677
+ }
678
+ : null;
679
+ if (errorComponent) {
680
+ if (lintErrorComponent) {
681
+ errorComponent.children.push(lintErrorComponent);
682
+ }
683
+ newAppDef.entryPoint = errorComponent;
684
+ }
685
+ else if (lintErrorComponent) {
686
+ newAppDef.entryPoint = lintErrorComponent;
687
+ }
688
+ discoverCompilationDependencies({
689
+ projectCompilation: resolvedRuntime.projectCompilation,
690
+ extensionManager,
691
+ });
692
+ setProjectCompilation(resolvedRuntime.projectCompilation);
693
+ setStandaloneApp(newAppDef);
694
+ });
695
+ })();
696
+ }, [runtime, standaloneAppDef]);
697
+ return { standaloneApp, projectCompilation };
698
+ }
699
+ /**
700
+ * Collect the missing components referenced by any part of the app
701
+ * @param entryPoint The app's main markup
702
+ * @param components The component markups
703
+ * @param componentsFailedToLoad The components that failed to load here
704
+ * @returns The components that are still missing
705
+ */
706
+ function collectMissingComponents(entryPoint, components, componentsFailedToLoad = new Set(), extensionManager) {
707
+ // --- Add the discovered compound components to the registry
708
+ const componentRegistry = new ComponentProvider_1.ComponentRegistry({ compoundComponents: components }, extensionManager);
709
+ // --- Check the xmlui markup. This check will find all unloaded components
710
+ const result = (0, markup_check_1.checkXmlUiMarkup)(entryPoint, components, {
711
+ getComponentProps: (componentName) => {
712
+ var _a, _b;
713
+ return (_b = (_a = componentRegistry.lookupComponentRenderer(componentName)) === null || _a === void 0 ? void 0 : _a.descriptor) === null || _b === void 0 ? void 0 : _b.props;
714
+ },
715
+ acceptArbitraryProps: () => {
716
+ return true;
717
+ },
718
+ getComponentValidator: () => {
719
+ return null;
720
+ },
721
+ getComponentEvents: () => {
722
+ return null;
723
+ },
724
+ componentRegistered: (componentName) => {
725
+ return componentRegistry.hasComponent(componentName);
726
+ },
727
+ });
728
+ componentRegistry.destroy();
729
+ // --- Collect all missing components.
730
+ // Omit the components that failed to load and the ones that are not in #app-ns namespace
731
+ return new Set(result
732
+ .filter((r) => r.code === "M001")
733
+ .map((r) => r.args[0].replace("#app-ns.", ""))
734
+ .filter((comp) => !componentsFailedToLoad.has(comp) && !comp.includes(".")));
735
+ }
736
+ // --- This React hook logs the app's version number to the browser's console at startup
737
+ function usePrintVersionNumber(standaloneApp) {
738
+ const logged = (0, react_1.useRef)(false);
739
+ (0, react_1.useEffect)(() => {
740
+ if (logged.current) {
741
+ return;
742
+ }
743
+ logged.current = true;
744
+ let log = `XMLUI version: ${process.env.VITE_XMLUI_VERSION || "dev"}`;
745
+ if (standaloneApp === null || standaloneApp === void 0 ? void 0 : standaloneApp.name) {
746
+ log += `; ${standaloneApp.name} version: ${process.env.VITE_APP_VERSION || "dev"}`;
747
+ }
748
+ console.log(log);
749
+ }, [standaloneApp === null || standaloneApp === void 0 ? void 0 : standaloneApp.name]);
750
+ }
751
+ let contentRoot = null;
752
+ /**
753
+ * This function injects the StandaloneApp component into a React app. It looks
754
+ * up a component with the "root" id as the host of the standalone app. If such
755
+ * an element does not exist, it creates a `<div id="root">` element.
756
+ * @param runtime The app's runtime representation
757
+ * @param components The related component's runtime representation
758
+ * @returns The content's root element
759
+ */
760
+ function startApp(runtime, extensions = [], extensionManager = new StandaloneExtensionManager_1.default()) {
761
+ extensionManager.registerExtension(extensions);
762
+ let rootElement = document.getElementById("root");
763
+ if (!rootElement) {
764
+ rootElement = document.createElement("div");
765
+ rootElement.setAttribute("id", "root");
766
+ document.body.appendChild(rootElement);
767
+ }
768
+ if (!contentRoot) {
769
+ contentRoot = client_1.default.createRoot(rootElement);
770
+ }
771
+ contentRoot.render((0, jsx_runtime_1.jsx)(StandaloneApp, { runtime: runtime, extensionManager: extensionManager }));
772
+ return contentRoot;
773
+ }
774
+ exports.default = StandaloneApp;
775
+ function processAppLinting(appDef, metadataProvider) {
776
+ var _a;
777
+ const lintSeverity = (0, lint_1.getLintSeverity)((_a = appDef.appGlobals) === null || _a === void 0 ? void 0 : _a.lintSeverity);
778
+ if (lintSeverity !== lint_1.LintSeverity.Skip) {
779
+ const allComponentLints = (0, lint_1.lintApp)({
780
+ appDef,
781
+ metadataProvider,
782
+ });
783
+ if (allComponentLints.length > 0) {
784
+ if (lintSeverity === lint_1.LintSeverity.Warning) {
785
+ allComponentLints.forEach(lint_1.printComponentLints);
786
+ }
787
+ else if (lintSeverity === lint_1.LintSeverity.Error) {
788
+ return (0, lint_1.lintErrorsComponent)(allComponentLints);
789
+ }
790
+ }
791
+ return null;
792
+ }
793
+ }
794
+ function discoverCompilationDependencies({ projectCompilation: { components, entrypoint }, extensionManager, }) {
795
+ const registry = new ComponentProvider_1.ComponentRegistry({}, extensionManager);
796
+ const entrypointDependencies = discoverDirectComponentDependencies(entrypoint.definition, registry);
797
+ entrypoint.dependencies = entrypointDependencies;
798
+ for (const componentCompilation of components) {
799
+ const compDependencies = discoverDirectComponentDependencies(componentCompilation.definition.component, registry);
800
+ compDependencies.delete(componentCompilation.definition.name);
801
+ componentCompilation.dependencies = compDependencies;
802
+ }
803
+ registry.destroy();
804
+ }
805
+ function discoverDirectComponentDependencies(entrypoint, registry) {
806
+ return discoverDirectComponentDependenciesHelp(entrypoint, registry, new Set());
807
+ }
808
+ function discoverDirectComponentDependenciesHelp(component, registry, deps) {
809
+ if (!component) {
810
+ return deps;
811
+ }
812
+ const compName = component.type;
813
+ if (!registry.hasComponent(compName)) {
814
+ deps.add(compName);
815
+ }
816
+ if (!component.children) {
817
+ return deps;
818
+ }
819
+ for (const child of component.children) {
820
+ discoverDirectComponentDependenciesHelp(child, registry, deps);
821
+ }
822
+ return deps;
823
+ }