@openwebf/webf 0.23.2 → 0.23.7
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/README.md +5 -1
- package/bin/webf.js +1 -0
- package/dist/analyzer.js +65 -1
- package/dist/commands.js +198 -98
- package/dist/dart.js +91 -25
- package/dist/declaration.js +1 -0
- package/dist/generator.js +26 -17
- package/dist/react.js +272 -25
- package/dist/vue.js +74 -11
- package/package.json +1 -1
- package/src/analyzer.ts +58 -2
- package/src/commands.ts +300 -196
- package/src/dart.ts +95 -20
- package/src/declaration.ts +1 -0
- package/src/generator.ts +24 -16
- package/src/react.ts +288 -29
- package/src/vue.ts +85 -13
- package/templates/class.dart.tpl +1 -1
- package/templates/vue.components.d.ts.tpl +2 -0
- package/test/commands.test.ts +82 -2
- package/test/dart-nullable-props.test.ts +58 -0
- package/test/react-consts.test.ts +1 -1
- package/test/react-vue-nullable-props.test.ts +66 -0
- package/test/react.test.ts +46 -4
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { analyzer, clearCaches, UnionTypeCollector, ParameterType } from '../src/analyzer';
|
|
2
|
+
import { generateDartClass } from '../src/dart';
|
|
3
|
+
import { IDLBlob } from '../src/IDLBlob';
|
|
4
|
+
|
|
5
|
+
describe('Dart nullable union properties', () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
clearCaches();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('handles boolean | null properties and maps "null" attribute to null', () => {
|
|
11
|
+
const tsContent = `
|
|
12
|
+
interface FlutterCupertinoCheckboxProperties {
|
|
13
|
+
/**
|
|
14
|
+
* Whether the checkbox is checked.
|
|
15
|
+
* Default: false.
|
|
16
|
+
*/
|
|
17
|
+
checked?: boolean | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface FlutterCupertinoCheckboxEvents {
|
|
21
|
+
/**
|
|
22
|
+
* Fired when the checkbox value changes.
|
|
23
|
+
*/
|
|
24
|
+
change: CustomEvent<boolean>;
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
const blob = new IDLBlob('checkbox.d.ts', 'dist', 'checkbox', 'implement');
|
|
29
|
+
blob.raw = tsContent;
|
|
30
|
+
|
|
31
|
+
const definedPropertyCollector = {
|
|
32
|
+
properties: new Set<string>(),
|
|
33
|
+
files: new Set<string>(),
|
|
34
|
+
interfaces: new Set<string>(),
|
|
35
|
+
};
|
|
36
|
+
const unionTypeCollector: UnionTypeCollector = { types: new Set<ParameterType[]>() };
|
|
37
|
+
|
|
38
|
+
analyzer(blob, definedPropertyCollector, unionTypeCollector);
|
|
39
|
+
|
|
40
|
+
const dartCode = generateDartClass(blob, 'test');
|
|
41
|
+
|
|
42
|
+
// Should generate bindings class for FlutterCupertinoCheckbox
|
|
43
|
+
expect(dartCode).toContain('abstract class FlutterCupertinoCheckboxBindings extends WidgetElement {');
|
|
44
|
+
|
|
45
|
+
// The checked property should be a nullable bool in Dart bindings.
|
|
46
|
+
expect(dartCode).toContain('bool? get checked;');
|
|
47
|
+
|
|
48
|
+
// Attribute setter should treat the literal "null" as a Dart null.
|
|
49
|
+
expect(dartCode).toContain(
|
|
50
|
+
"setter: (value) => checked = value == 'null' ? null : (value == 'true' || value == ''),"
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// Deleting the attribute should reset to the default `false`.
|
|
54
|
+
expect(dartCode).toContain(
|
|
55
|
+
"deleter: () => checked = false"
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -25,6 +25,6 @@ describe('React generator - declare const support', () => {
|
|
|
25
25
|
blob.objects = [eo as any];
|
|
26
26
|
|
|
27
27
|
const output = generateReactComponent(blob);
|
|
28
|
-
expect(output).toContain("export
|
|
28
|
+
expect(output).toContain("export enum CupertinoColors { 'red' = 0x0f, 'bbb' = 0x00 }");
|
|
29
29
|
});
|
|
30
30
|
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { analyzer, clearCaches, UnionTypeCollector, ParameterType } from '../src/analyzer';
|
|
2
|
+
import { generateReactComponent } from '../src/react';
|
|
3
|
+
import { generateVueTypings } from '../src/vue';
|
|
4
|
+
import { IDLBlob } from '../src/IDLBlob';
|
|
5
|
+
|
|
6
|
+
describe('React/Vue nullable union props', () => {
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
clearCaches();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const tsContent = `
|
|
12
|
+
interface FlutterCupertinoCheckboxProperties {
|
|
13
|
+
/**
|
|
14
|
+
* Whether the checkbox is checked.
|
|
15
|
+
* Default: false.
|
|
16
|
+
*/
|
|
17
|
+
checked?: boolean | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface FlutterCupertinoCheckboxEvents {
|
|
21
|
+
/**
|
|
22
|
+
* Fired when the checkbox value changes.
|
|
23
|
+
*/
|
|
24
|
+
change: CustomEvent<boolean>;
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
it('emits boolean | null for React props', () => {
|
|
29
|
+
const blob = new IDLBlob('checkbox.d.ts', 'dist', 'checkbox', 'implement');
|
|
30
|
+
blob.raw = tsContent;
|
|
31
|
+
|
|
32
|
+
const definedPropertyCollector = {
|
|
33
|
+
properties: new Set<string>(),
|
|
34
|
+
files: new Set<string>(),
|
|
35
|
+
interfaces: new Set<string>(),
|
|
36
|
+
};
|
|
37
|
+
const unionTypeCollector: UnionTypeCollector = { types: new Set<ParameterType[]>() };
|
|
38
|
+
|
|
39
|
+
analyzer(blob, definedPropertyCollector, unionTypeCollector);
|
|
40
|
+
|
|
41
|
+
const reactCode = generateReactComponent(blob);
|
|
42
|
+
|
|
43
|
+
// Prop should allow both undefined and null
|
|
44
|
+
expect(reactCode).toContain('checked?: boolean | null;');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('emits boolean | null for Vue props', () => {
|
|
48
|
+
const blob = new IDLBlob('checkbox.d.ts', 'dist', 'checkbox', 'implement');
|
|
49
|
+
blob.raw = tsContent;
|
|
50
|
+
|
|
51
|
+
const definedPropertyCollector = {
|
|
52
|
+
properties: new Set<string>(),
|
|
53
|
+
files: new Set<string>(),
|
|
54
|
+
interfaces: new Set<string>(),
|
|
55
|
+
};
|
|
56
|
+
const unionTypeCollector: UnionTypeCollector = { types: new Set<ParameterType[]>() };
|
|
57
|
+
|
|
58
|
+
analyzer(blob, definedPropertyCollector, unionTypeCollector);
|
|
59
|
+
|
|
60
|
+
const vueCode = generateVueTypings([blob]);
|
|
61
|
+
|
|
62
|
+
// Vue prop name is kebab-cased and should allow null explicitly
|
|
63
|
+
expect(vueCode).toContain(`'checked'?: boolean | null;`);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
package/test/react.test.ts
CHANGED
|
@@ -181,9 +181,9 @@ describe('React Generator', () => {
|
|
|
181
181
|
|
|
182
182
|
const result = generateReactComponent(blob);
|
|
183
183
|
|
|
184
|
-
// Should include custom props
|
|
185
|
-
expect(result).toContain('title: dom_string;');
|
|
186
|
-
expect(result).toContain('disabled?: boolean;');
|
|
184
|
+
// Should include custom props with generated TS types
|
|
185
|
+
expect(result).toContain('title: __webfTypes.dom_string;');
|
|
186
|
+
expect(result).toContain('disabled?: __webfTypes.boolean;');
|
|
187
187
|
|
|
188
188
|
// And still include standard HTML props
|
|
189
189
|
expect(result).toContain('id?: string;');
|
|
@@ -191,5 +191,47 @@ describe('React Generator', () => {
|
|
|
191
191
|
expect(result).toContain('children?: React.ReactNode;');
|
|
192
192
|
expect(result).toContain('className?: string;');
|
|
193
193
|
});
|
|
194
|
+
|
|
195
|
+
it('should preserve JSDoc for supporting option interfaces', () => {
|
|
196
|
+
const blob = new IDLBlob('/test/source', '/test/target', 'TestComponent', 'test', '');
|
|
197
|
+
|
|
198
|
+
const properties = new ClassObject();
|
|
199
|
+
properties.name = 'TestComponentProperties';
|
|
200
|
+
properties.kind = ClassObjectKind.interface;
|
|
201
|
+
|
|
202
|
+
const options = new ClassObject();
|
|
203
|
+
options.name = 'TestComponentOptions';
|
|
204
|
+
options.kind = ClassObjectKind.interface;
|
|
205
|
+
|
|
206
|
+
const titleProp = new PropsDeclaration();
|
|
207
|
+
titleProp.name = 'title';
|
|
208
|
+
titleProp.type = { value: 'string' } as any;
|
|
209
|
+
titleProp.optional = true;
|
|
210
|
+
titleProp.documentation = 'Optional override title for this show() call.';
|
|
211
|
+
titleProp.readonly = false;
|
|
212
|
+
titleProp.typeMode = {};
|
|
213
|
+
|
|
214
|
+
const messageProp = new PropsDeclaration();
|
|
215
|
+
messageProp.name = 'message';
|
|
216
|
+
messageProp.type = { value: 'string' } as any;
|
|
217
|
+
messageProp.optional = true;
|
|
218
|
+
messageProp.documentation = 'Optional override message for this show() call.';
|
|
219
|
+
messageProp.readonly = false;
|
|
220
|
+
messageProp.typeMode = {};
|
|
221
|
+
|
|
222
|
+
options.props = [titleProp, messageProp];
|
|
223
|
+
|
|
224
|
+
blob.objects = [properties, options];
|
|
225
|
+
|
|
226
|
+
const result = generateReactComponent(blob);
|
|
227
|
+
|
|
228
|
+
expect(result).toContain('interface TestComponentOptions');
|
|
229
|
+
expect(result).toMatch(
|
|
230
|
+
/interface TestComponentOptions[\s\S]*?\/\*\*[\s\S]*?Optional override title for this show\(\) call\.[\s\S]*?\*\/\s*\n\s*title\?:/
|
|
231
|
+
);
|
|
232
|
+
expect(result).toMatch(
|
|
233
|
+
/interface TestComponentOptions[\s\S]*?\/\*\*[\s\S]*?Optional override message for this show\(\) call\.[\s\S]*?\*\/\s*\n\s*message\?:/
|
|
234
|
+
);
|
|
235
|
+
});
|
|
194
236
|
});
|
|
195
|
-
});
|
|
237
|
+
});
|