@schalkneethling/miyagi-core 4.4.2 → 4.4.3

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 (115) hide show
  1. package/README.md +7 -2
  2. package/api/app.js +16 -16
  3. package/api/index.js +263 -262
  4. package/bin/miyagi.js +1 -1
  5. package/dist/css/iframe.css +6 -30
  6. package/frontend/assets/css/iframe/accordion-tabs.css +39 -39
  7. package/frontend/assets/css/iframe/jsontree.js.css +149 -149
  8. package/frontend/assets/css/iframe/prism.css +45 -45
  9. package/frontend/assets/css/iframe/styleguide/colors.css +27 -27
  10. package/frontend/assets/css/iframe/styleguide/fonts.css +23 -23
  11. package/frontend/assets/css/iframe/styleguide/index.css +58 -58
  12. package/frontend/assets/css/iframe/styleguide/spacings.css +10 -10
  13. package/frontend/assets/css/iframe.css +191 -191
  14. package/frontend/assets/css/main/menu/config-switcher.css +21 -21
  15. package/frontend/assets/css/main/menu/config-switchers.css +34 -34
  16. package/frontend/assets/css/main/menu/goto.css +16 -16
  17. package/frontend/assets/css/main/menu/nav.css +49 -49
  18. package/frontend/assets/css/main/menu/search.css +34 -34
  19. package/frontend/assets/css/main/menu/title.css +18 -18
  20. package/frontend/assets/css/main/menu.css +89 -89
  21. package/frontend/assets/css/main/reset.css +47 -47
  22. package/frontend/assets/css/main.css +41 -41
  23. package/frontend/assets/css/shared.css +16 -16
  24. package/frontend/assets/css/tokens.css +108 -107
  25. package/frontend/assets/js/_accordion-tabs.js +392 -392
  26. package/frontend/assets/js/_goto.js +59 -59
  27. package/frontend/assets/js/_iframe-links.js +14 -14
  28. package/frontend/assets/js/_is-triggered.js +3 -3
  29. package/frontend/assets/js/_main.js +369 -369
  30. package/frontend/assets/js/_mock-data.js +8 -8
  31. package/frontend/assets/js/_prism.js +1082 -1081
  32. package/frontend/assets/js/_search.js +186 -186
  33. package/frontend/assets/js/_socket.js +44 -44
  34. package/frontend/assets/js/config-switcher/development-mode.js +38 -38
  35. package/frontend/assets/js/config-switcher/index.js +55 -55
  36. package/frontend/assets/js/config-switcher/text-direction.js +22 -22
  37. package/frontend/assets/js/config-switcher/theme.js +68 -68
  38. package/frontend/assets/js/iframe.build.js +25 -25
  39. package/frontend/assets/js/iframe.js +38 -38
  40. package/frontend/assets/js/jsontree.js +979 -976
  41. package/frontend/assets/js/main.build.js +29 -29
  42. package/frontend/assets/js/main.js +31 -31
  43. package/frontend/assets/js/styleguide/color-converter.js +652 -652
  44. package/frontend/assets/js/styleguide/index.js +100 -100
  45. package/lib/build/index.js +1014 -1020
  46. package/lib/cli/app.js +16 -16
  47. package/lib/cli/component.js +50 -50
  48. package/lib/cli/doctor.js +130 -121
  49. package/lib/cli/drupal-assets.js +163 -157
  50. package/lib/cli/lint.js +196 -196
  51. package/lib/cli/run.js +150 -146
  52. package/lib/config.js +86 -86
  53. package/lib/constants/lint-log-levels.js +6 -6
  54. package/lib/drupal/load-assets-config.js +59 -60
  55. package/lib/drupal/resolve-library-assets.js +132 -141
  56. package/lib/errors.js +20 -20
  57. package/lib/generator/component.js +124 -124
  58. package/lib/generator/mocks.js +156 -156
  59. package/lib/helpers.js +68 -68
  60. package/lib/i18n/en.js +93 -93
  61. package/lib/i18n/index.js +8 -8
  62. package/lib/index.js +13 -13
  63. package/lib/init/args.js +153 -153
  64. package/lib/init/config.js +452 -438
  65. package/lib/init/engines.js +41 -41
  66. package/lib/init/index.js +83 -83
  67. package/lib/init/rendering.js +3 -3
  68. package/lib/init/static.js +90 -90
  69. package/lib/init/twing/cache.js +27 -27
  70. package/lib/init/twing/functions.js +37 -37
  71. package/lib/init/views.js +5 -5
  72. package/lib/logger.js +72 -72
  73. package/lib/mocks/get.js +88 -88
  74. package/lib/mocks/index.js +2 -2
  75. package/lib/mocks/resolve/ref.js +447 -447
  76. package/lib/mocks/resolve/tpl.js +218 -218
  77. package/lib/mocks/resolve.js +154 -154
  78. package/lib/render/helpers/resolve-assets.js +29 -39
  79. package/lib/render/helpers.js +27 -27
  80. package/lib/render/index.js +18 -18
  81. package/lib/render/views/iframe/component.docs.js +50 -50
  82. package/lib/render/views/iframe/component.js +249 -248
  83. package/lib/render/views/iframe/design-tokens/colors.js +38 -38
  84. package/lib/render/views/iframe/design-tokens/index.js +3 -3
  85. package/lib/render/views/iframe/design-tokens/sizes.js +35 -35
  86. package/lib/render/views/iframe/design-tokens/typography.js +37 -37
  87. package/lib/render/views/iframe/docs.js +42 -42
  88. package/lib/render/views/iframe/index.js +28 -28
  89. package/lib/render/views/iframe/variation.js +89 -89
  90. package/lib/render/views/iframe/variation.standalone.js +69 -68
  91. package/lib/render/views/main/component.docs.js +38 -38
  92. package/lib/render/views/main/component.js +55 -55
  93. package/lib/render/views/main/design-tokens.js +38 -38
  94. package/lib/render/views/main/docs.js +33 -33
  95. package/lib/render/views/main/index.js +33 -33
  96. package/lib/state/components.js +99 -99
  97. package/lib/state/css.js +33 -33
  98. package/lib/state/docs.js +72 -72
  99. package/lib/state/file-contents.js +154 -154
  100. package/lib/state/helpers.js +53 -53
  101. package/lib/state/index.js +39 -39
  102. package/lib/state/menu/index.js +202 -202
  103. package/lib/state/menu/structure.js +84 -84
  104. package/lib/state/partials.js +12 -12
  105. package/lib/state/source-tree.js +51 -51
  106. package/lib/styleguide/color-names.js +148 -148
  107. package/lib/styleguide/colors.js +113 -113
  108. package/lib/styleguide/helpers.js +33 -33
  109. package/lib/styleguide/index.js +4 -4
  110. package/lib/styleguide/media-queries.js +18 -18
  111. package/lib/styleguide/spacings.js +22 -22
  112. package/lib/styleguide/typography.js +46 -46
  113. package/lib/validator/mocks.js +110 -83
  114. package/lib/validator/schemas.js +236 -227
  115. package/package.json +118 -117
@@ -10,13 +10,14 @@ const ALLOWED_SCHEMA_VALIDATION_MODES = new Set(["collect-all", "fail-fast"]);
10
10
  * @returns {"collect-all"|"fail-fast"}
11
11
  */
12
12
  export function getSchemaValidationMode() {
13
- const mode = global.config.schemaValidationMode ?? DEFAULT_SCHEMA_VALIDATION_MODE;
13
+ const mode =
14
+ global.config.schemaValidationMode ?? DEFAULT_SCHEMA_VALIDATION_MODE;
14
15
 
15
- if (!ALLOWED_SCHEMA_VALIDATION_MODES.has(mode)) {
16
- return DEFAULT_SCHEMA_VALIDATION_MODE;
17
- }
16
+ if (!ALLOWED_SCHEMA_VALIDATION_MODES.has(mode)) {
17
+ return DEFAULT_SCHEMA_VALIDATION_MODE;
18
+ }
18
19
 
19
- return mode;
20
+ return mode;
20
21
  }
21
22
 
22
23
  /**
@@ -25,30 +26,30 @@ export function getSchemaValidationMode() {
25
26
  * and contain an array of JSON Schema definition objects.
26
27
  * @returns {Array<{schema: object, globalSchemaFile: string}>}
27
28
  */
28
- function loadGlobalSchemas() {
29
- const { components, files } = global.config;
30
-
31
- if (!components?.folder || !files?.schema) {
32
- return [];
33
- }
34
-
35
- const schemaFileName = `${files.schema.name}.${files.schema.extension}`;
36
- const globalSchemaFile = path.join(
37
- process.cwd(),
38
- components.folder,
39
- schemaFileName,
40
- );
41
-
42
- const content = global.state?.fileContents?.[globalSchemaFile];
43
- if (!content) {
44
- return [];
45
- }
46
-
47
- const defs = Array.isArray(content) ? content : [content];
48
-
49
- return defs
50
- .filter((def) => def && typeof def === "object")
51
- .map((schema) => ({ schema: structuredClone(schema), globalSchemaFile }));
29
+ export function loadGlobalSchemas() {
30
+ const { components, files } = global.config;
31
+
32
+ if (!components?.folder || !files?.schema) {
33
+ return [];
34
+ }
35
+
36
+ const schemaFileName = `${files.schema.name}.${files.schema.extension}`;
37
+ const globalSchemaFile = path.join(
38
+ process.cwd(),
39
+ components.folder,
40
+ schemaFileName,
41
+ );
42
+
43
+ const content = global.state?.fileContents?.[globalSchemaFile];
44
+ if (!content) {
45
+ return [];
46
+ }
47
+
48
+ const defs = Array.isArray(content) ? content : [content];
49
+
50
+ return defs
51
+ .filter((def) => def && typeof def === "object")
52
+ .map((schema) => ({ schema: structuredClone(schema), globalSchemaFile }));
52
53
  }
53
54
 
54
55
  /**
@@ -57,128 +58,134 @@ function loadGlobalSchemas() {
57
58
  * @returns {{ valid: boolean, errors: Array<object>, validSchemas: Array<object> }}
58
59
  */
59
60
  export function validateSchemas({ components } = {}) {
60
- const validSchemas = [];
61
- const errors = [];
62
- const componentRoutes =
63
- components ??
64
- global.state.routes.filter((route) => route.type === "components" && route.paths.tpl);
65
- const validator = new global.config.schema.ajv(
66
- deepMerge(
67
- {
68
- allErrors: true,
69
- },
70
- global.config.schema.options || {},
71
- ),
72
- );
73
-
74
- // Register global schema definitions before compiling component schemas so
75
- // that component $ref entries targeting global $id values can resolve.
76
- for (const [index, { schema, globalSchemaFile }] of loadGlobalSchemas().entries()) {
77
- if (!schema.$id) {
78
- schema.$id = `miyagi-global:${index}`;
79
- }
80
- try {
81
- validator.addSchema(schema);
82
- validSchemas.push({
83
- component: "$global",
84
- schemaFile: globalSchemaFile,
85
- schema,
86
- });
87
- } catch (error) {
88
- errors.push(
89
- buildSchemaValidationError({
90
- error,
91
- component: "$global",
92
- schemaFile: globalSchemaFile,
93
- rawSchema: schema,
94
- }),
95
- );
96
- }
97
- }
98
-
99
- let pendingSchemas = componentRoutes
100
- .map((component, index) => {
101
- // Absolute schema file path.
102
- const schemaFile = component.paths.schema.full;
103
- // Parsed schema from in-memory state cache.
104
- const schemaFromState = global.state.fileContents[schemaFile];
105
-
106
- if (!schemaFromState) {
107
- return null;
108
- }
109
-
110
- const schema = structuredClone(schemaFromState);
111
- if (!schema.$id) {
112
- schema.$id = component.paths.schema.short || schemaFile || index.toString();
113
- }
114
-
115
- return {
116
- component: component.paths.dir.short,
117
- schemaFile,
118
- rawSchema: schemaFromState,
119
- schema,
120
- };
121
- })
122
- .filter(Boolean);
123
-
124
- while (pendingSchemas.length > 0) {
125
- let progress = false;
126
- const retrySchemas = [];
127
-
128
- pendingSchemas.forEach((entry) => {
129
- try {
130
- validator.compile(entry.schema);
131
- if (!validator.getSchema(entry.schema.$id)) {
132
- validator.addSchema(entry.schema);
133
- }
134
- validSchemas.push({
135
- component: entry.component,
136
- schemaFile: entry.schemaFile,
137
- schema: entry.schema,
138
- });
139
- progress = true;
140
- } catch (error) {
141
- if (isUnresolvedRefError(error)) {
142
- retrySchemas.push(entry);
143
- return;
144
- }
145
-
146
- errors.push(
147
- buildSchemaValidationError({
148
- error,
149
- component: entry.component,
150
- schemaFile: entry.schemaFile,
151
- rawSchema: entry.rawSchema,
152
- }),
153
- );
154
- }
155
- });
156
-
157
- if (!progress) {
158
- retrySchemas.forEach((entry) => {
159
- const error = new Error(
160
- `can't resolve reference while validating schema ${entry.schemaFile}`,
161
- );
162
- errors.push(
163
- buildSchemaValidationError({
164
- error,
165
- component: entry.component,
166
- schemaFile: entry.schemaFile,
167
- rawSchema: entry.rawSchema,
168
- }),
169
- );
170
- });
171
- break;
172
- }
173
-
174
- pendingSchemas = retrySchemas;
175
- }
176
-
177
- return {
178
- valid: errors.length === 0,
179
- errors,
180
- validSchemas,
181
- };
61
+ const validSchemas = [];
62
+ const errors = [];
63
+ const componentRoutes =
64
+ components ??
65
+ global.state.routes.filter(
66
+ (route) => route.type === "components" && route.paths.tpl,
67
+ );
68
+ const validator = new global.config.schema.ajv(
69
+ deepMerge(
70
+ {
71
+ allErrors: true,
72
+ },
73
+ global.config.schema.options || {},
74
+ ),
75
+ );
76
+
77
+ // Register global schema definitions before compiling component schemas so
78
+ // that component $ref entries targeting global $id values can resolve.
79
+ for (const [
80
+ index,
81
+ { schema, globalSchemaFile },
82
+ ] of loadGlobalSchemas().entries()) {
83
+ if (!schema.$id) {
84
+ schema.$id = `miyagi-global:${index}`;
85
+ }
86
+ try {
87
+ validator.addSchema(schema);
88
+ validSchemas.push({
89
+ component: "$global",
90
+ schemaFile: globalSchemaFile,
91
+ schema,
92
+ });
93
+ } catch (error) {
94
+ errors.push(
95
+ buildSchemaValidationError({
96
+ error,
97
+ component: "$global",
98
+ schemaFile: globalSchemaFile,
99
+ rawSchema: schema,
100
+ }),
101
+ );
102
+ }
103
+ }
104
+
105
+ let pendingSchemas = componentRoutes
106
+ .map((component, index) => {
107
+ // Absolute schema file path.
108
+ const schemaFile = component.paths.schema.full;
109
+ // Parsed schema from in-memory state cache.
110
+ const schemaFromState = global.state.fileContents[schemaFile];
111
+
112
+ if (!schemaFromState) {
113
+ return null;
114
+ }
115
+
116
+ const schema = structuredClone(schemaFromState);
117
+ if (!schema.$id) {
118
+ schema.$id =
119
+ component.paths.schema.short || schemaFile || index.toString();
120
+ }
121
+
122
+ return {
123
+ component: component.paths.dir.short,
124
+ schemaFile,
125
+ rawSchema: schemaFromState,
126
+ schema,
127
+ };
128
+ })
129
+ .filter(Boolean);
130
+
131
+ while (pendingSchemas.length > 0) {
132
+ let progress = false;
133
+ const retrySchemas = [];
134
+
135
+ pendingSchemas.forEach((entry) => {
136
+ try {
137
+ validator.compile(entry.schema);
138
+ if (!validator.getSchema(entry.schema.$id)) {
139
+ validator.addSchema(entry.schema);
140
+ }
141
+ validSchemas.push({
142
+ component: entry.component,
143
+ schemaFile: entry.schemaFile,
144
+ schema: entry.schema,
145
+ });
146
+ progress = true;
147
+ } catch (error) {
148
+ if (isUnresolvedRefError(error)) {
149
+ retrySchemas.push(entry);
150
+ return;
151
+ }
152
+
153
+ errors.push(
154
+ buildSchemaValidationError({
155
+ error,
156
+ component: entry.component,
157
+ schemaFile: entry.schemaFile,
158
+ rawSchema: entry.rawSchema,
159
+ }),
160
+ );
161
+ }
162
+ });
163
+
164
+ if (!progress) {
165
+ retrySchemas.forEach((entry) => {
166
+ const error = new Error(
167
+ `can't resolve reference while validating schema ${entry.schemaFile}`,
168
+ );
169
+ errors.push(
170
+ buildSchemaValidationError({
171
+ error,
172
+ component: entry.component,
173
+ schemaFile: entry.schemaFile,
174
+ rawSchema: entry.rawSchema,
175
+ }),
176
+ );
177
+ });
178
+ break;
179
+ }
180
+
181
+ pendingSchemas = retrySchemas;
182
+ }
183
+
184
+ return {
185
+ valid: errors.length === 0,
186
+ errors,
187
+ validSchemas,
188
+ };
182
189
  }
183
190
 
184
191
  /**
@@ -189,28 +196,33 @@ export function validateSchemas({ components } = {}) {
189
196
  * @param {object} obj.rawSchema
190
197
  * @returns {object}
191
198
  */
192
- function buildSchemaValidationError({ error, component, schemaFile, rawSchema }) {
193
- const ajvErrors = Array.isArray(error?.errors) ? error.errors : [];
194
- const [firstAjvError] = ajvErrors;
195
- const hint = getSchemaHint(rawSchema, ajvErrors);
196
- const type = isUnresolvedRefError(error) ? "schema-ref" : "schema";
197
-
198
- return {
199
- type,
200
- component,
201
- schemaFile,
202
- message: error?.toString?.() || "Unknown schema validation error",
203
- schemaPath: firstAjvError?.schemaPath || "",
204
- instancePath: firstAjvError?.instancePath || "",
205
- hint,
206
- details: ajvErrors.map((entry) => ({
207
- keyword: entry.keyword,
208
- message: entry.message,
209
- schemaPath: entry.schemaPath,
210
- instancePath: entry.instancePath,
211
- params: entry.params,
212
- })),
213
- };
199
+ function buildSchemaValidationError({
200
+ error,
201
+ component,
202
+ schemaFile,
203
+ rawSchema,
204
+ }) {
205
+ const ajvErrors = Array.isArray(error?.errors) ? error.errors : [];
206
+ const [firstAjvError] = ajvErrors;
207
+ const hint = getSchemaHint(rawSchema, ajvErrors);
208
+ const type = isUnresolvedRefError(error) ? "schema-ref" : "schema";
209
+
210
+ return {
211
+ type,
212
+ component,
213
+ schemaFile,
214
+ message: error?.toString?.() || "Unknown schema validation error",
215
+ schemaPath: firstAjvError?.schemaPath || "",
216
+ instancePath: firstAjvError?.instancePath || "",
217
+ hint,
218
+ details: ajvErrors.map((entry) => ({
219
+ keyword: entry.keyword,
220
+ message: entry.message,
221
+ schemaPath: entry.schemaPath,
222
+ instancePath: entry.instancePath,
223
+ params: entry.params,
224
+ })),
225
+ };
214
226
  }
215
227
 
216
228
  /**
@@ -219,21 +231,21 @@ function buildSchemaValidationError({ error, component, schemaFile, rawSchema })
219
231
  * @returns {string|undefined}
220
232
  */
221
233
  function getSchemaHint(schema, ajvErrors) {
222
- if (schema?.properties === null) {
223
- return "Hint: `properties` resolves to null. In YAML this often means `properties:` has no nested keys.";
224
- }
225
-
226
- if (
227
- ajvErrors.some(
228
- (error) =>
229
- error?.schemaPath?.endsWith("/properties/type") &&
230
- error?.instancePath?.includes("/properties/"),
231
- )
232
- ) {
233
- return "Hint: check each field `type` value; it must be a valid JSON Schema type.";
234
- }
235
-
236
- return undefined;
234
+ if (schema?.properties === null) {
235
+ return "Hint: `properties` resolves to null. In YAML this often means `properties:` has no nested keys.";
236
+ }
237
+
238
+ if (
239
+ ajvErrors.some(
240
+ (error) =>
241
+ error?.schemaPath?.endsWith("/properties/type") &&
242
+ error?.instancePath?.includes("/properties/"),
243
+ )
244
+ ) {
245
+ return "Hint: check each field `type` value; it must be a valid JSON Schema type.";
246
+ }
247
+
248
+ return undefined;
237
249
  }
238
250
 
239
251
  /**
@@ -241,24 +253,24 @@ function getSchemaHint(schema, ajvErrors) {
241
253
  * @returns {boolean}
242
254
  */
243
255
  function isUnresolvedRefError(error) {
244
- if (typeof error?.missingRef === "string" && error.missingRef.length > 0) {
245
- return true;
246
- }
247
-
248
- if (
249
- typeof error?.missingSchema === "string" &&
250
- error.missingSchema.length > 0
251
- ) {
252
- return true;
253
- }
254
-
255
- if (error?.code === "ERR_MISSING_REF") {
256
- return true;
257
- }
258
-
259
- return /can't resolve reference|missing ref|missing schema/i.test(
260
- error?.message || "",
261
- );
256
+ if (typeof error?.missingRef === "string" && error.missingRef.length > 0) {
257
+ return true;
258
+ }
259
+
260
+ if (
261
+ typeof error?.missingSchema === "string" &&
262
+ error.missingSchema.length > 0
263
+ ) {
264
+ return true;
265
+ }
266
+
267
+ if (error?.code === "ERR_MISSING_REF") {
268
+ return true;
269
+ }
270
+
271
+ return /can't resolve reference|missing ref|missing schema/i.test(
272
+ error?.message || "",
273
+ );
262
274
  }
263
275
 
264
276
  /**
@@ -268,25 +280,22 @@ function isUnresolvedRefError(error) {
268
280
  * @returns {{ type: "schema"|"schema-ref", data: Array<object> }}
269
281
  */
270
282
  export function toSchemaValidationResult(schemaError, options = {}) {
271
- const useVerbose =
272
- options.verbose ?? global.config?.schema?.verbose === true;
273
- const formattedError = {
274
- message: schemaError.message,
275
- component: schemaError.component,
276
- schemaFile: schemaError.schemaFile,
277
- hint: schemaError.hint,
278
- };
279
-
280
- if (useVerbose) {
281
- formattedError.schemaPath = schemaError.schemaPath;
282
- formattedError.instancePath = schemaError.instancePath;
283
- formattedError.details = schemaError.details;
284
- }
285
-
286
- return {
287
- type: schemaError.type || "schema",
288
- data: [
289
- formattedError,
290
- ],
291
- };
283
+ const useVerbose = options.verbose ?? global.config?.schema?.verbose === true;
284
+ const formattedError = {
285
+ message: schemaError.message,
286
+ component: schemaError.component,
287
+ schemaFile: schemaError.schemaFile,
288
+ hint: schemaError.hint,
289
+ };
290
+
291
+ if (useVerbose) {
292
+ formattedError.schemaPath = schemaError.schemaPath;
293
+ formattedError.instancePath = schemaError.instancePath;
294
+ formattedError.details = schemaError.details;
295
+ }
296
+
297
+ return {
298
+ type: schemaError.type || "schema",
299
+ data: [formattedError],
300
+ };
292
301
  }