@spwig/theme-validator 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +367 -0
  2. package/dist/index.d.ts +12 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +11 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/schemas/component_manifest_schema.json +221 -0
  7. package/dist/schemas/theme_manifest_schema.json +267 -0
  8. package/dist/types/manifest.d.ts +183 -0
  9. package/dist/types/manifest.d.ts.map +1 -0
  10. package/dist/types/manifest.js +5 -0
  11. package/dist/types/manifest.js.map +1 -0
  12. package/dist/types/validation-result.d.ts +48 -0
  13. package/dist/types/validation-result.d.ts.map +1 -0
  14. package/dist/types/validation-result.js +26 -0
  15. package/dist/types/validation-result.js.map +1 -0
  16. package/dist/validators/component-validator.d.ts +50 -0
  17. package/dist/validators/component-validator.d.ts.map +1 -0
  18. package/dist/validators/component-validator.js +235 -0
  19. package/dist/validators/component-validator.js.map +1 -0
  20. package/dist/validators/design-tokens-validator.d.ts +46 -0
  21. package/dist/validators/design-tokens-validator.d.ts.map +1 -0
  22. package/dist/validators/design-tokens-validator.js +202 -0
  23. package/dist/validators/design-tokens-validator.js.map +1 -0
  24. package/dist/validators/manifest-validator.d.ts +69 -0
  25. package/dist/validators/manifest-validator.d.ts.map +1 -0
  26. package/dist/validators/manifest-validator.js +206 -0
  27. package/dist/validators/manifest-validator.js.map +1 -0
  28. package/dist/validators/template-validator.d.ts +34 -0
  29. package/dist/validators/template-validator.d.ts.map +1 -0
  30. package/dist/validators/template-validator.js +170 -0
  31. package/dist/validators/template-validator.js.map +1 -0
  32. package/dist/validators/theme-validator.d.ts +44 -0
  33. package/dist/validators/theme-validator.d.ts.map +1 -0
  34. package/dist/validators/theme-validator.js +237 -0
  35. package/dist/validators/theme-validator.js.map +1 -0
  36. package/package.json +50 -0
package/README.md ADDED
@@ -0,0 +1,367 @@
1
+ # @spwig/theme-validator
2
+
3
+ Standalone validation library for Spwig themes and components.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @spwig/theme-validator
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Validate a Theme
14
+
15
+ ```typescript
16
+ import { ThemeValidator } from '@spwig/theme-validator';
17
+
18
+ const validator = new ThemeValidator('./path/to/theme');
19
+ const result = await validator.validate();
20
+
21
+ if (result.isValid) {
22
+ console.log('✅ Theme is valid!');
23
+ console.log('Theme:', result.themeInfo?.display_name);
24
+ } else {
25
+ console.error('❌ Validation failed');
26
+ result.errors.forEach(error => {
27
+ console.error(` ${error.code}: ${error.message}`);
28
+ });
29
+ }
30
+
31
+ // Check warnings
32
+ if (result.warnings.length > 0) {
33
+ console.warn('⚠️ Warnings:');
34
+ result.warnings.forEach(warning => {
35
+ console.warn(` ${warning.code}: ${warning.message}`);
36
+ });
37
+ }
38
+ ```
39
+
40
+ ### Validate a Component
41
+
42
+ ```typescript
43
+ import { ComponentValidator } from '@spwig/theme-validator';
44
+
45
+ const validator = new ComponentValidator('./path/to/component');
46
+ const result = await validator.validate();
47
+
48
+ if (result.isValid) {
49
+ console.log('✅ Component is valid!');
50
+ console.log('Component:', result.componentInfo?.display_name);
51
+ } else {
52
+ console.error('❌ Validation failed');
53
+ result.errors.forEach(error => {
54
+ console.error(` ${error.code}: ${error.message}`);
55
+ });
56
+ }
57
+ ```
58
+
59
+ ### Validate Design Tokens
60
+
61
+ ```typescript
62
+ import { DesignTokensValidator } from '@spwig/theme-validator';
63
+
64
+ const validator = new DesignTokensValidator();
65
+ const result = await validator.validateFile('./design_tokens.json');
66
+
67
+ if (!result.isValid) {
68
+ result.errors.forEach(error => {
69
+ console.error(`${error.code}: ${error.message}`);
70
+ });
71
+ }
72
+ ```
73
+
74
+ ### Validate Template Files
75
+
76
+ ```typescript
77
+ import { TemplateValidator } from '@spwig/theme-validator';
78
+
79
+ const validator = new TemplateValidator();
80
+ const result = await validator.validateFile('./template.html');
81
+
82
+ // Check for template syntax issues
83
+ if (result.warnings.length > 0) {
84
+ console.warn('Template warnings:', result.warnings);
85
+ }
86
+ ```
87
+
88
+ ## API Reference
89
+
90
+ ### ThemeValidator
91
+
92
+ Validates complete theme packages including manifest, components, design tokens, and structure.
93
+
94
+ **Constructor:**
95
+ ```typescript
96
+ constructor(themeDir: string)
97
+ ```
98
+
99
+ **Methods:**
100
+ ```typescript
101
+ async validate(): Promise<ValidationResult>
102
+ ```
103
+
104
+ **What it validates:**
105
+ - Theme manifest against JSON schema
106
+ - Required files (manifest.json, design_tokens.json)
107
+ - Design tokens structure
108
+ - Bundled components
109
+ - Page schemas
110
+ - Asset references
111
+ - Preview images
112
+
113
+ ### ComponentValidator
114
+
115
+ Validates individual component packages.
116
+
117
+ **Constructor:**
118
+ ```typescript
119
+ constructor(componentDir: string)
120
+ ```
121
+
122
+ **Methods:**
123
+ ```typescript
124
+ async validate(): Promise<ValidationResult>
125
+ ```
126
+
127
+ **What it validates:**
128
+ - Component manifest against JSON schema
129
+ - Required files (manifest.json, template.html, schema.json)
130
+ - Template file syntax (basic checks)
131
+ - Props schema validity
132
+ - Asset declarations and file existence
133
+ - Locale files
134
+ - Preview image
135
+ - Dependency version constraints
136
+
137
+ ### DesignTokensValidator
138
+
139
+ Validates design token files.
140
+
141
+ **Constructor:**
142
+ ```typescript
143
+ constructor()
144
+ ```
145
+
146
+ **Methods:**
147
+ ```typescript
148
+ async validateFile(filePath: string): Promise<ValidationResult>
149
+ async validateTokens(tokens: DesignTokens): Promise<ValidationResult>
150
+ ```
151
+
152
+ **What it validates:**
153
+ - Color token formats (hex, rgb, rgba, hsl, CSS variables)
154
+ - Typography values
155
+ - Spacing scales
156
+ - Border radius values
157
+ - Shadow definitions
158
+
159
+ ### TemplateValidator
160
+
161
+ Validates Django/Jinja2 template files.
162
+
163
+ **Constructor:**
164
+ ```typescript
165
+ constructor()
166
+ ```
167
+
168
+ **Methods:**
169
+ ```typescript
170
+ async validateFile(filePath: string): Promise<ValidationResult>
171
+ async validateTemplate(content: string): Promise<ValidationResult>
172
+ ```
173
+
174
+ **What it validates:**
175
+ - Basic Jinja2 syntax
176
+ - Balanced template tags
177
+ - Common template errors
178
+ - UTF-8 encoding
179
+
180
+ ### ManifestValidator
181
+
182
+ Base validator class for manifest files using JSON Schema validation.
183
+
184
+ **Constructor:**
185
+ ```typescript
186
+ constructor()
187
+ ```
188
+
189
+ **Methods:**
190
+ ```typescript
191
+ async loadSchema(schemaPath: string): Promise<object>
192
+ validateAgainstSchema(data: any, schema: object, name: string): boolean
193
+ getErrors(): ValidationError[]
194
+ getWarnings(): ValidationWarning[]
195
+ ```
196
+
197
+ ## TypeScript Types
198
+
199
+ All validators include full TypeScript type definitions:
200
+
201
+ ```typescript
202
+ import type {
203
+ ValidationResult,
204
+ ValidationError,
205
+ ValidationWarning,
206
+ ThemeManifest,
207
+ ComponentManifest,
208
+ DesignTokens,
209
+ PageSchema,
210
+ BundledComponentRef
211
+ } from '@spwig/theme-validator';
212
+ ```
213
+
214
+ ### ValidationResult
215
+
216
+ ```typescript
217
+ interface ValidationResult {
218
+ isValid: boolean;
219
+ errors: ValidationError[];
220
+ warnings: ValidationWarning[];
221
+ themeInfo?: ThemeManifest; // For theme validation
222
+ componentInfo?: ComponentManifest; // For component validation
223
+ }
224
+ ```
225
+
226
+ ### ValidationError
227
+
228
+ ```typescript
229
+ interface ValidationError {
230
+ code: string; // Error code (e.g., 'missing_file', 'invalid_schema')
231
+ message: string; // Human-readable error message
232
+ path?: string; // File path or JSON path where error occurred
233
+ suggestion?: string; // Optional suggestion to fix the error
234
+ }
235
+ ```
236
+
237
+ ### ValidationWarning
238
+
239
+ ```typescript
240
+ interface ValidationWarning {
241
+ code: string;
242
+ message: string;
243
+ path?: string;
244
+ suggestion?: string;
245
+ }
246
+ ```
247
+
248
+ ## Error Codes
249
+
250
+ Common error codes you might encounter:
251
+
252
+ | Code | Description |
253
+ |------|-------------|
254
+ | `directory_not_found` | Theme/component directory doesn't exist |
255
+ | `missing_file` | Required file is missing |
256
+ | `invalid_json` | JSON file is malformed |
257
+ | `schema_validation_failed` | Manifest doesn't match JSON schema |
258
+ | `missing_asset` | Referenced asset file not found |
259
+ | `missing_locale` | Declared locale file not found |
260
+ | `file_too_large` | File exceeds size limit |
261
+ | `invalid_version` | Version number format is invalid |
262
+ | `invalid_dependency` | Dependency version constraint is invalid |
263
+
264
+ ## Integration Examples
265
+
266
+ ### CI/CD Pipeline
267
+
268
+ ```typescript
269
+ // validate-theme.ts
270
+ import { ThemeValidator } from '@spwig/theme-validator';
271
+
272
+ async function validateInCI() {
273
+ const validator = new ThemeValidator(process.cwd());
274
+ const result = await validator.validate();
275
+
276
+ if (!result.isValid) {
277
+ console.error('❌ Theme validation failed:');
278
+ result.errors.forEach(error => {
279
+ console.error(` ${error.code}: ${error.message}`);
280
+ if (error.suggestion) {
281
+ console.error(` 💡 ${error.suggestion}`);
282
+ }
283
+ });
284
+ process.exit(1);
285
+ }
286
+
287
+ if (result.warnings.length > 0) {
288
+ console.warn('⚠️ Warnings found:');
289
+ result.warnings.forEach(warning => {
290
+ console.warn(` ${warning.message}`);
291
+ });
292
+ }
293
+
294
+ console.log('✅ Theme validation passed!');
295
+ }
296
+
297
+ validateInCI().catch(err => {
298
+ console.error('Validation error:', err);
299
+ process.exit(1);
300
+ });
301
+ ```
302
+
303
+ ### Build Tool Integration
304
+
305
+ ```typescript
306
+ // webpack.config.js or build script
307
+ import { ThemeValidator } from '@spwig/theme-validator';
308
+
309
+ class ThemeValidationPlugin {
310
+ apply(compiler) {
311
+ compiler.hooks.beforeCompile.tapPromise('ThemeValidation', async () => {
312
+ const validator = new ThemeValidator('./src/theme');
313
+ const result = await validator.validate();
314
+
315
+ if (!result.isValid) {
316
+ throw new Error('Theme validation failed');
317
+ }
318
+ });
319
+ }
320
+ }
321
+ ```
322
+
323
+ ### Testing
324
+
325
+ ```typescript
326
+ // theme.test.ts
327
+ import { ThemeValidator } from '@spwig/theme-validator';
328
+ import { describe, it, expect } from 'jest';
329
+
330
+ describe('Theme Validation', () => {
331
+ it('should validate successfully', async () => {
332
+ const validator = new ThemeValidator('./fixtures/valid-theme');
333
+ const result = await validator.validate();
334
+
335
+ expect(result.isValid).toBe(true);
336
+ expect(result.errors).toHaveLength(0);
337
+ });
338
+
339
+ it('should detect missing manifest', async () => {
340
+ const validator = new ThemeValidator('./fixtures/invalid-theme');
341
+ const result = await validator.validate();
342
+
343
+ expect(result.isValid).toBe(false);
344
+ expect(result.errors.some(e => e.code === 'missing_file')).toBe(true);
345
+ });
346
+ });
347
+ ```
348
+
349
+ ## Requirements
350
+
351
+ - Node.js >= 18.0.0
352
+ - Dependencies:
353
+ - `ajv` - JSON Schema validation
354
+ - `ajv-errors` - Enhanced error messages
355
+ - `fs-extra` - File system utilities
356
+
357
+ ## Related Packages
358
+
359
+ - [@spwig/theme-cli](../cli) - Command-line interface for theme development
360
+
361
+ ## License
362
+
363
+ Apache License 2.0 - see [LICENSE](../../LICENSE) file for details.
364
+
365
+ ## Support
366
+
367
+ - [GitHub Issues](https://github.com/spwig/theme-sdk/issues)
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Spwig Theme Validator
3
+ * Standalone validation library for Spwig themes
4
+ */
5
+ export { ThemeValidator } from './validators/theme-validator.js';
6
+ export { ComponentValidator } from './validators/component-validator.js';
7
+ export { ManifestValidator } from './validators/manifest-validator.js';
8
+ export { TemplateValidator } from './validators/template-validator.js';
9
+ export { DesignTokensValidator } from './validators/design-tokens-validator.js';
10
+ export type { ValidationResult, ValidationError, ValidationWarning, } from './types/validation-result.js';
11
+ export type { ThemeManifest, ComponentManifest, PageSchema, DesignTokens, BundledComponentRef, } from './types/manifest.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAGhF,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAClB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,mBAAmB,GACpB,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Spwig Theme Validator
3
+ * Standalone validation library for Spwig themes
4
+ */
5
+ // Export validators
6
+ export { ThemeValidator } from './validators/theme-validator.js';
7
+ export { ComponentValidator } from './validators/component-validator.js';
8
+ export { ManifestValidator } from './validators/manifest-validator.js';
9
+ export { TemplateValidator } from './validators/template-validator.js';
10
+ export { DesignTokensValidator } from './validators/design-tokens-validator.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAoB;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC"}
@@ -0,0 +1,221 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Component Manifest Schema",
4
+ "description": "Schema for Spwig component package manifests",
5
+ "type": "object",
6
+ "required": [
7
+ "name",
8
+ "version",
9
+ "display_name",
10
+ "description",
11
+ "author",
12
+ "tier_compatibility",
13
+ "regions"
14
+ ],
15
+ "properties": {
16
+ "name": {
17
+ "type": "string",
18
+ "pattern": "^[a-z][a-z0-9_]*$",
19
+ "minLength": 2,
20
+ "maxLength": 50,
21
+ "description": "Component identifier (lowercase, alphanumeric with underscores)"
22
+ },
23
+ "version": {
24
+ "type": "string",
25
+ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
26
+ "description": "Semantic version (e.g., 1.0.0)"
27
+ },
28
+ "display_name": {
29
+ "type": "string",
30
+ "minLength": 1,
31
+ "maxLength": 100,
32
+ "description": "Human-readable component name"
33
+ },
34
+ "description": {
35
+ "type": "string",
36
+ "minLength": 10,
37
+ "maxLength": 500,
38
+ "description": "Component description for marketplace listing"
39
+ },
40
+ "author": {
41
+ "type": "string",
42
+ "minLength": 1,
43
+ "maxLength": 100,
44
+ "description": "Component author/vendor name"
45
+ },
46
+ "tier_compatibility": {
47
+ "type": "array",
48
+ "minItems": 1,
49
+ "uniqueItems": true,
50
+ "items": {
51
+ "type": "string",
52
+ "enum": ["A", "B", "C"]
53
+ },
54
+ "description": "Security tiers this component is compatible with"
55
+ },
56
+ "regions": {
57
+ "type": "array",
58
+ "minItems": 1,
59
+ "uniqueItems": true,
60
+ "items": {
61
+ "type": "string",
62
+ "pattern": "^[a-z][a-z0-9_]*$"
63
+ },
64
+ "description": "Page regions this component can be placed in"
65
+ },
66
+ "props_schema": {
67
+ "type": "object",
68
+ "description": "JSON Schema defining component properties",
69
+ "required": ["type", "properties"],
70
+ "properties": {
71
+ "type": {
72
+ "const": "object"
73
+ },
74
+ "properties": {
75
+ "type": "object"
76
+ },
77
+ "required": {
78
+ "type": "array",
79
+ "items": {
80
+ "type": "string"
81
+ }
82
+ }
83
+ }
84
+ },
85
+ "assets": {
86
+ "type": "object",
87
+ "properties": {
88
+ "css": {
89
+ "type": "array",
90
+ "items": {
91
+ "type": "string",
92
+ "pattern": "^assets/.*\\.css$"
93
+ },
94
+ "description": "CSS files relative to component root"
95
+ },
96
+ "js": {
97
+ "type": "array",
98
+ "items": {
99
+ "type": "string",
100
+ "pattern": "^assets/.*\\.js$"
101
+ },
102
+ "description": "JavaScript files relative to component root"
103
+ },
104
+ "images": {
105
+ "type": "array",
106
+ "items": {
107
+ "type": "string",
108
+ "pattern": "^assets/.*\\.(png|jpg|jpeg|svg|gif|webp)$"
109
+ },
110
+ "description": "Image files relative to component root"
111
+ }
112
+ },
113
+ "additionalProperties": false
114
+ },
115
+ "dependencies": {
116
+ "type": "array",
117
+ "items": {
118
+ "type": "object",
119
+ "required": ["name", "min_version"],
120
+ "properties": {
121
+ "name": {
122
+ "type": "string",
123
+ "pattern": "^[a-z][a-z0-9_]*$"
124
+ },
125
+ "min_version": {
126
+ "type": "string",
127
+ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
128
+ },
129
+ "max_version": {
130
+ "type": "string",
131
+ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
132
+ }
133
+ }
134
+ },
135
+ "description": "Component dependencies on other components"
136
+ },
137
+ "locales": {
138
+ "type": "array",
139
+ "items": {
140
+ "type": "string",
141
+ "pattern": "^[a-z]{2}(_[A-Z]{2})?$"
142
+ },
143
+ "description": "Supported locale codes (e.g., en, es, fr, en_US)"
144
+ },
145
+ "preview": {
146
+ "type": "string",
147
+ "pattern": "^preview\\.(png|jpg|jpeg|webp)$",
148
+ "description": "Preview image filename"
149
+ },
150
+ "category": {
151
+ "type": "string",
152
+ "enum": [
153
+ "hero",
154
+ "header",
155
+ "footer",
156
+ "content",
157
+ "product",
158
+ "collection",
159
+ "cart",
160
+ "checkout",
161
+ "marketing",
162
+ "social",
163
+ "navigation",
164
+ "utility"
165
+ ],
166
+ "description": "Component category for marketplace organization"
167
+ },
168
+ "tags": {
169
+ "type": "array",
170
+ "maxItems": 10,
171
+ "items": {
172
+ "type": "string",
173
+ "pattern": "^[a-z][a-z0-9-]*$",
174
+ "maxLength": 30
175
+ },
176
+ "description": "Searchable tags for marketplace"
177
+ },
178
+ "license": {
179
+ "type": "string",
180
+ "enum": ["MIT", "Apache-2.0", "GPL-3.0", "Proprietary"],
181
+ "default": "Proprietary",
182
+ "description": "Component license type"
183
+ },
184
+ "changelog": {
185
+ "type": "array",
186
+ "items": {
187
+ "type": "object",
188
+ "required": ["version", "date", "changes"],
189
+ "properties": {
190
+ "version": {
191
+ "type": "string",
192
+ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$"
193
+ },
194
+ "date": {
195
+ "type": "string",
196
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
197
+ },
198
+ "changes": {
199
+ "type": "array",
200
+ "minItems": 1,
201
+ "items": {
202
+ "type": "string"
203
+ }
204
+ }
205
+ }
206
+ },
207
+ "description": "Version history and changes"
208
+ },
209
+ "min_platform_version": {
210
+ "type": "string",
211
+ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
212
+ "description": "Minimum platform version required"
213
+ },
214
+ "max_platform_version": {
215
+ "type": "string",
216
+ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
217
+ "description": "Maximum platform version supported"
218
+ }
219
+ },
220
+ "additionalProperties": false
221
+ }