juxscript 1.0.88 → 1.0.90
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/bin/cli.js +243 -92
- package/index.js +21 -0
- package/lib/componentsv2/base/BaseEngine.d.ts +10 -0
- package/lib/componentsv2/base/BaseEngine.d.ts.map +1 -1
- package/lib/componentsv2/base/BaseEngine.js +28 -7
- package/lib/componentsv2/base/BaseEngine.js.map +1 -1
- package/lib/componentsv2/base/BaseEngine.ts +29 -0
- package/lib/componentsv2/base/OptionsContract.d.ts +20 -0
- package/lib/componentsv2/base/OptionsContract.d.ts.map +1 -0
- package/lib/componentsv2/base/OptionsContract.js +107 -0
- package/lib/componentsv2/base/OptionsContract.js.map +1 -0
- package/lib/componentsv2/base/OptionsContract.ts +139 -0
- package/lib/componentsv2/element/component.d.ts +22 -0
- package/lib/componentsv2/element/component.d.ts.map +1 -1
- package/lib/componentsv2/element/component.js +22 -0
- package/lib/componentsv2/element/component.js.map +1 -1
- package/lib/componentsv2/element/component.ts +23 -1
- package/lib/componentsv2/element/engine.d.ts +31 -14
- package/lib/componentsv2/element/engine.d.ts.map +1 -1
- package/lib/componentsv2/element/engine.js +74 -23
- package/lib/componentsv2/element/engine.js.map +1 -1
- package/lib/componentsv2/element/engine.ts +86 -29
- package/lib/componentsv2/element/skin.d.ts.map +1 -1
- package/lib/componentsv2/element/skin.js +7 -10
- package/lib/componentsv2/element/skin.js.map +1 -1
- package/lib/componentsv2/element/skin.ts +7 -11
- package/lib/componentsv2/grid/engine.d.ts +48 -3
- package/lib/componentsv2/grid/engine.d.ts.map +1 -1
- package/lib/componentsv2/grid/engine.js +109 -14
- package/lib/componentsv2/grid/engine.js.map +1 -1
- package/lib/componentsv2/grid/engine.ts +120 -16
- package/lib/componentsv2/input/engine.d.ts +48 -5
- package/lib/componentsv2/input/engine.d.ts.map +1 -1
- package/lib/componentsv2/input/engine.js +108 -15
- package/lib/componentsv2/input/engine.js.map +1 -1
- package/lib/componentsv2/input/engine.ts +119 -16
- package/lib/componentsv2/input/skin.d.ts.map +1 -1
- package/lib/componentsv2/input/skin.js +1 -4
- package/lib/componentsv2/input/skin.js.map +1 -1
- package/lib/componentsv2/input/skin.ts +1 -4
- package/lib/componentsv2/list/component.d.ts +28 -6
- package/lib/componentsv2/list/component.d.ts.map +1 -1
- package/lib/componentsv2/list/component.js +28 -6
- package/lib/componentsv2/list/component.js.map +1 -1
- package/lib/componentsv2/list/component.ts +28 -6
- package/lib/componentsv2/list/engine.d.ts +61 -9
- package/lib/componentsv2/list/engine.d.ts.map +1 -1
- package/lib/componentsv2/list/engine.js +156 -95
- package/lib/componentsv2/list/engine.js.map +1 -1
- package/lib/componentsv2/list/engine.ts +175 -108
- package/machinery/build3.js +21 -0
- package/machinery/compiler3.js +638 -0
- package/machinery/serve.js +255 -0
- package/machinery/watcher.js +53 -64
- package/package.json +11 -3
- package/lib/componentsv2/index.d.ts +0 -41
- package/lib/componentsv2/index.d.ts.map +0 -1
- package/lib/componentsv2/index.js +0 -223
- package/lib/componentsv2/index.js.map +0 -1
- package/lib/componentsv2/index.ts +0 -256
- package/lib/componentsv2/juxerror/component.d.ts +0 -28
- package/lib/componentsv2/juxerror/component.d.ts.map +0 -1
- package/lib/componentsv2/juxerror/component.js +0 -101
- package/lib/componentsv2/juxerror/component.js.map +0 -1
- package/lib/componentsv2/juxerror/component.ts +0 -125
- package/lib/componentsv2/juxerror/engine.d.ts +0 -35
- package/lib/componentsv2/juxerror/engine.d.ts.map +0 -1
- package/lib/componentsv2/juxerror/engine.js +0 -190
- package/lib/componentsv2/juxerror/engine.js.map +0 -1
- package/lib/componentsv2/juxerror/engine.ts +0 -241
- package/lib/componentsv2/juxerror/skin.d.ts +0 -11
- package/lib/componentsv2/juxerror/skin.d.ts.map +0 -1
- package/lib/componentsv2/juxerror/skin.js +0 -180
- package/lib/componentsv2/juxerror/skin.js.map +0 -1
- package/lib/componentsv2/juxerror/skin.ts +0 -200
- package/lib/componentsv2/juxerror/structure.css +0 -351
- package/machinery/ast.js +0 -347
- package/machinery/compiler.js +0 -706
- package/machinery/diagnose.js +0 -72
- package/machinery/doc-generator.js +0 -136
- package/machinery/imports.js +0 -155
- package/machinery/jux-module-pattern.md +0 -118
- package/machinery/server.js +0 -86
- package/machinery/ts-shim.js +0 -46
- package/machinery/verifier.js +0 -135
- package/tests/dropdown-test.js +0 -25
- package/tests/juxerrors/bad_syntax.jux +0 -8
- package/tests/juxerrors/ghost_dep.jux +0 -10
- package/tests/server_plugin_test.ts +0 -191
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates user-provided options against a defined contract schema.
|
|
3
|
+
* Emits warnings for unknown/misnamed options and errors for type mismatches.
|
|
4
|
+
*/
|
|
5
|
+
export function validateOptions(componentName, userOptions, schema, debugMode = false) {
|
|
6
|
+
const result = {
|
|
7
|
+
valid: true,
|
|
8
|
+
warnings: [],
|
|
9
|
+
errors: [],
|
|
10
|
+
normalized: {}
|
|
11
|
+
};
|
|
12
|
+
const validKeys = new Set(Object.keys(schema));
|
|
13
|
+
const aliasMap = new Map();
|
|
14
|
+
// Build alias lookup
|
|
15
|
+
for (const [key, def] of Object.entries(schema)) {
|
|
16
|
+
if (def.aliases) {
|
|
17
|
+
def.aliases.forEach(alias => aliasMap.set(alias.toLowerCase(), key));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// Check for unknown or aliased options
|
|
21
|
+
for (const [key, value] of Object.entries(userOptions)) {
|
|
22
|
+
const lowerKey = key.toLowerCase();
|
|
23
|
+
if (validKeys.has(key)) {
|
|
24
|
+
// Valid key - validate type
|
|
25
|
+
const def = schema[key];
|
|
26
|
+
if (!validateType(value, def.type)) {
|
|
27
|
+
result.errors.push(`[${componentName}] Option "${key}" expects type "${def.type}", got "${typeof value}".`);
|
|
28
|
+
result.valid = false;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
result.normalized[key] = value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else if (aliasMap.has(lowerKey)) {
|
|
35
|
+
// Found an alias - warn and normalize
|
|
36
|
+
const correctKey = aliasMap.get(lowerKey);
|
|
37
|
+
result.warnings.push(`[${componentName}] Option "${key}" is not valid. Did you mean "${correctKey}"?`);
|
|
38
|
+
result.normalized[correctKey] = value;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Unknown option
|
|
42
|
+
const suggestion = findClosestMatch(key, Array.from(validKeys));
|
|
43
|
+
const hint = suggestion ? ` Did you mean "${suggestion}"?` : '';
|
|
44
|
+
result.warnings.push(`[${componentName}] Unknown option "${key}".${hint} Valid options: ${Array.from(validKeys).join(', ')}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Apply defaults for missing required options
|
|
48
|
+
for (const [key, def] of Object.entries(schema)) {
|
|
49
|
+
if (!(key in result.normalized)) {
|
|
50
|
+
if (def.required && def.default === undefined) {
|
|
51
|
+
result.errors.push(`[${componentName}] Required option "${key}" is missing.`);
|
|
52
|
+
result.valid = false;
|
|
53
|
+
}
|
|
54
|
+
else if (def.default !== undefined) {
|
|
55
|
+
result.normalized[key] = def.default;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Log warnings/errors in debug mode
|
|
60
|
+
if (debugMode || result.warnings.length || result.errors.length) {
|
|
61
|
+
result.warnings.forEach(w => console.warn(w));
|
|
62
|
+
result.errors.forEach(e => console.error(e));
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
function validateType(value, expectedType) {
|
|
67
|
+
if (value === undefined || value === null)
|
|
68
|
+
return true; // Allow optional
|
|
69
|
+
switch (expectedType) {
|
|
70
|
+
case 'string': return typeof value === 'string';
|
|
71
|
+
case 'number': return typeof value === 'number';
|
|
72
|
+
case 'boolean': return typeof value === 'boolean';
|
|
73
|
+
case 'array': return Array.isArray(value);
|
|
74
|
+
case 'object': return typeof value === 'object' && !Array.isArray(value);
|
|
75
|
+
case 'function': return typeof value === 'function';
|
|
76
|
+
default: return true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function findClosestMatch(input, candidates) {
|
|
80
|
+
const lower = input.toLowerCase();
|
|
81
|
+
let best = null;
|
|
82
|
+
let bestScore = Infinity;
|
|
83
|
+
for (const candidate of candidates) {
|
|
84
|
+
const score = levenshtein(lower, candidate.toLowerCase());
|
|
85
|
+
if (score < bestScore && score <= 3) { // Max 3 edits
|
|
86
|
+
bestScore = score;
|
|
87
|
+
best = candidate;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return best;
|
|
91
|
+
}
|
|
92
|
+
function levenshtein(a, b) {
|
|
93
|
+
const matrix = [];
|
|
94
|
+
for (let i = 0; i <= b.length; i++)
|
|
95
|
+
matrix[i] = [i];
|
|
96
|
+
for (let j = 0; j <= a.length; j++)
|
|
97
|
+
matrix[0][j] = j;
|
|
98
|
+
for (let i = 1; i <= b.length; i++) {
|
|
99
|
+
for (let j = 1; j <= a.length; j++) {
|
|
100
|
+
matrix[i][j] = b[i - 1] === a[j - 1]
|
|
101
|
+
? matrix[i - 1][j - 1]
|
|
102
|
+
: Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return matrix[b.length][a.length];
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=OptionsContract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OptionsContract.js","sourceRoot":"","sources":["OptionsContract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export interface OptionDefinition {
|
|
2
|
+
type: 'string' | 'number' | 'boolean' | 'array' | 'object' | 'function';
|
|
3
|
+
required?: boolean;
|
|
4
|
+
default?: any;
|
|
5
|
+
description?: string;
|
|
6
|
+
aliases?: string[]; // Common misspellings or alternate names
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type OptionsContractSchema = Record<string, OptionDefinition>;
|
|
10
|
+
|
|
11
|
+
export interface ValidationResult {
|
|
12
|
+
valid: boolean;
|
|
13
|
+
warnings: string[];
|
|
14
|
+
errors: string[];
|
|
15
|
+
normalized: Record<string, any>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Validates user-provided options against a defined contract schema.
|
|
20
|
+
* Emits warnings for unknown/misnamed options and errors for type mismatches.
|
|
21
|
+
*/
|
|
22
|
+
export function validateOptions<T extends Record<string, any>>(
|
|
23
|
+
componentName: string,
|
|
24
|
+
userOptions: Record<string, any>,
|
|
25
|
+
schema: OptionsContractSchema,
|
|
26
|
+
debugMode: boolean = false
|
|
27
|
+
): ValidationResult {
|
|
28
|
+
const result: ValidationResult = {
|
|
29
|
+
valid: true,
|
|
30
|
+
warnings: [],
|
|
31
|
+
errors: [],
|
|
32
|
+
normalized: {}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const validKeys = new Set(Object.keys(schema));
|
|
36
|
+
const aliasMap = new Map<string, string>();
|
|
37
|
+
|
|
38
|
+
// Build alias lookup
|
|
39
|
+
for (const [key, def] of Object.entries(schema)) {
|
|
40
|
+
if (def.aliases) {
|
|
41
|
+
def.aliases.forEach(alias => aliasMap.set(alias.toLowerCase(), key));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check for unknown or aliased options
|
|
46
|
+
for (const [key, value] of Object.entries(userOptions)) {
|
|
47
|
+
const lowerKey = key.toLowerCase();
|
|
48
|
+
|
|
49
|
+
if (validKeys.has(key)) {
|
|
50
|
+
// Valid key - validate type
|
|
51
|
+
const def = schema[key];
|
|
52
|
+
if (!validateType(value, def.type)) {
|
|
53
|
+
result.errors.push(
|
|
54
|
+
`[${componentName}] Option "${key}" expects type "${def.type}", got "${typeof value}".`
|
|
55
|
+
);
|
|
56
|
+
result.valid = false;
|
|
57
|
+
} else {
|
|
58
|
+
result.normalized[key] = value;
|
|
59
|
+
}
|
|
60
|
+
} else if (aliasMap.has(lowerKey)) {
|
|
61
|
+
// Found an alias - warn and normalize
|
|
62
|
+
const correctKey = aliasMap.get(lowerKey)!;
|
|
63
|
+
result.warnings.push(
|
|
64
|
+
`[${componentName}] Option "${key}" is not valid. Did you mean "${correctKey}"?`
|
|
65
|
+
);
|
|
66
|
+
result.normalized[correctKey] = value;
|
|
67
|
+
} else {
|
|
68
|
+
// Unknown option
|
|
69
|
+
const suggestion = findClosestMatch(key, Array.from(validKeys));
|
|
70
|
+
const hint = suggestion ? ` Did you mean "${suggestion}"?` : '';
|
|
71
|
+
result.warnings.push(
|
|
72
|
+
`[${componentName}] Unknown option "${key}".${hint} Valid options: ${Array.from(validKeys).join(', ')}`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Apply defaults for missing required options
|
|
78
|
+
for (const [key, def] of Object.entries(schema)) {
|
|
79
|
+
if (!(key in result.normalized)) {
|
|
80
|
+
if (def.required && def.default === undefined) {
|
|
81
|
+
result.errors.push(`[${componentName}] Required option "${key}" is missing.`);
|
|
82
|
+
result.valid = false;
|
|
83
|
+
} else if (def.default !== undefined) {
|
|
84
|
+
result.normalized[key] = def.default;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Log warnings/errors in debug mode
|
|
90
|
+
if (debugMode || result.warnings.length || result.errors.length) {
|
|
91
|
+
result.warnings.forEach(w => console.warn(w));
|
|
92
|
+
result.errors.forEach(e => console.error(e));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function validateType(value: any, expectedType: string): boolean {
|
|
99
|
+
if (value === undefined || value === null) return true; // Allow optional
|
|
100
|
+
switch (expectedType) {
|
|
101
|
+
case 'string': return typeof value === 'string';
|
|
102
|
+
case 'number': return typeof value === 'number';
|
|
103
|
+
case 'boolean': return typeof value === 'boolean';
|
|
104
|
+
case 'array': return Array.isArray(value);
|
|
105
|
+
case 'object': return typeof value === 'object' && !Array.isArray(value);
|
|
106
|
+
case 'function': return typeof value === 'function';
|
|
107
|
+
default: return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function findClosestMatch(input: string, candidates: string[]): string | null {
|
|
112
|
+
const lower = input.toLowerCase();
|
|
113
|
+
let best: string | null = null;
|
|
114
|
+
let bestScore = Infinity;
|
|
115
|
+
|
|
116
|
+
for (const candidate of candidates) {
|
|
117
|
+
const score = levenshtein(lower, candidate.toLowerCase());
|
|
118
|
+
if (score < bestScore && score <= 3) { // Max 3 edits
|
|
119
|
+
bestScore = score;
|
|
120
|
+
best = candidate;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return best;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function levenshtein(a: string, b: string): number {
|
|
127
|
+
const matrix: number[][] = [];
|
|
128
|
+
for (let i = 0; i <= b.length; i++) matrix[i] = [i];
|
|
129
|
+
for (let j = 0; j <= a.length; j++) matrix[0][j] = j;
|
|
130
|
+
|
|
131
|
+
for (let i = 1; i <= b.length; i++) {
|
|
132
|
+
for (let j = 1; j <= a.length; j++) {
|
|
133
|
+
matrix[i][j] = b[i - 1] === a[j - 1]
|
|
134
|
+
? matrix[i - 1][j - 1]
|
|
135
|
+
: Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return matrix[b.length][a.length];
|
|
139
|
+
}
|
|
@@ -3,5 +3,27 @@ export type ElementComponent = ElementEngine & {
|
|
|
3
3
|
render: (targetId: string | HTMLElement) => ElementComponent;
|
|
4
4
|
injectCSS: (id: string, cssContent: string) => void;
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* OPTIONS CONTRACT for Element:
|
|
8
|
+
*
|
|
9
|
+
* | Option | Type | Default | Aliases |
|
|
10
|
+
* |--------------|--------|---------|----------------------------------|
|
|
11
|
+
* | tagName | string | 'div' | tag, element, type |
|
|
12
|
+
* | content | string | '' | text, html, innerHTML, value |
|
|
13
|
+
* | contentType | string | 'text' | type, mode |
|
|
14
|
+
* | inlineStyle | string | '' | style, css, styles |
|
|
15
|
+
*
|
|
16
|
+
* METHODS (match state properties):
|
|
17
|
+
* - .tagName(value) - Set HTML tag
|
|
18
|
+
* - .content(value, type) - Set content with type
|
|
19
|
+
* - .contentType(type) - Set content type
|
|
20
|
+
* - .inlineStyle(css) - Set inline styles
|
|
21
|
+
*
|
|
22
|
+
* CONVENIENCE ALIASES:
|
|
23
|
+
* - .tag(value) → .tagName(value)
|
|
24
|
+
* - .text(value) → .content(value, 'text')
|
|
25
|
+
* - .html(value) → .content(value, 'html')
|
|
26
|
+
* - .style(css) → .inlineStyle(css)
|
|
27
|
+
*/
|
|
6
28
|
export declare function Element(id: string, options?: ElementOptions): ElementComponent;
|
|
7
29
|
//# sourceMappingURL=component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG5D,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG;IAC3C,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,KAAK,gBAAgB,CAAC;IAC7D,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD,CAAC;AAEF,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,gBAAgB,CAuBlF"}
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG5D,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG;IAC3C,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,KAAK,gBAAgB,CAAC;IAC7D,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,gBAAgB,CAuBlF"}
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import { ElementEngine } from './engine.js';
|
|
2
2
|
import { ElementSkin } from './skin.js';
|
|
3
|
+
/**
|
|
4
|
+
* OPTIONS CONTRACT for Element:
|
|
5
|
+
*
|
|
6
|
+
* | Option | Type | Default | Aliases |
|
|
7
|
+
* |--------------|--------|---------|----------------------------------|
|
|
8
|
+
* | tagName | string | 'div' | tag, element, type |
|
|
9
|
+
* | content | string | '' | text, html, innerHTML, value |
|
|
10
|
+
* | contentType | string | 'text' | type, mode |
|
|
11
|
+
* | inlineStyle | string | '' | style, css, styles |
|
|
12
|
+
*
|
|
13
|
+
* METHODS (match state properties):
|
|
14
|
+
* - .tagName(value) - Set HTML tag
|
|
15
|
+
* - .content(value, type) - Set content with type
|
|
16
|
+
* - .contentType(type) - Set content type
|
|
17
|
+
* - .inlineStyle(css) - Set inline styles
|
|
18
|
+
*
|
|
19
|
+
* CONVENIENCE ALIASES:
|
|
20
|
+
* - .tag(value) → .tagName(value)
|
|
21
|
+
* - .text(value) → .content(value, 'text')
|
|
22
|
+
* - .html(value) → .content(value, 'html')
|
|
23
|
+
* - .style(css) → .inlineStyle(css)
|
|
24
|
+
*/
|
|
3
25
|
export function Element(id, options = {}) {
|
|
4
26
|
const engine = new ElementEngine(id, options);
|
|
5
27
|
if (typeof window !== 'undefined') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","sourceRoot":"","sources":["component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAOxC,MAAM,UAAU,OAAO,CAAC,EAAU,EAAE,UAA0B,EAAE;IAC5D,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAE9C,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,aAAa;QACb,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QAC5C,aAAa;QACb,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;IACnC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IAErC,aAAa;IACb,MAAM,CAAC,MAAM,GAAG,CAAC,QAA8B,EAAE,EAAE;QAC/C,MAAM,MAAM,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC3F,IAAI,MAAM;YAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,MAA0B,CAAC;IACtC,CAAC,CAAC;IAEF,aAAa;IACb,MAAM,CAAC,SAAS,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"component.js","sourceRoot":"","sources":["component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAOxC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,OAAO,CAAC,EAAU,EAAE,UAA0B,EAAE;IAC5D,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAE9C,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,aAAa;QACb,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QAC5C,aAAa;QACb,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC;IACnC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IAErC,aAAa;IACb,MAAM,CAAC,MAAM,GAAG,CAAC,QAA8B,EAAE,EAAE;QAC/C,MAAM,MAAM,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC3F,IAAI,MAAM;YAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,MAA0B,CAAC;IACtC,CAAC,CAAC;IAEF,aAAa;IACb,MAAM,CAAC,SAAS,GAAG,CAAC,EAAU,EAAE,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAExE,OAAO,MAA0B,CAAC;AACtC,CAAC"}
|
|
@@ -6,6 +6,28 @@ export type ElementComponent = ElementEngine & {
|
|
|
6
6
|
injectCSS: (id: string, cssContent: string) => void;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* OPTIONS CONTRACT for Element:
|
|
11
|
+
*
|
|
12
|
+
* | Option | Type | Default | Aliases |
|
|
13
|
+
* |--------------|--------|---------|----------------------------------|
|
|
14
|
+
* | tagName | string | 'div' | tag, element, type |
|
|
15
|
+
* | content | string | '' | text, html, innerHTML, value |
|
|
16
|
+
* | contentType | string | 'text' | type, mode |
|
|
17
|
+
* | inlineStyle | string | '' | style, css, styles |
|
|
18
|
+
*
|
|
19
|
+
* METHODS (match state properties):
|
|
20
|
+
* - .tagName(value) - Set HTML tag
|
|
21
|
+
* - .content(value, type) - Set content with type
|
|
22
|
+
* - .contentType(type) - Set content type
|
|
23
|
+
* - .inlineStyle(css) - Set inline styles
|
|
24
|
+
*
|
|
25
|
+
* CONVENIENCE ALIASES:
|
|
26
|
+
* - .tag(value) → .tagName(value)
|
|
27
|
+
* - .text(value) → .content(value, 'text')
|
|
28
|
+
* - .html(value) → .content(value, 'html')
|
|
29
|
+
* - .style(css) → .inlineStyle(css)
|
|
30
|
+
*/
|
|
9
31
|
export function Element(id: string, options: ElementOptions = {}): ElementComponent {
|
|
10
32
|
const engine = new ElementEngine(id, options);
|
|
11
33
|
|
|
@@ -26,7 +48,7 @@ export function Element(id: string, options: ElementOptions = {}): ElementCompon
|
|
|
26
48
|
};
|
|
27
49
|
|
|
28
50
|
// @ts-ignore
|
|
29
|
-
engine.injectCSS = (id, css) => skin.injectCSS(id, css);
|
|
51
|
+
engine.injectCSS = (id: string, css: string) => skin.injectCSS(id, css);
|
|
30
52
|
|
|
31
53
|
return engine as ElementComponent;
|
|
32
54
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseEngine, BaseState } from '../base/BaseEngine.js';
|
|
2
|
+
import { OptionsContractSchema } from '../base/OptionsContract.js';
|
|
2
3
|
export interface ElementState extends BaseState {
|
|
3
4
|
tagName: string;
|
|
4
5
|
content: string | null;
|
|
@@ -6,37 +7,53 @@ export interface ElementState extends BaseState {
|
|
|
6
7
|
inlineStyle: string;
|
|
7
8
|
}
|
|
8
9
|
export interface ElementOptions {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
tagName?: string;
|
|
11
|
+
content?: string;
|
|
12
|
+
contentType?: 'text' | 'html';
|
|
13
|
+
inlineStyle?: string;
|
|
13
14
|
}
|
|
14
15
|
export declare class ElementEngine extends BaseEngine<ElementState, ElementOptions> {
|
|
15
16
|
constructor(id: string, options?: ElementOptions);
|
|
17
|
+
/**
|
|
18
|
+
* OPTIONS CONTRACT
|
|
19
|
+
* Defines valid options with types, defaults, and aliases for common mistakes.
|
|
20
|
+
*/
|
|
21
|
+
protected get optionsSchema(): OptionsContractSchema;
|
|
16
22
|
protected prepareState(id: string, options: ElementOptions): ElementState;
|
|
17
23
|
/**
|
|
18
|
-
* Set the HTML
|
|
24
|
+
* Set the HTML tag name (e.g., 'div', 'span', 'h1', 'section')
|
|
25
|
+
* Method name matches state property: tagName
|
|
19
26
|
*/
|
|
20
|
-
|
|
27
|
+
tagName(value: string): this;
|
|
21
28
|
/**
|
|
22
|
-
* Set
|
|
29
|
+
* Set content with explicit type
|
|
30
|
+
* Method name matches state property: content
|
|
23
31
|
*/
|
|
24
|
-
|
|
32
|
+
content(value: string, type?: 'text' | 'html'): this;
|
|
33
|
+
/**
|
|
34
|
+
* Set content type
|
|
35
|
+
* Method name matches state property: contentType
|
|
36
|
+
*/
|
|
37
|
+
contentType(type: 'text' | 'html'): this;
|
|
25
38
|
/**
|
|
26
|
-
* Set
|
|
39
|
+
* Set inline styles (e.g., "color: red; margin: 10px;")
|
|
40
|
+
* Method name matches state property: inlineStyle
|
|
27
41
|
*/
|
|
42
|
+
inlineStyle(cssText: string): this;
|
|
43
|
+
/** @alias for tagName() */
|
|
44
|
+
tag(value: string): this;
|
|
45
|
+
/** @alias for content(value, 'text') */
|
|
46
|
+
text(value: string): this;
|
|
47
|
+
/** @alias for content(value, 'html') */
|
|
28
48
|
html(value: string): this;
|
|
49
|
+
/** @alias for inlineStyle() */
|
|
50
|
+
style(cssText: string): this;
|
|
29
51
|
/**
|
|
30
52
|
* Append raw HTML to existing content
|
|
31
53
|
*/
|
|
32
54
|
appendHtml(value: string): this;
|
|
33
|
-
/**
|
|
34
|
-
* Set inline styles (e.g. "color: red; margin: 10px;")
|
|
35
|
-
*/
|
|
36
|
-
style(cssText: string): this;
|
|
37
55
|
/**
|
|
38
56
|
* Receives RAW DOM events from the Skin and emits them to listeners.
|
|
39
|
-
* This keeps the 'emit' logic encapsulated within the Engine.
|
|
40
57
|
*/
|
|
41
58
|
handleEvent(eventName: string, content: any): void;
|
|
42
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,aAAc,SAAQ,UAAU,CAAC,YAAY,EAAE,cAAc,CAAC;gBAC3D,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB;IAIpD;;;OAGG;IACH,SAAS,KAAK,aAAa,IAAI,qBAAqB,CA2BnD;IAED,SAAS,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,YAAY;IAezE;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM5B;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,GAAG,MAAe,GAAG,IAAI;IAK5D;;;OAGG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAKxC;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAOlC,2BAA2B;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIxB,wCAAwC;IACxC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIzB,wCAAwC;IACxC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIzB,+BAA+B;IAC/B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM/B;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI;CAGrD"}
|
|
@@ -3,6 +3,38 @@ export class ElementEngine extends BaseEngine {
|
|
|
3
3
|
constructor(id, options = {}) {
|
|
4
4
|
super(id, options);
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* OPTIONS CONTRACT
|
|
8
|
+
* Defines valid options with types, defaults, and aliases for common mistakes.
|
|
9
|
+
*/
|
|
10
|
+
get optionsSchema() {
|
|
11
|
+
return {
|
|
12
|
+
tagName: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
default: 'div',
|
|
15
|
+
description: 'HTML tag name (e.g., "div", "span", "h1")',
|
|
16
|
+
aliases: ['tag', 'element', 'type']
|
|
17
|
+
},
|
|
18
|
+
content: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
default: '',
|
|
21
|
+
description: 'Text or HTML content',
|
|
22
|
+
aliases: ['text', 'html', 'innerHTML', 'textContent', 'value']
|
|
23
|
+
},
|
|
24
|
+
contentType: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
default: 'text',
|
|
27
|
+
description: 'Content type: "text" (escaped) or "html" (raw)',
|
|
28
|
+
aliases: ['type', 'mode']
|
|
29
|
+
},
|
|
30
|
+
inlineStyle: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
default: '',
|
|
33
|
+
description: 'Inline CSS styles (e.g., "color: red;")',
|
|
34
|
+
aliases: ['style', 'css', 'styles']
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
6
38
|
prepareState(id, options) {
|
|
7
39
|
return {
|
|
8
40
|
id,
|
|
@@ -11,53 +43,72 @@ export class ElementEngine extends BaseEngine {
|
|
|
11
43
|
disabled: false,
|
|
12
44
|
loading: false,
|
|
13
45
|
attributes: {},
|
|
14
|
-
tagName: options.
|
|
15
|
-
content: options.
|
|
16
|
-
contentType: options.
|
|
17
|
-
inlineStyle: options.
|
|
46
|
+
tagName: options.tagName || 'div',
|
|
47
|
+
content: options.content || '',
|
|
48
|
+
contentType: options.contentType || 'text',
|
|
49
|
+
inlineStyle: options.inlineStyle || ''
|
|
18
50
|
};
|
|
19
51
|
}
|
|
20
52
|
/**
|
|
21
|
-
* Set the HTML
|
|
53
|
+
* Set the HTML tag name (e.g., 'div', 'span', 'h1', 'section')
|
|
54
|
+
* Method name matches state property: tagName
|
|
22
55
|
*/
|
|
23
|
-
|
|
24
|
-
this.updateState({ tagName });
|
|
25
|
-
this.emit('config', { tagName });
|
|
56
|
+
tagName(value) {
|
|
57
|
+
this.updateState({ tagName: value });
|
|
58
|
+
this.emit('config', { tagName: value });
|
|
26
59
|
return this;
|
|
27
60
|
}
|
|
28
61
|
/**
|
|
29
|
-
* Set
|
|
62
|
+
* Set content with explicit type
|
|
63
|
+
* Method name matches state property: content
|
|
30
64
|
*/
|
|
31
|
-
|
|
32
|
-
this.updateState({ content: value, contentType:
|
|
33
|
-
// No emit needed, state update triggers paint
|
|
65
|
+
content(value, type = 'text') {
|
|
66
|
+
this.updateState({ content: value, contentType: type });
|
|
34
67
|
return this;
|
|
35
68
|
}
|
|
36
69
|
/**
|
|
37
|
-
* Set
|
|
70
|
+
* Set content type
|
|
71
|
+
* Method name matches state property: contentType
|
|
38
72
|
*/
|
|
39
|
-
|
|
40
|
-
this.updateState({
|
|
73
|
+
contentType(type) {
|
|
74
|
+
this.updateState({ contentType: type });
|
|
41
75
|
return this;
|
|
42
76
|
}
|
|
43
77
|
/**
|
|
44
|
-
*
|
|
78
|
+
* Set inline styles (e.g., "color: red; margin: 10px;")
|
|
79
|
+
* Method name matches state property: inlineStyle
|
|
45
80
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.updateState({ content: current + value, contentType: 'html' });
|
|
81
|
+
inlineStyle(cssText) {
|
|
82
|
+
this.updateState({ inlineStyle: cssText });
|
|
49
83
|
return this;
|
|
50
84
|
}
|
|
85
|
+
// --- Convenience Aliases (documented as such) ---
|
|
86
|
+
/** @alias for tagName() */
|
|
87
|
+
tag(value) {
|
|
88
|
+
return this.tagName(value);
|
|
89
|
+
}
|
|
90
|
+
/** @alias for content(value, 'text') */
|
|
91
|
+
text(value) {
|
|
92
|
+
return this.content(value, 'text');
|
|
93
|
+
}
|
|
94
|
+
/** @alias for content(value, 'html') */
|
|
95
|
+
html(value) {
|
|
96
|
+
return this.content(value, 'html');
|
|
97
|
+
}
|
|
98
|
+
/** @alias for inlineStyle() */
|
|
99
|
+
style(cssText) {
|
|
100
|
+
return this.inlineStyle(cssText);
|
|
101
|
+
}
|
|
51
102
|
/**
|
|
52
|
-
*
|
|
103
|
+
* Append raw HTML to existing content
|
|
53
104
|
*/
|
|
54
|
-
|
|
55
|
-
this.
|
|
105
|
+
appendHtml(value) {
|
|
106
|
+
const current = this.state.content || '';
|
|
107
|
+
this.updateState({ content: current + value, contentType: 'html' });
|
|
56
108
|
return this;
|
|
57
109
|
}
|
|
58
110
|
/**
|
|
59
111
|
* Receives RAW DOM events from the Skin and emits them to listeners.
|
|
60
|
-
* This keeps the 'emit' logic encapsulated within the Engine.
|
|
61
112
|
*/
|
|
62
113
|
handleEvent(eventName, content) {
|
|
63
114
|
this.emit(eventName, content);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,uBAAuB,CAAC;AAiB9D,MAAM,OAAO,aAAc,SAAQ,UAAwC;IACvE,YAAY,EAAU,EAAE,UAA0B,EAAE;QAChD,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACvB,CAAC;IAES,YAAY,CAAC,EAAU,EAAE,OAAuB;QACtD,OAAO;YACH,EAAE;YACF,OAAO,EAAE,CAAC,aAAa,CAAC;YACxB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,KAAK;YACf,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,EAAE;YACd,OAAO,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["engine.ts"],"names":[],"mappings":"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"}
|