@jxsuite/schema 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/class-schema.json +103 -1
- package/defs/children-value.schema.ts +10 -1
- package/defs/class-def.schema.ts +107 -1
- package/defs/element-def.schema.ts +15 -2
- package/defs/external-class-def.schema.ts +14 -1
- package/defs/function-def.schema.ts +8 -0
- package/defs/index.ts +4 -0
- package/defs/project-config.schema.ts +3 -2
- package/defs/style-object.schema.ts +4 -10
- package/package.json +1 -1
- package/project-schema.json +20 -2
- package/schema.json +1052 -19
- package/schemas/project.core.schema.json +20 -2
- package/src/guards.ts +10 -0
- package/src/schema.ts +41 -3
- package/src/validate-project.ts +13 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kevin Shenk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/class-schema.json
CHANGED
|
@@ -176,7 +176,16 @@
|
|
|
176
176
|
"parse",
|
|
177
177
|
"serialize",
|
|
178
178
|
"discover",
|
|
179
|
-
"load"
|
|
179
|
+
"load",
|
|
180
|
+
"projectData",
|
|
181
|
+
"resolvePaths",
|
|
182
|
+
"lower",
|
|
183
|
+
"emit",
|
|
184
|
+
"mount",
|
|
185
|
+
"dialect",
|
|
186
|
+
"deploySchema",
|
|
187
|
+
"bindings",
|
|
188
|
+
"testConnection"
|
|
180
189
|
],
|
|
181
190
|
"type": "string"
|
|
182
191
|
},
|
|
@@ -237,6 +246,40 @@
|
|
|
237
246
|
],
|
|
238
247
|
"type": "object"
|
|
239
248
|
},
|
|
249
|
+
"ConnectorBlockDef": {
|
|
250
|
+
"description": "Connection-provider admission block (specs/extensions.md §12). A class carrying this block provides database connections of the given provider/kind.",
|
|
251
|
+
"properties": {
|
|
252
|
+
"kind": {
|
|
253
|
+
"description": "SQL dialect family the provider speaks.",
|
|
254
|
+
"enum": [
|
|
255
|
+
"sqlite",
|
|
256
|
+
"postgres"
|
|
257
|
+
],
|
|
258
|
+
"type": "string"
|
|
259
|
+
},
|
|
260
|
+
"local": {
|
|
261
|
+
"description": "Local-development substitute provider (e.g. sqlite for D1).",
|
|
262
|
+
"type": "string"
|
|
263
|
+
},
|
|
264
|
+
"module": {
|
|
265
|
+
"description": "Module specifier exporting the provider implementation.",
|
|
266
|
+
"type": "string"
|
|
267
|
+
},
|
|
268
|
+
"provider": {
|
|
269
|
+
"description": "Provider identifier (e.g. d1, supabase, sqlite).",
|
|
270
|
+
"type": "string"
|
|
271
|
+
},
|
|
272
|
+
"serve": {
|
|
273
|
+
"description": "Module specifier exporting the serve-time worker binding.",
|
|
274
|
+
"type": "string"
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
"required": [
|
|
278
|
+
"provider",
|
|
279
|
+
"kind"
|
|
280
|
+
],
|
|
281
|
+
"type": "object"
|
|
282
|
+
},
|
|
240
283
|
"FormatDef": {
|
|
241
284
|
"description": "Format participation marker. A class carrying this block is auto-discovered from the project imports map and used for file-extension dispatch by the compiler, server, and studio.",
|
|
242
285
|
"properties": {
|
|
@@ -279,6 +322,56 @@
|
|
|
279
322
|
],
|
|
280
323
|
"type": "object"
|
|
281
324
|
},
|
|
325
|
+
"ProjectBlockDef": {
|
|
326
|
+
"additionalProperties": false,
|
|
327
|
+
"description": "Project-section admission block (specs/extensions.md §9). A class carrying this block owns the project.json section named by `key`; hosts dispatch that section's data through the class's projectData/resolvePaths capabilities.",
|
|
328
|
+
"properties": {
|
|
329
|
+
"description": {
|
|
330
|
+
"type": "string"
|
|
331
|
+
},
|
|
332
|
+
"key": {
|
|
333
|
+
"description": "The project.json top-level section this class owns (exclusive per project).",
|
|
334
|
+
"type": "string"
|
|
335
|
+
},
|
|
336
|
+
"referenceable": {
|
|
337
|
+
"description": "Whether section entries can be referenced from documents (e.g. content types).",
|
|
338
|
+
"type": "boolean"
|
|
339
|
+
},
|
|
340
|
+
"title": {
|
|
341
|
+
"type": "string"
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
"required": [
|
|
345
|
+
"key"
|
|
346
|
+
],
|
|
347
|
+
"type": "object"
|
|
348
|
+
},
|
|
349
|
+
"ServerBlockDef": {
|
|
350
|
+
"additionalProperties": false,
|
|
351
|
+
"description": "Server-mount admission block (specs/extensions.md §11). A class carrying this block mounts routes under its /_jx/ basePath in the site worker and dev server.",
|
|
352
|
+
"properties": {
|
|
353
|
+
"basePath": {
|
|
354
|
+
"description": "Route subtree this class mounts — must be under /_jx/ (exclusive per project).",
|
|
355
|
+
"examples": [
|
|
356
|
+
"/_jx/data",
|
|
357
|
+
"/_jx/auth"
|
|
358
|
+
],
|
|
359
|
+
"type": "string"
|
|
360
|
+
},
|
|
361
|
+
"module": {
|
|
362
|
+
"description": "Module specifier exporting the mount handler.",
|
|
363
|
+
"type": "string"
|
|
364
|
+
},
|
|
365
|
+
"order": {
|
|
366
|
+
"description": "Mount order (ascending; default 100).",
|
|
367
|
+
"type": "number"
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
"required": [
|
|
371
|
+
"basePath"
|
|
372
|
+
],
|
|
373
|
+
"type": "object"
|
|
374
|
+
},
|
|
282
375
|
"StudioHints": {
|
|
283
376
|
"description": "Studio control-surface hints for a format class: editor modes, document-mode rules, templates, and the element/nesting constraints that gate structural editing.",
|
|
284
377
|
"properties": {
|
|
@@ -442,6 +535,9 @@
|
|
|
442
535
|
"$studio": {
|
|
443
536
|
"$ref": "#/$defs/StudioHints"
|
|
444
537
|
},
|
|
538
|
+
"connector": {
|
|
539
|
+
"$ref": "#/$defs/ConnectorBlockDef"
|
|
540
|
+
},
|
|
445
541
|
"description": {
|
|
446
542
|
"type": "string"
|
|
447
543
|
},
|
|
@@ -468,6 +564,12 @@
|
|
|
468
564
|
"format": {
|
|
469
565
|
"$ref": "#/$defs/FormatDef"
|
|
470
566
|
},
|
|
567
|
+
"project": {
|
|
568
|
+
"$ref": "#/$defs/ProjectBlockDef"
|
|
569
|
+
},
|
|
570
|
+
"server": {
|
|
571
|
+
"$ref": "#/$defs/ServerBlockDef"
|
|
572
|
+
},
|
|
471
573
|
"title": {
|
|
472
574
|
"description": "PascalCase class name, used as the export name.",
|
|
473
575
|
"examples": [
|
|
@@ -18,7 +18,8 @@ export const childrenValueSchema = {
|
|
|
18
18
|
description:
|
|
19
19
|
"Array of child definitions — elements, text, or Array namespaces (dynamic lists) mixed " +
|
|
20
20
|
"freely. A bare Array namespace (the whole children slot is one dynamic list) is also " +
|
|
21
|
-
"accepted for backward compatibility
|
|
21
|
+
"accepted for backward compatibility, as is a ${…} template string that resolves at build " +
|
|
22
|
+
"time to an array of child definitions.",
|
|
22
23
|
oneOf: [
|
|
23
24
|
{
|
|
24
25
|
items: {
|
|
@@ -32,5 +33,13 @@ export const childrenValueSchema = {
|
|
|
32
33
|
type: "array",
|
|
33
34
|
},
|
|
34
35
|
{ $ref: "#/$defs/ArrayNamespace" },
|
|
36
|
+
{
|
|
37
|
+
description:
|
|
38
|
+
"Computed children — a ${…} template that resolves at build time to an array of child " +
|
|
39
|
+
'definitions (e.g. "${state.entry.$children}" for parsed content). A bare plain-text ' +
|
|
40
|
+
"string is NOT a valid children value; text children must be array items.",
|
|
41
|
+
pattern: "\\$\\{",
|
|
42
|
+
type: "string",
|
|
43
|
+
},
|
|
35
44
|
],
|
|
36
45
|
} as const;
|
package/defs/class-def.schema.ts
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Method capability roles: "method"/"accessor" plus every static capability role hosts dispatch on
|
|
3
|
+
* (format-registry EXTENSION_CAPABILITIES — specs/extensions.md §8). Kept as a literal tuple so
|
|
4
|
+
* FromSchema inference stays precise; the drift-guard test in tests/class-schema-drift.test.ts
|
|
5
|
+
* asserts parity with EXTENSION_CAPABILITIES.
|
|
6
|
+
*/
|
|
7
|
+
export const CLASS_METHOD_ROLES = [
|
|
8
|
+
"method",
|
|
9
|
+
"accessor",
|
|
10
|
+
"parse",
|
|
11
|
+
"serialize",
|
|
12
|
+
"discover",
|
|
13
|
+
"load",
|
|
14
|
+
"projectData",
|
|
15
|
+
"resolvePaths",
|
|
16
|
+
"lower",
|
|
17
|
+
"emit",
|
|
18
|
+
"mount",
|
|
19
|
+
"dialect",
|
|
20
|
+
"deploySchema",
|
|
21
|
+
"bindings",
|
|
22
|
+
"testConnection",
|
|
23
|
+
] as const;
|
|
24
|
+
|
|
1
25
|
export const classParameterDefSchema = {
|
|
2
26
|
description: "A typed parameter definition for a class.",
|
|
3
27
|
properties: {
|
|
@@ -100,7 +124,7 @@ export const classMethodDefSchema = {
|
|
|
100
124
|
},
|
|
101
125
|
returnType: {},
|
|
102
126
|
role: {
|
|
103
|
-
enum:
|
|
127
|
+
enum: CLASS_METHOD_ROLES,
|
|
104
128
|
type: "string",
|
|
105
129
|
},
|
|
106
130
|
scope: { enum: ["instance", "static"], type: "string" },
|
|
@@ -157,6 +181,85 @@ export const formatDefSchema = {
|
|
|
157
181
|
type: "object",
|
|
158
182
|
} as const;
|
|
159
183
|
|
|
184
|
+
export const projectBlockDefSchema = {
|
|
185
|
+
additionalProperties: false,
|
|
186
|
+
description:
|
|
187
|
+
"Project-section admission block (specs/extensions.md §9). A class carrying this block owns " +
|
|
188
|
+
"the project.json section named by `key`; hosts dispatch that section's data through the " +
|
|
189
|
+
"class's projectData/resolvePaths capabilities.",
|
|
190
|
+
properties: {
|
|
191
|
+
description: { type: "string" },
|
|
192
|
+
key: {
|
|
193
|
+
description: "The project.json top-level section this class owns (exclusive per project).",
|
|
194
|
+
type: "string",
|
|
195
|
+
},
|
|
196
|
+
referenceable: {
|
|
197
|
+
description: "Whether section entries can be referenced from documents (e.g. content types).",
|
|
198
|
+
type: "boolean",
|
|
199
|
+
},
|
|
200
|
+
title: { type: "string" },
|
|
201
|
+
},
|
|
202
|
+
required: ["key"],
|
|
203
|
+
type: "object",
|
|
204
|
+
} as const;
|
|
205
|
+
|
|
206
|
+
export const serverBlockDefSchema = {
|
|
207
|
+
additionalProperties: false,
|
|
208
|
+
description:
|
|
209
|
+
"Server-mount admission block (specs/extensions.md §11). A class carrying this block mounts " +
|
|
210
|
+
"routes under its /_jx/ basePath in the site worker and dev server.",
|
|
211
|
+
properties: {
|
|
212
|
+
basePath: {
|
|
213
|
+
description: "Route subtree this class mounts — must be under /_jx/ (exclusive per project).",
|
|
214
|
+
examples: ["/_jx/data", "/_jx/auth"],
|
|
215
|
+
type: "string",
|
|
216
|
+
},
|
|
217
|
+
module: {
|
|
218
|
+
description: "Module specifier exporting the mount handler.",
|
|
219
|
+
type: "string",
|
|
220
|
+
},
|
|
221
|
+
order: {
|
|
222
|
+
description: "Mount order (ascending; default 100).",
|
|
223
|
+
type: "number",
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
required: ["basePath"],
|
|
227
|
+
type: "object",
|
|
228
|
+
} as const;
|
|
229
|
+
|
|
230
|
+
export const connectorBlockDefSchema = {
|
|
231
|
+
// Open by design: the block mirrors format-registry's ConnectorBlock ([key: string]: unknown) —
|
|
232
|
+
// Providers carry extra keys (e.g. D1's `module`), so additionalProperties stays true.
|
|
233
|
+
description:
|
|
234
|
+
"Connection-provider admission block (specs/extensions.md §12). A class carrying this block " +
|
|
235
|
+
"provides database connections of the given provider/kind.",
|
|
236
|
+
properties: {
|
|
237
|
+
kind: {
|
|
238
|
+
description: "SQL dialect family the provider speaks.",
|
|
239
|
+
enum: ["sqlite", "postgres"],
|
|
240
|
+
type: "string",
|
|
241
|
+
},
|
|
242
|
+
local: {
|
|
243
|
+
description: "Local-development substitute provider (e.g. sqlite for D1).",
|
|
244
|
+
type: "string",
|
|
245
|
+
},
|
|
246
|
+
module: {
|
|
247
|
+
description: "Module specifier exporting the provider implementation.",
|
|
248
|
+
type: "string",
|
|
249
|
+
},
|
|
250
|
+
provider: {
|
|
251
|
+
description: "Provider identifier (e.g. d1, supabase, sqlite).",
|
|
252
|
+
type: "string",
|
|
253
|
+
},
|
|
254
|
+
serve: {
|
|
255
|
+
description: "Module specifier exporting the serve-time worker binding.",
|
|
256
|
+
type: "string",
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
required: ["provider", "kind"],
|
|
260
|
+
type: "object",
|
|
261
|
+
} as const;
|
|
262
|
+
|
|
160
263
|
export const studioHintsSchema = {
|
|
161
264
|
description:
|
|
162
265
|
"Studio control-surface hints for a format class: editor modes, document-mode rules, " +
|
|
@@ -258,6 +361,7 @@ export const classDefSchema = {
|
|
|
258
361
|
$prototype: { const: "Class", type: "string" },
|
|
259
362
|
$schema: { type: "string" },
|
|
260
363
|
$studio: { $ref: "#/$defs/StudioHints" },
|
|
364
|
+
connector: { $ref: "#/$defs/ConnectorBlockDef" },
|
|
261
365
|
description: { type: "string" },
|
|
262
366
|
extends: {
|
|
263
367
|
description: "Base class — string name or $ref to another .class.json.",
|
|
@@ -267,6 +371,8 @@ export const classDefSchema = {
|
|
|
267
371
|
],
|
|
268
372
|
},
|
|
269
373
|
format: { $ref: "#/$defs/FormatDef" },
|
|
374
|
+
project: { $ref: "#/$defs/ProjectBlockDef" },
|
|
375
|
+
server: { $ref: "#/$defs/ServerBlockDef" },
|
|
270
376
|
title: {
|
|
271
377
|
description: "PascalCase class name, used as the export name.",
|
|
272
378
|
type: "string",
|
|
@@ -12,8 +12,10 @@ export const attributesObjectSchema = {
|
|
|
12
12
|
} as const;
|
|
13
13
|
|
|
14
14
|
export const propsObjectSchema = {
|
|
15
|
+
// AnyOf, not oneOf: a RefObject value legitimately matches both the plain-object branch and
|
|
16
|
+
// The RefObject branch, and exclusive matching would reject every $ref-bound prop.
|
|
15
17
|
additionalProperties: {
|
|
16
|
-
|
|
18
|
+
anyOf: [
|
|
17
19
|
{ type: "string" },
|
|
18
20
|
{ type: "number" },
|
|
19
21
|
{ type: "boolean" },
|
|
@@ -39,7 +41,9 @@ export const elementPropertyValueSchema = {
|
|
|
39
41
|
export const switchDefSchema = {
|
|
40
42
|
additionalProperties: false,
|
|
41
43
|
description: "Reactive $ref that drives which case to render.",
|
|
42
|
-
|
|
44
|
+
// The discriminant is a reactive state path (e.g. "#/state/currentRoute") resolved by
|
|
45
|
+
// ResolveRef at render time — not a #/$defs/ type pointer.
|
|
46
|
+
properties: { $ref: { $ref: "#/$defs/StateRef" } },
|
|
43
47
|
required: ["$ref"],
|
|
44
48
|
type: "object",
|
|
45
49
|
} as const;
|
|
@@ -70,6 +74,15 @@ export const elementDefSchema = {
|
|
|
70
74
|
$switch: { $ref: "#/$defs/SwitchDef" },
|
|
71
75
|
alt: { $ref: "#/$defs/StringOrRef" },
|
|
72
76
|
attributes: { $ref: "#/$defs/AttributesObject" },
|
|
77
|
+
cases: {
|
|
78
|
+
additionalProperties: {
|
|
79
|
+
oneOf: [{ $ref: "#/$defs/ElementDef" }, { $ref: "#/$defs/ExternalComponentRef" }],
|
|
80
|
+
},
|
|
81
|
+
description:
|
|
82
|
+
"Switch cases for this element. Maps case values to element definitions or external " +
|
|
83
|
+
"component refs, rendered according to the reactive $switch discriminant.",
|
|
84
|
+
type: "object",
|
|
85
|
+
},
|
|
73
86
|
checked: { $ref: "#/$defs/BoolOrRef" },
|
|
74
87
|
children: { $ref: "#/$defs/ChildrenValue" },
|
|
75
88
|
className: { $ref: "#/$defs/StringOrRef" },
|
|
@@ -92,7 +92,20 @@ export const externalClassDefSchema = {
|
|
|
92
92
|
},
|
|
93
93
|
sameSite: { enum: ["strict", "lax", "none"], type: "string" },
|
|
94
94
|
secure: { type: "boolean" },
|
|
95
|
-
sort: {
|
|
95
|
+
sort: {
|
|
96
|
+
anyOf: [
|
|
97
|
+
{ $ref: "#/$defs/RefObject" },
|
|
98
|
+
{ description: "A single sort rule, e.g. { field, order }.", type: "object" },
|
|
99
|
+
{
|
|
100
|
+
description: 'Ordered sort rules, e.g. [{ field: "date", order: "desc" }].',
|
|
101
|
+
items: { type: "object" },
|
|
102
|
+
type: "array",
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
description:
|
|
106
|
+
"Sort configuration: a reactive $ref binding, a single { field, order } rule, or an " +
|
|
107
|
+
"ordered array of rules.",
|
|
108
|
+
},
|
|
96
109
|
src: {
|
|
97
110
|
description: "Configuration property passed to external class constructor.",
|
|
98
111
|
type: "string",
|
|
@@ -15,6 +15,14 @@ export const functionDefSchema = {
|
|
|
15
15
|
examples: ["./counter.js", "npm:@myorg/validators"],
|
|
16
16
|
type: "string",
|
|
17
17
|
},
|
|
18
|
+
arguments: {
|
|
19
|
+
description:
|
|
20
|
+
"Legacy alias for parameters: bare string parameter names (state may be listed " +
|
|
21
|
+
"explicitly as the first name). Superseded by parameters.",
|
|
22
|
+
examples: [["state", "event"]],
|
|
23
|
+
items: { type: "string" },
|
|
24
|
+
type: "array",
|
|
25
|
+
},
|
|
18
26
|
body: {
|
|
19
27
|
description:
|
|
20
28
|
"Inline function body: an opaque JS source string (first implicit parameter is state), or a structured statement array (spec §20) — explicit structured function declaration, analyzable by tooling and editable visually. The escalation ladder within the shape is structured statements → JS string.",
|
package/defs/index.ts
CHANGED
|
@@ -69,12 +69,16 @@ export {
|
|
|
69
69
|
|
|
70
70
|
// Class definitions
|
|
71
71
|
export {
|
|
72
|
+
CLASS_METHOD_ROLES,
|
|
72
73
|
classParameterDefSchema,
|
|
73
74
|
classFieldDefSchema,
|
|
74
75
|
classConstructorDefSchema,
|
|
75
76
|
classMethodDefSchema,
|
|
76
77
|
classDefSchema,
|
|
78
|
+
connectorBlockDefSchema,
|
|
77
79
|
formatDefSchema,
|
|
80
|
+
projectBlockDefSchema,
|
|
81
|
+
serverBlockDefSchema,
|
|
78
82
|
studioHintsSchema,
|
|
79
83
|
} from "./class-def.schema";
|
|
80
84
|
|
|
@@ -233,11 +233,12 @@ export const projectConfigSchema = {
|
|
|
233
233
|
},
|
|
234
234
|
style: {
|
|
235
235
|
additionalProperties: {
|
|
236
|
-
oneOf: [{ type: "string" }, { type: "number" }, {
|
|
236
|
+
oneOf: [{ type: "string" }, { type: "number" }, { $ref: "#/$defs/StyleObject" }],
|
|
237
237
|
},
|
|
238
238
|
description:
|
|
239
239
|
"Global CSS styles applied to the <body> element. " +
|
|
240
|
-
"Uses the same camelCase CSSOM convention
|
|
240
|
+
"Uses the same camelCase CSSOM convention and recursive selector/at-rule " +
|
|
241
|
+
"nesting as component styles.",
|
|
241
242
|
type: "object",
|
|
242
243
|
},
|
|
243
244
|
url: {
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
export const styleObjectSchema = {
|
|
2
2
|
additionalProperties: {
|
|
3
|
-
oneOf: [
|
|
4
|
-
{ type: "string" },
|
|
5
|
-
{ type: "number" },
|
|
6
|
-
{
|
|
7
|
-
additionalProperties: { oneOf: [{ type: "string" }, { type: "number" }] },
|
|
8
|
-
description: "Nested CSS selector or media breakpoint rules.",
|
|
9
|
-
type: "object",
|
|
10
|
-
},
|
|
11
|
-
],
|
|
3
|
+
oneOf: [{ type: "string" }, { type: "number" }, { $ref: "#/$defs/StyleObject" }],
|
|
12
4
|
},
|
|
13
5
|
description:
|
|
14
6
|
"CSS style definition. camelCase property names follow CSSOM convention. " +
|
|
15
7
|
"Keys starting with :, ., &, or [ are treated as nested CSS selectors. " +
|
|
16
|
-
"Keys matching $media breakpoint names
|
|
8
|
+
"Keys matching $media breakpoint names (or other @-prefixed at-rules) group nested rules. " +
|
|
9
|
+
"Nesting is recursive: selector and at-rule groups may nest to arbitrary depth " +
|
|
10
|
+
"(e.g. breakpoint → selector → pseudo-class), mirroring the compiler's recursive emission.",
|
|
17
11
|
properties: {},
|
|
18
12
|
type: "object",
|
|
19
13
|
} as const;
|
package/package.json
CHANGED
package/project-schema.json
CHANGED
|
@@ -58,6 +58,24 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"type": "object"
|
|
61
|
+
},
|
|
62
|
+
"StyleObject": {
|
|
63
|
+
"additionalProperties": {
|
|
64
|
+
"oneOf": [
|
|
65
|
+
{
|
|
66
|
+
"type": "string"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"type": "number"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"$ref": "#/$defs/StyleObject"
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
"description": "CSS style definition. camelCase property names follow CSSOM convention. Keys starting with :, ., &, or [ are treated as nested CSS selectors. Keys matching $media breakpoint names (or other @-prefixed at-rules) group nested rules. Nesting is recursive: selector and at-rule groups may nest to arbitrary depth (e.g. breakpoint → selector → pseudo-class), mirroring the compiler's recursive emission.",
|
|
77
|
+
"properties": {},
|
|
78
|
+
"type": "object"
|
|
61
79
|
}
|
|
62
80
|
},
|
|
63
81
|
"$id": "https://jxsuite.com/schema/project/v1",
|
|
@@ -360,11 +378,11 @@
|
|
|
360
378
|
"type": "number"
|
|
361
379
|
},
|
|
362
380
|
{
|
|
363
|
-
"
|
|
381
|
+
"$ref": "#/$defs/StyleObject"
|
|
364
382
|
}
|
|
365
383
|
]
|
|
366
384
|
},
|
|
367
|
-
"description": "Global CSS styles applied to the <body> element. Uses the same camelCase CSSOM convention as component styles.",
|
|
385
|
+
"description": "Global CSS styles applied to the <body> element. Uses the same camelCase CSSOM convention and recursive selector/at-rule nesting as component styles.",
|
|
368
386
|
"type": "object"
|
|
369
387
|
},
|
|
370
388
|
"url": {
|