@fluffjs/cli 0.0.8 → 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.
- package/BabelHelpers.d.ts +26 -0
- package/BabelHelpers.js +65 -0
- package/Cli.d.ts +5 -10
- package/Cli.js +123 -52
- package/CodeGenerator.d.ts +53 -39
- package/CodeGenerator.js +330 -725
- package/ComponentCompiler.d.ts +14 -16
- package/ComponentCompiler.js +187 -256
- package/DomPreProcessor.d.ts +36 -0
- package/DomPreProcessor.js +645 -0
- package/ErrorHelpers.d.ts +5 -0
- package/ErrorHelpers.js +8 -0
- package/ExpressionTransformer.d.ts +38 -28
- package/ExpressionTransformer.js +558 -230
- package/Generator.d.ts +1 -5
- package/Generator.js +128 -67
- package/GetterDependencyExtractor.d.ts +4 -0
- package/GetterDependencyExtractor.js +73 -0
- package/IndexHtmlTransformer.d.ts +6 -7
- package/IndexHtmlTransformer.js +82 -88
- package/Parse5Helpers.d.ts +16 -0
- package/Parse5Helpers.js +81 -0
- package/TemplateParser.d.ts +39 -21
- package/TemplateParser.js +462 -268
- package/Typeguards.d.ts +24 -0
- package/Typeguards.js +30 -0
- package/babel-plugin-class-transform.d.ts +3 -18
- package/babel-plugin-class-transform.js +3 -11
- package/babel-plugin-component.d.ts +4 -13
- package/babel-plugin-component.js +7 -0
- package/babel-plugin-imports.d.ts +3 -11
- package/babel-plugin-imports.js +5 -31
- package/babel-plugin-reactive.d.ts +2 -19
- package/babel-plugin-reactive.js +21 -76
- package/bin.js +2 -2
- package/fluff-esbuild-plugin.d.ts +2 -5
- package/fluff-esbuild-plugin.js +4 -1
- package/index.d.ts +6 -2
- package/index.js +1 -1
- package/interfaces/BabelPluginClassTransformState.d.ts +5 -0
- package/interfaces/BabelPluginComponentState.d.ts +4 -0
- package/interfaces/BabelPluginComponentState.js +1 -0
- package/interfaces/BabelPluginImportsState.d.ts +5 -0
- package/interfaces/BabelPluginImportsState.js +1 -0
- package/interfaces/BabelPluginReactiveState.d.ts +13 -0
- package/interfaces/BabelPluginReactiveState.js +1 -0
- package/interfaces/BabelPluginReactiveWatchCallInfo.d.ts +7 -0
- package/interfaces/BabelPluginReactiveWatchCallInfo.js +1 -0
- package/interfaces/BabelPluginReactiveWatchInfo.d.ts +5 -0
- package/interfaces/BabelPluginReactiveWatchInfo.js +1 -0
- package/interfaces/BabelToken.d.ts +8 -0
- package/interfaces/BabelToken.js +1 -0
- package/interfaces/BindingInfo.d.ts +12 -0
- package/interfaces/BindingInfo.js +1 -0
- package/interfaces/BreakMarkerConfig.d.ts +4 -0
- package/interfaces/BreakMarkerConfig.js +1 -0
- package/interfaces/BreakNode.d.ts +4 -0
- package/interfaces/BreakNode.js +1 -0
- package/interfaces/BundleOptions.d.ts +8 -0
- package/interfaces/BundleOptions.js +1 -0
- package/interfaces/ClassTransformOptions.d.ts +10 -0
- package/interfaces/ClassTransformOptions.js +1 -0
- package/interfaces/CliOptions.d.ts +6 -0
- package/interfaces/CliOptions.js +1 -0
- package/interfaces/CommentNode.d.ts +5 -0
- package/interfaces/CommentNode.js +1 -0
- package/interfaces/CompileResult.d.ts +6 -0
- package/interfaces/CompileResult.js +1 -0
- package/interfaces/CompilerOptions.d.ts +6 -0
- package/interfaces/CompilerOptions.js +1 -0
- package/interfaces/ComponentInfo.d.ts +8 -0
- package/interfaces/ComponentInfo.js +1 -0
- package/interfaces/ComponentMetadata.d.ts +9 -0
- package/interfaces/ComponentMetadata.js +1 -0
- package/interfaces/ControlFlow.d.ts +19 -0
- package/interfaces/ControlFlow.js +1 -0
- package/interfaces/ControlFlowNode.d.ts +6 -0
- package/interfaces/ControlFlowNode.js +1 -0
- package/interfaces/ControlFlowParseResult.d.ts +10 -0
- package/interfaces/ControlFlowParseResult.js +1 -0
- package/interfaces/ElementNode.d.ts +11 -0
- package/interfaces/ElementNode.js +1 -0
- package/interfaces/FluffConfigInterface.d.ts +7 -0
- package/interfaces/FluffConfigInterface.js +1 -0
- package/interfaces/FluffPluginOptions.d.ts +9 -0
- package/interfaces/FluffPluginOptions.js +1 -0
- package/interfaces/FluffTarget.d.ts +15 -0
- package/interfaces/FluffTarget.js +1 -0
- package/interfaces/ForMarkerConfig.d.ts +9 -0
- package/interfaces/ForMarkerConfig.js +1 -0
- package/interfaces/ForNode.d.ts +13 -0
- package/interfaces/ForNode.js +1 -0
- package/interfaces/GeneratorOptions.d.ts +5 -0
- package/interfaces/GeneratorOptions.js +1 -0
- package/interfaces/HtmlTransformOptions.d.ts +9 -0
- package/interfaces/HtmlTransformOptions.js +1 -0
- package/interfaces/IfBranch.d.ts +8 -0
- package/interfaces/IfBranch.js +1 -0
- package/interfaces/IfMarkerConfig.d.ts +8 -0
- package/interfaces/IfMarkerConfig.js +1 -0
- package/interfaces/IfNode.d.ts +7 -0
- package/interfaces/IfNode.js +1 -0
- package/interfaces/ImportTransformOptions.d.ts +7 -0
- package/interfaces/ImportTransformOptions.js +1 -0
- package/interfaces/InterpolationNode.d.ts +12 -0
- package/interfaces/InterpolationNode.js +1 -0
- package/interfaces/ParsedTemplate.d.ts +6 -0
- package/interfaces/ParsedTemplate.js +1 -0
- package/interfaces/ParsedTemplateOld.d.ts +9 -0
- package/interfaces/ParsedTemplateOld.js +1 -0
- package/interfaces/PropertyChain.d.ts +2 -0
- package/interfaces/PropertyChain.js +1 -0
- package/interfaces/Scope.d.ts +5 -0
- package/interfaces/Scope.js +1 -0
- package/interfaces/ServeOptions.d.ts +5 -0
- package/interfaces/ServeOptions.js +1 -0
- package/interfaces/SwitchCase.d.ts +8 -0
- package/interfaces/SwitchCase.js +1 -0
- package/interfaces/SwitchMarkerConfig.d.ts +11 -0
- package/interfaces/SwitchMarkerConfig.js +1 -0
- package/interfaces/SwitchNode.d.ts +10 -0
- package/interfaces/SwitchNode.js +1 -0
- package/interfaces/TemplateBinding.d.ts +10 -0
- package/interfaces/TemplateBinding.js +1 -0
- package/interfaces/TemplateNode.d.ts +7 -0
- package/interfaces/TemplateNode.js +1 -0
- package/interfaces/TextMarkerConfig.d.ts +10 -0
- package/interfaces/TextMarkerConfig.js +1 -0
- package/interfaces/TextNode.d.ts +5 -0
- package/interfaces/TextNode.js +1 -0
- package/interfaces/TokenizeResult.d.ts +6 -0
- package/interfaces/TokenizeResult.js +1 -0
- package/interfaces/TransformOptions.d.ts +11 -0
- package/interfaces/TransformOptions.js +1 -0
- package/interfaces/index.d.ts +34 -0
- package/interfaces/index.js +1 -0
- package/package.json +9 -1
- package/types/FluffConfig.d.ts +5 -27
- package/ControlFlowParser.d.ts +0 -55
- package/ControlFlowParser.js +0 -279
- package/types.d.ts +0 -46
- /package/{types.js → interfaces/BabelPluginClassTransformState.js} +0 -0
package/ComponentCompiler.d.ts
CHANGED
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
import type { ClassTransformOptions } from './babel-plugin-class-transform.js';
|
|
2
2
|
import type { ComponentMetadata } from './babel-plugin-component.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
watchFiles?: string[];
|
|
7
|
-
}
|
|
3
|
+
import type { CompileResult } from './interfaces/CompileResult.js';
|
|
4
|
+
import { TemplateParser } from './TemplateParser.js';
|
|
5
|
+
export type { CompileResult } from './interfaces/CompileResult.js';
|
|
8
6
|
export declare class ComponentCompiler {
|
|
9
7
|
private readonly componentSelectors;
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
compileComponent(filePath: string): Promise<string>;
|
|
16
|
-
compileComponentForBundle(filePath: string, minify?: boolean, sourcemap?: boolean): Promise<CompileResult>;
|
|
8
|
+
private getReactivePropsForFile;
|
|
9
|
+
protected createTemplateParser(_filePath: string): TemplateParser;
|
|
10
|
+
private runBabelTransform;
|
|
11
|
+
discoverComponents(dir: string): Promise<void>;
|
|
12
|
+
compileComponentForBundle(filePath: string, minify?: boolean, sourcemap?: boolean, skipDefine?: boolean, production?: boolean): Promise<CompileResult>;
|
|
17
13
|
stripTypeScriptWithSourceMap(code: string, filePath: string, sourcemap?: boolean): Promise<CompileResult>;
|
|
18
|
-
private createComponentSourceMap;
|
|
19
14
|
transformImportsForBundle(code: string, filePath: string): Promise<string>;
|
|
20
|
-
transformReactiveProperties(code: string, filePath?: string): Promise<string>;
|
|
15
|
+
transformReactiveProperties(code: string, filePath?: string, production?: boolean): Promise<string>;
|
|
21
16
|
stripTypeScript(code: string, filePath?: string): Promise<string>;
|
|
22
17
|
extractComponentMetadata(code: string, filePath: string): Promise<ComponentMetadata | null>;
|
|
23
|
-
transformImportsAndDecorators(code: string, filePath: string): Promise<string>;
|
|
24
18
|
transformClass(code: string, filePath: string, options: ClassTransformOptions): Promise<string>;
|
|
25
19
|
transformLibraryImports(code: string, filePath: string): Promise<string>;
|
|
26
|
-
|
|
20
|
+
private createComponentSourceMap;
|
|
21
|
+
private addFluffImport;
|
|
22
|
+
private appendCode;
|
|
23
|
+
private addBindingsMap;
|
|
24
|
+
private addCustomElementsDefine;
|
|
27
25
|
}
|
|
28
26
|
//# sourceMappingURL=ComponentCompiler.d.ts.map
|
package/ComponentCompiler.js
CHANGED
|
@@ -1,105 +1,86 @@
|
|
|
1
1
|
import * as babel from '@babel/core';
|
|
2
|
+
import { parse } from '@babel/parser';
|
|
3
|
+
import * as t from '@babel/types';
|
|
2
4
|
import * as esbuild from 'esbuild';
|
|
3
5
|
import * as fs from 'fs';
|
|
4
6
|
import { minify as minifyHtml } from 'html-minifier-terser';
|
|
5
7
|
import * as path from 'path';
|
|
6
8
|
import { SourceMapConsumer, SourceMapGenerator } from 'source-map';
|
|
7
|
-
import classTransformPlugin
|
|
9
|
+
import classTransformPlugin from './babel-plugin-class-transform.js';
|
|
8
10
|
import componentPlugin, { componentMetadataMap } from './babel-plugin-component.js';
|
|
9
11
|
import importsPlugin from './babel-plugin-imports.js';
|
|
10
12
|
import reactivePlugin, { reactivePropertiesMap } from './babel-plugin-reactive.js';
|
|
13
|
+
import { generate } from './BabelHelpers.js';
|
|
11
14
|
import { CodeGenerator } from './CodeGenerator.js';
|
|
15
|
+
import { ErrorHelpers } from './ErrorHelpers.js';
|
|
16
|
+
import { GetterDependencyExtractor } from './GetterDependencyExtractor.js';
|
|
12
17
|
import { TemplateParser } from './TemplateParser.js';
|
|
13
18
|
export class ComponentCompiler {
|
|
14
19
|
componentSelectors = new Set();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
async discoverComponents(demoDir) {
|
|
25
|
-
const files = fs.readdirSync(demoDir)
|
|
26
|
-
.filter(f => f.endsWith('.component.ts'));
|
|
27
|
-
for (const file of files) {
|
|
28
|
-
const filePath = path.join(demoDir, file);
|
|
29
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
30
|
-
const metadata = await this.extractComponentMetadata(content, filePath);
|
|
31
|
-
if (metadata?.selector) {
|
|
32
|
-
this.componentSelectors.add(metadata.selector);
|
|
20
|
+
getReactivePropsForFile(filePath) {
|
|
21
|
+
const direct = reactivePropertiesMap.get(filePath);
|
|
22
|
+
if (direct) {
|
|
23
|
+
return direct;
|
|
24
|
+
}
|
|
25
|
+
for (const [key, value] of reactivePropertiesMap.entries()) {
|
|
26
|
+
if (key === filePath || key.endsWith(filePath) || filePath.endsWith(key)) {
|
|
27
|
+
return value;
|
|
33
28
|
}
|
|
34
29
|
}
|
|
30
|
+
return new Set();
|
|
35
31
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
else if (template) {
|
|
60
|
-
templateHtml = template;
|
|
32
|
+
createTemplateParser(_filePath) {
|
|
33
|
+
return new TemplateParser();
|
|
34
|
+
}
|
|
35
|
+
async runBabelTransform(code, filePath, options) {
|
|
36
|
+
try {
|
|
37
|
+
const presets = options.useTypeScriptPreset
|
|
38
|
+
? [['@babel/preset-typescript', { isTSX: false, allExtensions: true }]]
|
|
39
|
+
: [];
|
|
40
|
+
const plugins = options.useDecoratorSyntax
|
|
41
|
+
? [['@babel/plugin-syntax-decorators', { version: '2023-11' }], ...options.plugins]
|
|
42
|
+
: options.plugins;
|
|
43
|
+
const parserOpts = options.useDecoratorSyntax
|
|
44
|
+
? { plugins: ['typescript', 'decorators'] }
|
|
45
|
+
: options.useTypeScriptPreset
|
|
46
|
+
? { plugins: ['typescript'] }
|
|
47
|
+
: undefined;
|
|
48
|
+
const result = await babel.transformAsync(code, {
|
|
49
|
+
filename: filePath,
|
|
50
|
+
presets,
|
|
51
|
+
plugins,
|
|
52
|
+
parserOpts
|
|
53
|
+
});
|
|
54
|
+
return result?.code ?? code;
|
|
61
55
|
}
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
catch (e) {
|
|
57
|
+
console.error(`${options.errorContext} in ${filePath}:`, ErrorHelpers.getErrorMessage(e));
|
|
58
|
+
return code;
|
|
64
59
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
}
|
|
61
|
+
async discoverComponents(dir) {
|
|
62
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
63
|
+
for (const entry of entries) {
|
|
64
|
+
const fullPath = path.join(dir, entry.name);
|
|
65
|
+
if (entry.isDirectory()) {
|
|
66
|
+
await this.discoverComponents(fullPath);
|
|
67
|
+
}
|
|
68
|
+
else if (entry.name.endsWith('.component.ts')) {
|
|
69
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
70
|
+
const metadata = await this.extractComponentMetadata(content, fullPath);
|
|
71
|
+
if (metadata?.selector) {
|
|
72
|
+
this.componentSelectors.add(metadata.selector);
|
|
73
|
+
}
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
|
-
else if (inlineStyles) {
|
|
73
|
-
styles = inlineStyles;
|
|
74
|
-
}
|
|
75
|
-
const { html, bindings, controlFlows, templateRefs } = this.parser.parse(templateHtml);
|
|
76
|
-
this.generator.setTemplateRefs(templateRefs);
|
|
77
|
-
const renderMethod = this.generator.generateRenderMethod(html, styles);
|
|
78
|
-
const bindingsSetup = this.generator.generateBindingsSetup(bindings, controlFlows);
|
|
79
|
-
let result = await this.transformImportsAndDecorators(source, filePath);
|
|
80
|
-
result = await this.transformClass(result, filePath, {
|
|
81
|
-
className, originalSuperClass: 'HTMLElement', newSuperClass: 'FluffElement', injectMethods: [
|
|
82
|
-
{ name: '__render', body: renderMethod }, { name: '__setupBindings', body: bindingsSetup }
|
|
83
|
-
]
|
|
84
|
-
});
|
|
85
|
-
result = 'import { FluffElement } from \'./fluff-lib/runtime/FluffElement.js\';\n' + result;
|
|
86
|
-
result += `\ncustomElements.define('${selector}', ${className});\n`;
|
|
87
|
-
result = await this.stripTypeScript(result, filePath);
|
|
88
|
-
return result;
|
|
89
76
|
}
|
|
90
|
-
async compileComponentForBundle(filePath, minify, sourcemap) {
|
|
77
|
+
async compileComponentForBundle(filePath, minify, sourcemap, skipDefine, production) {
|
|
91
78
|
let source = fs.readFileSync(filePath, 'utf-8');
|
|
92
79
|
const componentDir = path.dirname(filePath);
|
|
93
|
-
const
|
|
80
|
+
const parser = this.createTemplateParser(filePath);
|
|
81
|
+
reactivePropertiesMap.delete(filePath);
|
|
94
82
|
if (source.includes('@Reactive') || source.includes('@Input')) {
|
|
95
|
-
source = await this.transformReactiveProperties(source, filePath);
|
|
96
|
-
const reactiveProps = reactivePropertiesMap.get(filePath);
|
|
97
|
-
if (reactiveProps) {
|
|
98
|
-
generator.setReactiveProperties(reactiveProps);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
generator.setReactiveProperties(new Set());
|
|
83
|
+
source = await this.transformReactiveProperties(source, filePath, production);
|
|
103
84
|
}
|
|
104
85
|
const metadata = await this.extractComponentMetadata(source, filePath);
|
|
105
86
|
if (!metadata) {
|
|
@@ -126,32 +107,48 @@ export class ComponentCompiler {
|
|
|
126
107
|
else if (inlineStyles) {
|
|
127
108
|
styles = inlineStyles;
|
|
128
109
|
}
|
|
110
|
+
if (minify && styles) {
|
|
111
|
+
const cssResult = await esbuild.transform(styles, {
|
|
112
|
+
loader: 'css', minify: true
|
|
113
|
+
});
|
|
114
|
+
styles = cssResult.code;
|
|
115
|
+
}
|
|
116
|
+
const reactiveProps = this.getReactivePropsForFile(filePath);
|
|
117
|
+
const getterDepMap = GetterDependencyExtractor.extractGetterDependencyMap(source, reactiveProps);
|
|
118
|
+
parser.setGetterDependencyMap(getterDepMap);
|
|
119
|
+
const parsed = await parser.parse(templateHtml);
|
|
120
|
+
parser.setGetterDependencyMap(new Map());
|
|
121
|
+
const gen = new CodeGenerator(this.componentSelectors, selector);
|
|
122
|
+
let generatedHtml = gen.generateHtml(parsed);
|
|
129
123
|
if (minify) {
|
|
130
|
-
|
|
124
|
+
generatedHtml = await minifyHtml(generatedHtml, {
|
|
131
125
|
collapseWhitespace: true,
|
|
132
126
|
removeComments: true,
|
|
133
127
|
removeRedundantAttributes: true,
|
|
134
128
|
removeEmptyAttributes: true
|
|
135
129
|
});
|
|
136
|
-
if (styles) {
|
|
137
|
-
const cssResult = await esbuild.transform(styles, {
|
|
138
|
-
loader: 'css', minify: true
|
|
139
|
-
});
|
|
140
|
-
styles = cssResult.code;
|
|
141
|
-
}
|
|
142
130
|
}
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
const bindingsSetup = generator.generateBindingsSetup(bindings, controlFlows);
|
|
131
|
+
const markerConfigJson = gen.getMarkerConfigJson();
|
|
132
|
+
const renderMethod = gen.generateRenderMethodFromHtml(generatedHtml, styles, markerConfigJson);
|
|
133
|
+
const bindingsSetup = gen.generateBindingsSetup();
|
|
147
134
|
let result = await this.transformImportsForBundle(source, filePath);
|
|
148
135
|
result = await this.transformClass(result, filePath, {
|
|
149
136
|
className, originalSuperClass: 'HTMLElement', newSuperClass: 'FluffElement', injectMethods: [
|
|
150
137
|
{ name: '__render', body: renderMethod }, { name: '__setupBindings', body: bindingsSetup }
|
|
151
138
|
]
|
|
152
139
|
});
|
|
153
|
-
result =
|
|
154
|
-
|
|
140
|
+
result = this.addFluffImport(result);
|
|
141
|
+
const exprAssignments = gen.generateExpressionAssignments();
|
|
142
|
+
if (exprAssignments) {
|
|
143
|
+
result = this.appendCode(result, exprAssignments);
|
|
144
|
+
}
|
|
145
|
+
const bindingsMap = gen.getBindingsMap();
|
|
146
|
+
if (Object.keys(bindingsMap).length > 0) {
|
|
147
|
+
result = this.addBindingsMap(result, className, bindingsMap);
|
|
148
|
+
}
|
|
149
|
+
if (!skipDefine) {
|
|
150
|
+
result = this.addCustomElementsDefine(result, selector, className);
|
|
151
|
+
}
|
|
155
152
|
const tsResult = await this.stripTypeScriptWithSourceMap(result, filePath, sourcemap);
|
|
156
153
|
const watchFiles = [];
|
|
157
154
|
if (templatePath) {
|
|
@@ -178,78 +175,31 @@ export class ComponentCompiler {
|
|
|
178
175
|
return { code: result.code, map: result.map };
|
|
179
176
|
}
|
|
180
177
|
catch (e) {
|
|
181
|
-
|
|
182
|
-
console.error(`Error transforming ${filePath}:`, message);
|
|
178
|
+
console.error(`Error transforming ${filePath}:`, ErrorHelpers.getErrorMessage(e));
|
|
183
179
|
return { code };
|
|
184
180
|
}
|
|
185
181
|
}
|
|
186
|
-
async createComponentSourceMap(code, esbuildMap, componentPath, templatePath, stylePath) {
|
|
187
|
-
const consumer = await new SourceMapConsumer(JSON.parse(esbuildMap));
|
|
188
|
-
const generator = new SourceMapGenerator({
|
|
189
|
-
file: path.basename(componentPath)
|
|
190
|
-
.replace('.ts', '.js')
|
|
191
|
-
});
|
|
192
|
-
generator.setSourceContent(componentPath, fs.readFileSync(componentPath, 'utf-8'));
|
|
193
|
-
generator.setSourceContent(templatePath, fs.readFileSync(templatePath, 'utf-8'));
|
|
194
|
-
if (stylePath && fs.existsSync(stylePath)) {
|
|
195
|
-
generator.setSourceContent(stylePath, fs.readFileSync(stylePath, 'utf-8'));
|
|
196
|
-
}
|
|
197
|
-
consumer.eachMapping(mapping => {
|
|
198
|
-
if (mapping.source) {
|
|
199
|
-
generator.addMapping({
|
|
200
|
-
generated: { line: mapping.generatedLine, column: mapping.generatedColumn },
|
|
201
|
-
original: { line: mapping.originalLine, column: mapping.originalColumn },
|
|
202
|
-
source: mapping.source,
|
|
203
|
-
name: mapping.name ?? undefined
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
consumer.destroy();
|
|
208
|
-
return generator.toString();
|
|
209
|
-
}
|
|
210
182
|
async transformImportsForBundle(code, filePath) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
], parserOpts: {
|
|
224
|
-
plugins: ['typescript', 'decorators']
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
return result?.code ?? code;
|
|
228
|
-
}
|
|
229
|
-
catch (e) {
|
|
230
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
231
|
-
console.error(`Failed to transform imports in ${filePath}:`, message);
|
|
232
|
-
return code;
|
|
233
|
-
}
|
|
183
|
+
const importOptions = {
|
|
184
|
+
removeImportsFrom: ['lighter'],
|
|
185
|
+
removeDecorators: ['Component', 'Input', 'Output'],
|
|
186
|
+
pathReplacements: {},
|
|
187
|
+
addJsExtension: false
|
|
188
|
+
};
|
|
189
|
+
return this.runBabelTransform(code, filePath, {
|
|
190
|
+
useTypeScriptPreset: true,
|
|
191
|
+
useDecoratorSyntax: true,
|
|
192
|
+
plugins: [[importsPlugin, importOptions]],
|
|
193
|
+
errorContext: 'Failed to transform imports'
|
|
194
|
+
});
|
|
234
195
|
}
|
|
235
|
-
async transformReactiveProperties(code, filePath = 'file.ts') {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
], parserOpts: {
|
|
243
|
-
plugins: ['typescript', 'decorators']
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
return result?.code ?? code;
|
|
247
|
-
}
|
|
248
|
-
catch (e) {
|
|
249
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
250
|
-
console.error(`Babel transform error in ${filePath}:`, message);
|
|
251
|
-
return code;
|
|
252
|
-
}
|
|
196
|
+
async transformReactiveProperties(code, filePath = 'file.ts', production) {
|
|
197
|
+
return this.runBabelTransform(code, filePath, {
|
|
198
|
+
useTypeScriptPreset: true,
|
|
199
|
+
useDecoratorSyntax: true,
|
|
200
|
+
plugins: [[reactivePlugin, { production: production ?? false }]],
|
|
201
|
+
errorContext: 'Babel transform error'
|
|
202
|
+
});
|
|
253
203
|
}
|
|
254
204
|
async stripTypeScript(code, filePath = 'file.ts') {
|
|
255
205
|
try {
|
|
@@ -259,123 +209,104 @@ export class ComponentCompiler {
|
|
|
259
209
|
return result.code;
|
|
260
210
|
}
|
|
261
211
|
catch (e) {
|
|
262
|
-
|
|
263
|
-
console.error(`Error transforming ${filePath}:`, message);
|
|
212
|
+
console.error(`Error transforming ${filePath}:`, ErrorHelpers.getErrorMessage(e));
|
|
264
213
|
return code;
|
|
265
214
|
}
|
|
266
215
|
}
|
|
267
216
|
async extractComponentMetadata(code, filePath) {
|
|
268
217
|
try {
|
|
269
218
|
componentMetadataMap.delete(filePath);
|
|
270
|
-
await
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
], parserOpts: {
|
|
276
|
-
plugins: ['typescript', 'decorators']
|
|
277
|
-
}
|
|
219
|
+
await this.runBabelTransform(code, filePath, {
|
|
220
|
+
useTypeScriptPreset: true,
|
|
221
|
+
useDecoratorSyntax: true,
|
|
222
|
+
plugins: [componentPlugin],
|
|
223
|
+
errorContext: 'Failed to extract component metadata'
|
|
278
224
|
});
|
|
279
225
|
return componentMetadataMap.get(filePath) ?? null;
|
|
280
226
|
}
|
|
281
227
|
catch (e) {
|
|
282
|
-
|
|
283
|
-
console.error(`Failed to extract component metadata from ${filePath}:`, message);
|
|
228
|
+
console.error(`Failed to extract component metadata from ${filePath}:`, ErrorHelpers.getErrorMessage(e));
|
|
284
229
|
return null;
|
|
285
230
|
}
|
|
286
231
|
}
|
|
287
|
-
async transformImportsAndDecorators(code, filePath) {
|
|
288
|
-
try {
|
|
289
|
-
const importOptions = {
|
|
290
|
-
removeImportsFrom: ['lighter'], removeDecorators: ['Component', 'Input', 'Output'], pathReplacements: {
|
|
291
|
-
'@/fluff-lib/': './fluff-lib/'
|
|
292
|
-
}, addJsExtension: true
|
|
293
|
-
};
|
|
294
|
-
const result = await babel.transformAsync(code, {
|
|
295
|
-
filename: filePath, presets: [
|
|
296
|
-
['@babel/preset-typescript', { isTSX: false, allExtensions: true }]
|
|
297
|
-
], plugins: [
|
|
298
|
-
['@babel/plugin-syntax-decorators', { version: '2023-11' }], [importsPlugin, importOptions]
|
|
299
|
-
], parserOpts: {
|
|
300
|
-
plugins: ['typescript', 'decorators']
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
return result?.code ?? code;
|
|
304
|
-
}
|
|
305
|
-
catch (e) {
|
|
306
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
307
|
-
console.error(`Failed to transform imports in ${filePath}:`, message);
|
|
308
|
-
return code;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
232
|
async transformClass(code, filePath, options) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
let transformed = result?.code ?? code;
|
|
319
|
-
if (options.injectMethods) {
|
|
320
|
-
transformed = injectMethodBodies(transformed, options.injectMethods);
|
|
321
|
-
}
|
|
322
|
-
return transformed;
|
|
323
|
-
}
|
|
324
|
-
catch (e) {
|
|
325
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
326
|
-
console.error(`Failed to transform class in ${filePath}:`, message);
|
|
327
|
-
return code;
|
|
328
|
-
}
|
|
233
|
+
return this.runBabelTransform(code, filePath, {
|
|
234
|
+
useTypeScriptPreset: false,
|
|
235
|
+
useDecoratorSyntax: false,
|
|
236
|
+
plugins: [[classTransformPlugin, options]],
|
|
237
|
+
errorContext: 'Failed to transform class'
|
|
238
|
+
});
|
|
329
239
|
}
|
|
330
240
|
async transformLibraryImports(code, filePath) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
], parserOpts: {
|
|
343
|
-
plugins: ['typescript']
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
return result?.code ?? code;
|
|
347
|
-
}
|
|
348
|
-
catch (e) {
|
|
349
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
350
|
-
console.error(`Failed to transform library imports in ${filePath}:`, message);
|
|
351
|
-
return code;
|
|
352
|
-
}
|
|
241
|
+
const importOptions = {
|
|
242
|
+
pathReplacements: {
|
|
243
|
+
'@/fluff-lib/': '../'
|
|
244
|
+
}, addJsExtension: true
|
|
245
|
+
};
|
|
246
|
+
return this.runBabelTransform(code, filePath, {
|
|
247
|
+
useTypeScriptPreset: true,
|
|
248
|
+
useDecoratorSyntax: false,
|
|
249
|
+
plugins: [[importsPlugin, importOptions]],
|
|
250
|
+
errorContext: 'Failed to transform library imports'
|
|
251
|
+
});
|
|
353
252
|
}
|
|
354
|
-
async
|
|
355
|
-
const
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
253
|
+
async createComponentSourceMap(code, esbuildMap, componentPath, templatePath, stylePath) {
|
|
254
|
+
const consumer = await new SourceMapConsumer(JSON.parse(esbuildMap));
|
|
255
|
+
const generator = new SourceMapGenerator({
|
|
256
|
+
file: path.basename(componentPath)
|
|
257
|
+
.replace('.ts', '.js')
|
|
258
|
+
});
|
|
259
|
+
generator.setSourceContent(componentPath, fs.readFileSync(componentPath, 'utf-8'));
|
|
260
|
+
generator.setSourceContent(templatePath, fs.readFileSync(templatePath, 'utf-8'));
|
|
261
|
+
if (stylePath && fs.existsSync(stylePath)) {
|
|
262
|
+
generator.setSourceContent(stylePath, fs.readFileSync(stylePath, 'utf-8'));
|
|
359
263
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
}
|
|
368
|
-
const files = fs.readdirSync(srcPath)
|
|
369
|
-
.filter(f => f.endsWith('.ts'));
|
|
370
|
-
for (const file of files) {
|
|
371
|
-
const fullPath = path.join(srcPath, file);
|
|
372
|
-
let content = fs.readFileSync(fullPath, 'utf-8');
|
|
373
|
-
content = await this.transformLibraryImports(content, fullPath);
|
|
374
|
-
content = await this.stripTypeScript(content, fullPath);
|
|
375
|
-
const outFile = file.replace('.ts', '.js');
|
|
376
|
-
fs.writeFileSync(path.join(distPath, outFile), content);
|
|
377
|
-
}
|
|
264
|
+
consumer.eachMapping(mapping => {
|
|
265
|
+
if (mapping.source) {
|
|
266
|
+
generator.addMapping({
|
|
267
|
+
generated: { line: mapping.generatedLine, column: mapping.generatedColumn },
|
|
268
|
+
original: { line: mapping.originalLine, column: mapping.originalColumn },
|
|
269
|
+
source: mapping.source,
|
|
270
|
+
name: mapping.name ?? undefined
|
|
271
|
+
});
|
|
378
272
|
}
|
|
273
|
+
});
|
|
274
|
+
consumer.destroy();
|
|
275
|
+
return generator.toString();
|
|
276
|
+
}
|
|
277
|
+
addFluffImport(code) {
|
|
278
|
+
const ast = parse(code, { sourceType: 'module' });
|
|
279
|
+
const importSpecifiers = [
|
|
280
|
+
t.importSpecifier(t.identifier('FluffBase'), t.identifier('FluffBase')),
|
|
281
|
+
t.importSpecifier(t.identifier('FluffElement'), t.identifier('FluffElement')),
|
|
282
|
+
t.importSpecifier(t.identifier('MarkerManager'), t.identifier('MarkerManager'))
|
|
283
|
+
];
|
|
284
|
+
const importDecl = t.importDeclaration(importSpecifiers, t.stringLiteral('@fluffjs/fluff'));
|
|
285
|
+
ast.program.body.unshift(importDecl);
|
|
286
|
+
return generate(ast, { compact: false }).code;
|
|
287
|
+
}
|
|
288
|
+
appendCode(code, additionalCode) {
|
|
289
|
+
const ast = parse(code, { sourceType: 'module' });
|
|
290
|
+
const additionalAst = parse(additionalCode, { sourceType: 'module' });
|
|
291
|
+
ast.program.body.push(...additionalAst.program.body);
|
|
292
|
+
return generate(ast, { compact: false }).code;
|
|
293
|
+
}
|
|
294
|
+
addBindingsMap(code, className, bindingsMap) {
|
|
295
|
+
const ast = parse(code, { sourceType: 'module' });
|
|
296
|
+
const jsonStr = JSON.stringify(bindingsMap);
|
|
297
|
+
const valueAst = parse(`(${jsonStr})`, { sourceType: 'module' });
|
|
298
|
+
const [valueStmt] = valueAst.program.body;
|
|
299
|
+
if (!t.isExpressionStatement(valueStmt)) {
|
|
300
|
+
return code;
|
|
379
301
|
}
|
|
302
|
+
const assignment = t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(className), t.identifier('__bindings')), valueStmt.expression));
|
|
303
|
+
ast.program.body.push(assignment);
|
|
304
|
+
return generate(ast, { compact: false }).code;
|
|
305
|
+
}
|
|
306
|
+
addCustomElementsDefine(code, selector, className) {
|
|
307
|
+
const ast = parse(code, { sourceType: 'module' });
|
|
308
|
+
const defineCall = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('customElements'), t.identifier('define')), [t.stringLiteral(selector), t.identifier(className)]));
|
|
309
|
+
ast.program.body.push(defineCall);
|
|
310
|
+
return generate(ast, { compact: false }).code;
|
|
380
311
|
}
|
|
381
312
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare class DomPreProcessor {
|
|
2
|
+
private readonly stack;
|
|
3
|
+
private source;
|
|
4
|
+
private rootFragment;
|
|
5
|
+
private readonly elementStack;
|
|
6
|
+
process(html: string): Promise<string>;
|
|
7
|
+
private handleStartTag;
|
|
8
|
+
private transformAttribute;
|
|
9
|
+
private convertInterpolationToExpression;
|
|
10
|
+
private handleEndTag;
|
|
11
|
+
private handleText;
|
|
12
|
+
private appendNode;
|
|
13
|
+
private appendText;
|
|
14
|
+
private appendDoctype;
|
|
15
|
+
private findNextSpecial;
|
|
16
|
+
private parseInterpolation;
|
|
17
|
+
private parseControlFlow;
|
|
18
|
+
private parseExpressionBlockCore;
|
|
19
|
+
private parseSimpleBlockCore;
|
|
20
|
+
private parseIfStatement;
|
|
21
|
+
private parseElseIfStatement;
|
|
22
|
+
private parseElseStatement;
|
|
23
|
+
private parseForStatement;
|
|
24
|
+
private parseSwitchStatement;
|
|
25
|
+
private parseCaseStatement;
|
|
26
|
+
private parseDefaultStatement;
|
|
27
|
+
private parseEmptyStatement;
|
|
28
|
+
private parseSimpleStatement;
|
|
29
|
+
private parseFallthroughStatement;
|
|
30
|
+
private parseBreakStatement;
|
|
31
|
+
private parseForContent;
|
|
32
|
+
private skipWhitespace;
|
|
33
|
+
private handleComment;
|
|
34
|
+
private getOriginalAttributeName;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=DomPreProcessor.d.ts.map
|