@openwebf/webf 0.1.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 (60) hide show
  1. package/CLAUDE.md +206 -0
  2. package/README-zhCN.md +256 -0
  3. package/README.md +232 -0
  4. package/bin/webf.js +25 -0
  5. package/coverage/clover.xml +1295 -0
  6. package/coverage/coverage-final.json +12 -0
  7. package/coverage/lcov-report/IDLBlob.ts.html +142 -0
  8. package/coverage/lcov-report/analyzer.ts.html +2158 -0
  9. package/coverage/lcov-report/analyzer_original.ts.html +1450 -0
  10. package/coverage/lcov-report/base.css +224 -0
  11. package/coverage/lcov-report/block-navigation.js +87 -0
  12. package/coverage/lcov-report/commands.ts.html +700 -0
  13. package/coverage/lcov-report/dart.ts.html +490 -0
  14. package/coverage/lcov-report/declaration.ts.html +337 -0
  15. package/coverage/lcov-report/favicon.png +0 -0
  16. package/coverage/lcov-report/generator.ts.html +1171 -0
  17. package/coverage/lcov-report/index.html +266 -0
  18. package/coverage/lcov-report/logger.ts.html +424 -0
  19. package/coverage/lcov-report/prettify.css +1 -0
  20. package/coverage/lcov-report/prettify.js +2 -0
  21. package/coverage/lcov-report/react.ts.html +619 -0
  22. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  23. package/coverage/lcov-report/sorter.js +196 -0
  24. package/coverage/lcov-report/utils.ts.html +466 -0
  25. package/coverage/lcov-report/vue.ts.html +613 -0
  26. package/coverage/lcov.info +2149 -0
  27. package/global.d.ts +2 -0
  28. package/jest.config.js +24 -0
  29. package/package.json +36 -0
  30. package/src/IDLBlob.ts +20 -0
  31. package/src/analyzer.ts +692 -0
  32. package/src/commands.ts +645 -0
  33. package/src/dart.ts +170 -0
  34. package/src/declaration.ts +84 -0
  35. package/src/generator.ts +454 -0
  36. package/src/logger.ts +114 -0
  37. package/src/react.ts +186 -0
  38. package/src/utils.ts +127 -0
  39. package/src/vue.ts +176 -0
  40. package/templates/class.dart.tpl +86 -0
  41. package/templates/gitignore.tpl +2 -0
  42. package/templates/react.component.tsx.tpl +53 -0
  43. package/templates/react.createComponent.tpl +286 -0
  44. package/templates/react.index.ts.tpl +8 -0
  45. package/templates/react.package.json.tpl +26 -0
  46. package/templates/react.tsconfig.json.tpl +16 -0
  47. package/templates/react.tsup.config.ts.tpl +10 -0
  48. package/templates/tsconfig.json.tpl +8 -0
  49. package/templates/vue.component.partial.tpl +31 -0
  50. package/templates/vue.components.d.ts.tpl +49 -0
  51. package/templates/vue.package.json.tpl +11 -0
  52. package/templates/vue.tsconfig.json.tpl +15 -0
  53. package/test/IDLBlob.test.ts +75 -0
  54. package/test/analyzer.test.ts +370 -0
  55. package/test/commands.test.ts +1253 -0
  56. package/test/generator.test.ts +460 -0
  57. package/test/logger.test.ts +215 -0
  58. package/test/react.test.ts +49 -0
  59. package/test/utils.test.ts +316 -0
  60. package/tsconfig.json +30 -0
package/src/logger.ts ADDED
@@ -0,0 +1,114 @@
1
+ // Simplified logger without chalk dependency for now
2
+
3
+ export enum LogLevel {
4
+ DEBUG = 0,
5
+ INFO = 1,
6
+ WARN = 2,
7
+ ERROR = 3,
8
+ SILENT = 4
9
+ }
10
+
11
+ class Logger {
12
+ private logLevel: LogLevel = LogLevel.INFO;
13
+ private debugMode: boolean = false;
14
+
15
+ constructor() {
16
+ // Check for debug environment variable
17
+ this.debugMode = process.env.WEBF_DEBUG === 'true' || process.env.DEBUG === 'true';
18
+ if (this.debugMode) {
19
+ this.logLevel = LogLevel.DEBUG;
20
+ }
21
+ }
22
+
23
+ setLogLevel(level: LogLevel) {
24
+ this.logLevel = level;
25
+ }
26
+
27
+ debug(message: string, ...args: any[]) {
28
+ if (this.logLevel <= LogLevel.DEBUG) {
29
+ console.log(`[DEBUG] ${message}`, ...args);
30
+ }
31
+ }
32
+
33
+ info(message: string, ...args: any[]) {
34
+ if (this.logLevel <= LogLevel.INFO) {
35
+ console.log(`ℹ ${message}`, ...args);
36
+ }
37
+ }
38
+
39
+ success(message: string, ...args: any[]) {
40
+ if (this.logLevel <= LogLevel.INFO) {
41
+ console.log(`✓ ${message}`, ...args);
42
+ }
43
+ }
44
+
45
+ warn(message: string, ...args: any[]) {
46
+ if (this.logLevel <= LogLevel.WARN) {
47
+ console.warn(`⚠ ${message}`, ...args);
48
+ }
49
+ }
50
+
51
+ error(message: string, error?: Error | unknown) {
52
+ if (this.logLevel <= LogLevel.ERROR) {
53
+ console.error(`✗ ${message}`);
54
+ if (error) {
55
+ if (error instanceof Error) {
56
+ console.error(error.stack || error.message);
57
+ } else {
58
+ console.error(String(error));
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ group(title: string) {
65
+ if (this.logLevel <= LogLevel.INFO) {
66
+ console.log(`\n${title}`);
67
+ console.log('─'.repeat(title.length));
68
+ }
69
+ }
70
+
71
+ progress(current: number, total: number, message: string) {
72
+ if (this.logLevel <= LogLevel.INFO) {
73
+ const percentage = Math.round((current / total) * 100);
74
+ const progressBar = this.createProgressBar(percentage);
75
+ process.stdout.write(`\r${progressBar} ${percentage}% - ${message}`);
76
+ if (current === total) {
77
+ process.stdout.write('\n');
78
+ }
79
+ }
80
+ }
81
+
82
+ private createProgressBar(percentage: number): string {
83
+ const width = 20;
84
+ const filled = Math.round((percentage / 100) * width);
85
+ const empty = width - filled;
86
+ return `[${'█'.repeat(filled)}${'░'.repeat(empty)}]`;
87
+ }
88
+
89
+ time(label: string) {
90
+ if (this.logLevel <= LogLevel.DEBUG) {
91
+ console.time(`[TIMER] ${label}`);
92
+ }
93
+ }
94
+
95
+ timeEnd(label: string) {
96
+ if (this.logLevel <= LogLevel.DEBUG) {
97
+ console.timeEnd(`[TIMER] ${label}`);
98
+ }
99
+ }
100
+ }
101
+
102
+ // Export singleton instance
103
+ export const logger = new Logger();
104
+
105
+ // Export convenience functions
106
+ export const debug = logger.debug.bind(logger);
107
+ export const info = logger.info.bind(logger);
108
+ export const success = logger.success.bind(logger);
109
+ export const warn = logger.warn.bind(logger);
110
+ export const error = logger.error.bind(logger);
111
+ export const group = logger.group.bind(logger);
112
+ export const progress = logger.progress.bind(logger);
113
+ export const time = logger.time.bind(logger);
114
+ export const timeEnd = logger.timeEnd.bind(logger);
package/src/react.ts ADDED
@@ -0,0 +1,186 @@
1
+ import _ from "lodash";
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import {ParameterType} from "./analyzer";
5
+ import {ClassObject, FunctionArgumentType, FunctionDeclaration} from "./declaration";
6
+ import {IDLBlob} from "./IDLBlob";
7
+ import {getPointerType, isPointerType} from "./utils";
8
+
9
+ function readTemplate(name: string) {
10
+ return fs.readFileSync(path.join(__dirname, '../templates/' + name + '.tpl'), {encoding: 'utf-8'});
11
+ }
12
+
13
+ function generateReturnType(type: ParameterType) {
14
+ if (isPointerType(type)) {
15
+ const pointerType = getPointerType(type);
16
+ return pointerType;
17
+ }
18
+ if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
19
+ return `${getPointerType(type.value)}[]`;
20
+ }
21
+ switch (type.value) {
22
+ case FunctionArgumentType.int:
23
+ case FunctionArgumentType.double: {
24
+ return 'number';
25
+ }
26
+ case FunctionArgumentType.any: {
27
+ return 'any';
28
+ }
29
+ case FunctionArgumentType.boolean: {
30
+ return 'boolean';
31
+ }
32
+ case FunctionArgumentType.dom_string: {
33
+ return 'string';
34
+ }
35
+ case FunctionArgumentType.void:
36
+ return 'void';
37
+ default:
38
+ return 'void';
39
+ }
40
+ }
41
+
42
+ function generateEventHandlerType(type: ParameterType) {
43
+ if (!isPointerType(type)) {
44
+ throw new Error('Event type must be an instance of Event');
45
+ }
46
+ const pointerType = getPointerType(type);
47
+ if (pointerType === 'Event') {
48
+ return `EventHandler<SyntheticEvent<Element>>`;
49
+ }
50
+ if (pointerType === 'CustomEvent') {
51
+ return `EventHandler<SyntheticEvent<Element, CustomEvent>>`;
52
+ }
53
+ throw new Error('Unknown event type: ' + pointerType);
54
+ }
55
+
56
+ function generateMethodDeclaration(method: FunctionDeclaration) {
57
+ var methodName = method.name;
58
+ var args = method.args.map(arg => {
59
+ var argName = arg.name;
60
+ var argType = generateReturnType(arg.type);
61
+ return `${argName}: ${argType}`;
62
+ }).join(', ');
63
+ var returnType = generateReturnType(method.returnType);
64
+ return `${methodName}(${args}): ${returnType};`;
65
+ }
66
+
67
+ function toReactEventName(name: string) {
68
+ const eventName = 'on-' + name;
69
+ return _.camelCase(eventName);
70
+ }
71
+
72
+ export function generateReactComponent(blob: IDLBlob) {
73
+ const classObjects = blob.objects as ClassObject[];
74
+ const classObjectDictionary = Object.fromEntries(
75
+ classObjects.map(object => {
76
+ return [object.name, object];
77
+ })
78
+ );
79
+
80
+ const properties = classObjects.filter(object => {
81
+ return object.name.endsWith('Properties');
82
+ });
83
+ const events = classObjects.filter(object => {
84
+ return object.name.endsWith('Events');
85
+ });
86
+
87
+ const others = classObjects.filter(object => {
88
+ return !object.name.endsWith('Properties')
89
+ && !object.name.endsWith('Events');
90
+ });
91
+
92
+ const dependencies = others.map(object => {
93
+ const props = object.props.map(prop => {
94
+ if (prop.optional) {
95
+ return `${prop.name}?: ${generateReturnType(prop.type)};`;
96
+ }
97
+ return `${prop.name}: ${generateReturnType(prop.type)};`;
98
+ }).join('\n ');
99
+
100
+ return `
101
+ interface ${object.name} {
102
+ ${props}
103
+ }`;
104
+ }).join('\n\n');
105
+
106
+ const componentProperties = properties.length > 0 ? properties[0] : undefined;
107
+ const componentEvents = events.length > 0 ? events[0] : undefined;
108
+ const className = (() => {
109
+ if (componentProperties) {
110
+ return componentProperties.name.replace(/Properties$/, '');
111
+ }
112
+ if (componentEvents) {
113
+ return componentEvents.name.replace(/Events$/, '');
114
+ }
115
+ return '';
116
+ })();
117
+
118
+ if (!className) {
119
+ return '';
120
+ }
121
+
122
+ // Calculate the relative path from component location to utils
123
+ const componentDepth = blob.relativeDir ? blob.relativeDir.split(path.sep).length : 0;
124
+ const utilsPath = componentDepth > 0
125
+ ? '../'.repeat(componentDepth) + 'utils/createComponent'
126
+ : './utils/createComponent';
127
+
128
+ const content = _.template(readTemplate('react.component.tsx'))({
129
+ className: className,
130
+ properties: componentProperties,
131
+ events: componentEvents,
132
+ classObjectDictionary,
133
+ dependencies,
134
+ blob,
135
+ utilsPath,
136
+ toReactEventName,
137
+ generateReturnType,
138
+ generateMethodDeclaration,
139
+ generateEventHandlerType,
140
+ });
141
+
142
+ const result = content.split('\n').filter(str => {
143
+ return str.trim().length > 0;
144
+ }).join('\n');
145
+
146
+ return result;
147
+ }
148
+
149
+ export function generateReactIndex(blobs: IDLBlob[]) {
150
+ const components = blobs.map(blob => {
151
+ const classObjects = blob.objects as ClassObject[];
152
+
153
+ const properties = classObjects.filter(object => {
154
+ return object.name.endsWith('Properties');
155
+ });
156
+ const events = classObjects.filter(object => {
157
+ return object.name.endsWith('Events');
158
+ });
159
+
160
+ const componentProperties = properties.length > 0 ? properties[0] : undefined;
161
+ const componentEvents = events.length > 0 ? events[0] : undefined;
162
+ const className = (() => {
163
+ if (componentProperties) {
164
+ return componentProperties.name.replace(/Properties$/, '');
165
+ }
166
+ if (componentEvents) {
167
+ return componentEvents.name.replace(/Events$/, '');
168
+ }
169
+ return '';
170
+ })();
171
+ return {
172
+ className: className,
173
+ fileName: blob.filename,
174
+ relativeDir: blob.relativeDir,
175
+ }
176
+ }).filter(name => {
177
+ return name.className.length > 0;
178
+ });
179
+ const content = _.template(readTemplate('react.index.ts'))({
180
+ components,
181
+ });
182
+
183
+ return content.split('\n').filter(str => {
184
+ return str.trim().length > 0;
185
+ }).join('\n');
186
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,127 @@
1
+ import { ParameterType } from './analyzer';
2
+ import { FunctionArgumentType } from './declaration';
3
+ import {IDLBlob} from './IDLBlob';
4
+ import {camelCase, snakeCase} from 'lodash';
5
+
6
+ export function addIndent(str: string, space: number) {
7
+ if (!str) return str;
8
+ let lines = str.split('\n');
9
+ lines = lines.map(l => {
10
+ for (let i = 0; i < space; i ++) {
11
+ l = ' ' + l;
12
+ }
13
+ return l;
14
+ });
15
+ return lines.join('\n');
16
+ }
17
+
18
+ export function getClassName(blob: IDLBlob) {
19
+ let raw = camelCase(blob.filename);
20
+ if (raw.slice(0, 3) == 'dom') {
21
+ if (raw === 'domMatrixReadonly') {
22
+ return `DOMMatrixReadOnly`;
23
+ } else if (raw === 'domPointReadonly') {
24
+ return `DOMPointReadOnly`;
25
+ }
26
+ return 'DOM' + raw.slice(3);
27
+ }
28
+ if (raw.slice(0, 4) == 'html') {
29
+ // Legacy support names.
30
+ if (raw === 'htmlIframeElement') {
31
+ return `HTMLIFrameElement`;
32
+ }
33
+ return 'HTML' + raw.slice(4);
34
+ }
35
+ if (raw.slice(0, 6) == 'svgSvg') {
36
+ // special for SVGSVGElement
37
+ return 'SVGSVG' + raw.slice(6)
38
+ }
39
+ if (raw.slice(0, 3) == 'svg') {
40
+ return 'SVG' + raw.slice(3)
41
+ }
42
+ if (raw.slice(0, 3) == 'css') {
43
+ return 'CSS' + raw.slice(3);
44
+ }
45
+ if (raw.slice(0, 2) == 'ui') {
46
+ return 'UI' + raw.slice(2);
47
+ }
48
+
49
+ if (raw == 'webfTouchAreaElement') {
50
+ return 'WebFTouchAreaElement';
51
+ }
52
+ if (raw == 'webfRouterLinkElement') {
53
+ return 'WebFRouterLinkElement';
54
+ }
55
+
56
+ return `${raw[0].toUpperCase() + raw.slice(1)}`;
57
+ }
58
+
59
+ export function getWrapperTypeInfoNameOfClassName(className: string) {
60
+ if (className.slice(0, 6) === 'SVGSVG') {
61
+ // special for SVGSVGElement
62
+ className = `SVGSvg${className.slice(6)}`
63
+ } else if (className === 'SVGGElement') {
64
+ // TODO: use more better way
65
+ className = `SVG_G_Element`
66
+ }
67
+
68
+ return snakeCase(className).toUpperCase()
69
+ }
70
+
71
+ export function getMethodName(name: string) {
72
+ if (!name || name.length === 0) return '';
73
+ return name[0].toUpperCase() + name.slice(1);
74
+ }
75
+
76
+ export function trimNullTypeFromType(type: ParameterType): ParameterType {
77
+ let types = type.value;
78
+ if (!Array.isArray(types)) return type;
79
+ let trimed = types.filter(t => t.value != FunctionArgumentType.null);
80
+
81
+ if (trimed.length === 1) {
82
+ return {
83
+ isArray: false,
84
+ value: trimed[0].value
85
+ }
86
+ }
87
+
88
+ return {
89
+ isArray: type.isArray,
90
+ value: trimed
91
+ };
92
+ }
93
+
94
+ export function isUnionType(type: ParameterType): boolean {
95
+ if (type.isArray || !Array.isArray(type.value)) {
96
+ return false;
97
+ }
98
+
99
+ const trimedType = trimNullTypeFromType(type);
100
+ return Array.isArray(trimedType.value);
101
+ }
102
+
103
+ export function isPointerType(type: ParameterType): boolean {
104
+ if (type.isArray) return false;
105
+ if (typeof type.value === 'string') {
106
+ return true;
107
+ }
108
+ if (Array.isArray(type.value)) {
109
+ return type.value.some(t => typeof t.value === 'string');
110
+ }
111
+ return false;
112
+ }
113
+
114
+ export function getPointerType(type: ParameterType): string {
115
+ if (typeof type.value === 'string') {
116
+ return type.value;
117
+ }
118
+ if (Array.isArray(type.value)) {
119
+ for (let i = 0; i < type.value.length; i++) {
120
+ let childValue = type.value[i];
121
+ if (typeof childValue.value === 'string') {
122
+ return childValue.value;
123
+ }
124
+ }
125
+ }
126
+ return '';
127
+ }
package/src/vue.ts ADDED
@@ -0,0 +1,176 @@
1
+ import _ from "lodash";
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import {ParameterType} from "./analyzer";
5
+ import {ClassObject, FunctionArgumentType, FunctionDeclaration} from "./declaration";
6
+ import {IDLBlob} from "./IDLBlob";
7
+ import {getPointerType, isPointerType} from "./utils";
8
+
9
+ function readTemplate(name: string) {
10
+ return fs.readFileSync(path.join(__dirname, '../templates/' + name + '.tpl'), {encoding: 'utf-8'});
11
+ }
12
+
13
+ function generateReturnType(type: ParameterType) {
14
+ if (isPointerType(type)) {
15
+ const pointerType = getPointerType(type);
16
+ return pointerType;
17
+ }
18
+ if (type.isArray && typeof type.value === 'object' && !Array.isArray(type.value)) {
19
+ return `${getPointerType(type.value)}[]`;
20
+ }
21
+ switch (type.value) {
22
+ case FunctionArgumentType.int:
23
+ case FunctionArgumentType.double: {
24
+ return 'number';
25
+ }
26
+ case FunctionArgumentType.any: {
27
+ return 'any';
28
+ }
29
+ case FunctionArgumentType.boolean: {
30
+ return 'boolean';
31
+ }
32
+ case FunctionArgumentType.dom_string: {
33
+ return 'string';
34
+ }
35
+ case FunctionArgumentType.void:
36
+ return 'void';
37
+ default:
38
+ return 'void';
39
+ }
40
+ }
41
+
42
+ function generateEventHandlerType(type: ParameterType) {
43
+ if (!isPointerType(type)) {
44
+ throw new Error('Event type must be an instance of Event');
45
+ }
46
+ const pointerType = getPointerType(type);
47
+ if (pointerType === 'Event') {
48
+ return 'Event';
49
+ }
50
+ if (pointerType === 'CustomEvent') {
51
+ return 'CustomEvent';
52
+ }
53
+ throw new Error('Unknown event type: ' + pointerType);
54
+ }
55
+
56
+ function generateMethodDeclaration(method: FunctionDeclaration) {
57
+ var methodName = method.name;
58
+ var args = method.args.map(arg => {
59
+ var argName = arg.name;
60
+ var argType = generateReturnType(arg.type);
61
+ return `${argName}: ${argType}`;
62
+ }).join(', ');
63
+ var returnType = generateReturnType(method.returnType);
64
+ return `${methodName}(${args}): ${returnType};`;
65
+ }
66
+
67
+ function generateVueComponent(blob: IDLBlob) {
68
+ const classObjects = blob.objects as ClassObject[];
69
+ const classObjectDictionary = Object.fromEntries(
70
+ classObjects.map(object => {
71
+ return [object.name, object];
72
+ })
73
+ );
74
+
75
+ const properties = classObjects.filter(object => {
76
+ return object.name.endsWith('Properties');
77
+ });
78
+ const events = classObjects.filter(object => {
79
+ return object.name.endsWith('Events');
80
+ });
81
+
82
+ const others = classObjects.filter(object => {
83
+ return !object.name.endsWith('Properties')
84
+ && !object.name.endsWith('Events');
85
+ });
86
+
87
+ const dependencies = others.map(object => {
88
+ const props = object.props.map(prop => {
89
+ if (prop.optional) {
90
+ return `${prop.name}?: ${generateReturnType(prop.type)};`;
91
+ }
92
+ return `${prop.name}: ${generateReturnType(prop.type)};`;
93
+ }).join('\n ');
94
+
95
+ return `
96
+ interface ${object.name} {
97
+ ${props}
98
+ }`;
99
+ }).join('\n\n');
100
+
101
+ const componentProperties = properties.length > 0 ? properties[0] : undefined;
102
+ const componentEvents = events.length > 0 ? events[0] : undefined;
103
+ const className = (() => {
104
+ if (componentProperties) {
105
+ return componentProperties.name.replace(/Properties$/, '');
106
+ }
107
+ if (componentEvents) {
108
+ return componentEvents.name.replace(/Events$/, '');
109
+ }
110
+ return '';
111
+ })();
112
+
113
+ if (!className) {
114
+ return '';
115
+ }
116
+
117
+ const content = _.template(readTemplate('vue.component.partial'))({
118
+ className: className,
119
+ properties: componentProperties,
120
+ events: componentEvents,
121
+ classObjectDictionary,
122
+ dependencies,
123
+ blob,
124
+ generateReturnType,
125
+ generateMethodDeclaration,
126
+ generateEventHandlerType,
127
+ });
128
+
129
+ const result = content.split('\n').filter(str => {
130
+ return str.trim().length > 0;
131
+ }).join('\n');
132
+
133
+ return result;
134
+ }
135
+
136
+ export function generateVueTypings(blobs: IDLBlob[]) {
137
+ const componentNames = blobs.map(blob => {
138
+ const classObjects = blob.objects as ClassObject[];
139
+
140
+ const properties = classObjects.filter(object => {
141
+ return object.name.endsWith('Properties');
142
+ });
143
+ const events = classObjects.filter(object => {
144
+ return object.name.endsWith('Events');
145
+ });
146
+
147
+ const componentProperties = properties.length > 0 ? properties[0] : undefined;
148
+ const componentEvents = events.length > 0 ? events[0] : undefined;
149
+ const className = (() => {
150
+ if (componentProperties) {
151
+ return componentProperties.name.replace(/Properties$/, '');
152
+ }
153
+ if (componentEvents) {
154
+ return componentEvents.name.replace(/Events$/, '');
155
+ }
156
+ return '';
157
+ })();
158
+ return className;
159
+ }).filter(name => {
160
+ return name.length > 0;
161
+ });
162
+ const components = blobs.map(blob => {
163
+ return generateVueComponent(blob);
164
+ }).filter(component => {
165
+ return component.length > 0;
166
+ }).join('\n\n');
167
+
168
+ const content = _.template(readTemplate('vue.components.d.ts'))({
169
+ componentNames,
170
+ components,
171
+ });
172
+
173
+ return content.split('\n').filter(str => {
174
+ return str.trim().length > 0;
175
+ }).join('\n');
176
+ }
@@ -0,0 +1,86 @@
1
+ // AUTO GENERATED FILE, DO NOT EDIT.
2
+ //
3
+ // Generated by <%= command %>
4
+
5
+ // ignore_for_file: avoid_unused_constructor_parameters
6
+ // ignore_for_file: non_constant_identifier_names
7
+ // ignore_for_file: avoid_setters_without_getters
8
+ // ignore_for_file: implementation_imports
9
+ // ignore_for_file: library_private_types_in_public_api
10
+ // ignore_for_file: prefer_void_to_null
11
+
12
+ import 'package:webf/webf.dart';
13
+
14
+ abstract class <%= className %>Bindings extends WidgetElement {
15
+ <%= className %>Bindings(super.context);
16
+
17
+ <% _.forEach(properties?.props, function(prop, index) { %>
18
+ <% var propName = _.camelCase(prop.name); %>
19
+ <% if (shouldMakeNullable(prop)) { %>
20
+ <%= generateReturnType(prop.type) %>? get <%= propName %>;
21
+ <% } else { %>
22
+ <%= generateReturnType(prop.type) %> get <%= propName %>;
23
+ <% } %>
24
+ set <%= propName %>(value);
25
+ <% }); %>
26
+
27
+ <% if (properties?.props.length > 0) { %>
28
+ @override
29
+ void initializeAttributes(Map<String, ElementAttributeProperty> attributes) {
30
+ super.initializeAttributes(attributes);
31
+
32
+ <% _.forEach(properties?.props, function(prop, index) { %>
33
+ <% var attributeName = _.kebabCase(prop.name); %>
34
+ <% var propName = _.camelCase(prop.name); %>
35
+ attributes['<%= attributeName %>'] = ElementAttributeProperty(
36
+ getter: () => <%= propName %>.toString(),
37
+ setter: (value) => <%= generateAttributeSetter(propName, prop.type) %>
38
+ );
39
+ <% }); %>
40
+ }
41
+
42
+ static StaticDefinedBindingPropertyMap <%= _.camelCase(className) %>Properties = {
43
+ <% _.forEach(properties?.props, function(prop, index) { %>
44
+ <% var propName = _.camelCase(prop.name); %>
45
+
46
+ '<%= propName %>': StaticDefinedBindingProperty(
47
+ getter: (element) => castToType<<%= className %>Bindings>(element).<%= propName %>,
48
+ setter: (element, value) =>
49
+ castToType<<%= className %>Bindings>(element).<%= propName %> = value,
50
+ ),
51
+ <% }); %>
52
+ };
53
+
54
+ @override
55
+ List<StaticDefinedBindingPropertyMap> get properties => [
56
+ ...super.properties,
57
+ <%= _.camelCase(className) %>Properties,
58
+ ];
59
+ <% } %>
60
+
61
+ <% if (properties?.methods.length > 0) { %>
62
+
63
+ <% _.forEach(properties?.methods, function(method, index) { %>
64
+ <% var methodName = _.camelCase(method.name); %>
65
+ <%= generateReturnType(method.returnType) %> <%= methodName %>(List<dynamic> args);
66
+ <% }) %>
67
+
68
+ static StaticDefinedSyncBindingObjectMethodMap <%= _.camelCase(className) %>Methods = {
69
+ <% _.forEach(properties?.methods, function(method, index) { %>
70
+ <% var methodName = method.name; %>
71
+ '<%= methodName %>': StaticDefinedSyncBindingObjectMethod(
72
+ call: (element, args) {
73
+ return castToType<<%= className %>Bindings>(element).<%= methodName %>(args);
74
+ },
75
+ ),
76
+ <% }); %>
77
+ };
78
+
79
+ @override
80
+ List<StaticDefinedSyncBindingObjectMethodMap> get methods => [
81
+ ...super.methods,
82
+ <%= _.camelCase(className) %>Methods,
83
+ ];
84
+
85
+ <% } %>
86
+ }
@@ -0,0 +1,2 @@
1
+ dist/
2
+ node_modules/