@fluffjs/cli 0.0.8 → 0.1.1
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 +7 -10
- package/Cli.js +139 -52
- package/CodeGenerator.d.ts +53 -39
- package/CodeGenerator.js +330 -725
- package/ComponentCompiler.d.ts +14 -16
- package/ComponentCompiler.js +193 -257
- 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 +17 -0
- package/Parse5Helpers.js +95 -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 +9 -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 +8 -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 +10 -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,88 @@
|
|
|
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';
|
|
6
|
+
import * as parse5 from 'parse5';
|
|
4
7
|
import { minify as minifyHtml } from 'html-minifier-terser';
|
|
5
8
|
import * as path from 'path';
|
|
6
9
|
import { SourceMapConsumer, SourceMapGenerator } from 'source-map';
|
|
7
|
-
import classTransformPlugin
|
|
10
|
+
import classTransformPlugin from './babel-plugin-class-transform.js';
|
|
8
11
|
import componentPlugin, { componentMetadataMap } from './babel-plugin-component.js';
|
|
9
12
|
import importsPlugin from './babel-plugin-imports.js';
|
|
10
13
|
import reactivePlugin, { reactivePropertiesMap } from './babel-plugin-reactive.js';
|
|
14
|
+
import { generate } from './BabelHelpers.js';
|
|
11
15
|
import { CodeGenerator } from './CodeGenerator.js';
|
|
16
|
+
import { ErrorHelpers } from './ErrorHelpers.js';
|
|
17
|
+
import { GetterDependencyExtractor } from './GetterDependencyExtractor.js';
|
|
18
|
+
import { Parse5Helpers } from './Parse5Helpers.js';
|
|
12
19
|
import { TemplateParser } from './TemplateParser.js';
|
|
13
20
|
export class ComponentCompiler {
|
|
14
21
|
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);
|
|
22
|
+
getReactivePropsForFile(filePath) {
|
|
23
|
+
const direct = reactivePropertiesMap.get(filePath);
|
|
24
|
+
if (direct) {
|
|
25
|
+
return direct;
|
|
26
|
+
}
|
|
27
|
+
for (const [key, value] of reactivePropertiesMap.entries()) {
|
|
28
|
+
if (key === filePath || key.endsWith(filePath) || filePath.endsWith(key)) {
|
|
29
|
+
return value;
|
|
33
30
|
}
|
|
34
31
|
}
|
|
32
|
+
return new Set();
|
|
35
33
|
}
|
|
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;
|
|
34
|
+
createTemplateParser(_filePath) {
|
|
35
|
+
return new TemplateParser();
|
|
36
|
+
}
|
|
37
|
+
async runBabelTransform(code, filePath, options) {
|
|
38
|
+
try {
|
|
39
|
+
const presets = options.useTypeScriptPreset
|
|
40
|
+
? [['@babel/preset-typescript', { isTSX: false, allExtensions: true }]]
|
|
41
|
+
: [];
|
|
42
|
+
const plugins = options.useDecoratorSyntax
|
|
43
|
+
? [['@babel/plugin-syntax-decorators', { version: '2023-11' }], ...options.plugins]
|
|
44
|
+
: options.plugins;
|
|
45
|
+
const parserOpts = options.useDecoratorSyntax
|
|
46
|
+
? { plugins: ['typescript', 'decorators'] }
|
|
47
|
+
: options.useTypeScriptPreset
|
|
48
|
+
? { plugins: ['typescript'] }
|
|
49
|
+
: undefined;
|
|
50
|
+
const result = await babel.transformAsync(code, {
|
|
51
|
+
filename: filePath,
|
|
52
|
+
presets,
|
|
53
|
+
plugins,
|
|
54
|
+
parserOpts
|
|
55
|
+
});
|
|
56
|
+
return result?.code ?? code;
|
|
61
57
|
}
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
catch (e) {
|
|
59
|
+
console.error(`${options.errorContext} in ${filePath}:`, ErrorHelpers.getErrorMessage(e));
|
|
60
|
+
return code;
|
|
64
61
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
}
|
|
63
|
+
async discoverComponents(dir) {
|
|
64
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
65
|
+
for (const entry of entries) {
|
|
66
|
+
const fullPath = path.join(dir, entry.name);
|
|
67
|
+
if (entry.isDirectory()) {
|
|
68
|
+
await this.discoverComponents(fullPath);
|
|
69
|
+
}
|
|
70
|
+
else if (entry.name.endsWith('.component.ts')) {
|
|
71
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
72
|
+
const metadata = await this.extractComponentMetadata(content, fullPath);
|
|
73
|
+
if (metadata?.selector) {
|
|
74
|
+
this.componentSelectors.add(metadata.selector);
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
}
|
|
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
78
|
}
|
|
90
|
-
async compileComponentForBundle(filePath, minify, sourcemap) {
|
|
79
|
+
async compileComponentForBundle(filePath, minify, sourcemap, skipDefine, production) {
|
|
91
80
|
let source = fs.readFileSync(filePath, 'utf-8');
|
|
92
81
|
const componentDir = path.dirname(filePath);
|
|
93
|
-
const
|
|
82
|
+
const parser = this.createTemplateParser(filePath);
|
|
83
|
+
reactivePropertiesMap.delete(filePath);
|
|
94
84
|
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());
|
|
85
|
+
source = await this.transformReactiveProperties(source, filePath, production);
|
|
103
86
|
}
|
|
104
87
|
const metadata = await this.extractComponentMetadata(source, filePath);
|
|
105
88
|
if (!metadata) {
|
|
@@ -126,32 +109,51 @@ export class ComponentCompiler {
|
|
|
126
109
|
else if (inlineStyles) {
|
|
127
110
|
styles = inlineStyles;
|
|
128
111
|
}
|
|
112
|
+
if (minify && styles) {
|
|
113
|
+
const cssResult = await esbuild.transform(styles, {
|
|
114
|
+
loader: 'css', minify: true
|
|
115
|
+
});
|
|
116
|
+
styles = cssResult.code;
|
|
117
|
+
}
|
|
118
|
+
const reactiveProps = this.getReactivePropsForFile(filePath);
|
|
119
|
+
const getterDepMap = GetterDependencyExtractor.extractGetterDependencyMap(source, reactiveProps);
|
|
120
|
+
parser.setGetterDependencyMap(getterDepMap);
|
|
121
|
+
const parsed = await parser.parse(templateHtml);
|
|
122
|
+
parser.setGetterDependencyMap(new Map());
|
|
123
|
+
const gen = new CodeGenerator(this.componentSelectors, selector);
|
|
124
|
+
let generatedHtml = gen.generateHtml(parsed);
|
|
129
125
|
if (minify) {
|
|
130
|
-
|
|
126
|
+
const fragment = parse5.parseFragment(generatedHtml);
|
|
127
|
+
Parse5Helpers.removeNonMarkerComments(fragment);
|
|
128
|
+
generatedHtml = parse5.serialize(fragment);
|
|
129
|
+
generatedHtml = await minifyHtml(generatedHtml, {
|
|
131
130
|
collapseWhitespace: true,
|
|
132
|
-
removeComments:
|
|
131
|
+
removeComments: false,
|
|
133
132
|
removeRedundantAttributes: true,
|
|
134
133
|
removeEmptyAttributes: true
|
|
135
134
|
});
|
|
136
|
-
if (styles) {
|
|
137
|
-
const cssResult = await esbuild.transform(styles, {
|
|
138
|
-
loader: 'css', minify: true
|
|
139
|
-
});
|
|
140
|
-
styles = cssResult.code;
|
|
141
|
-
}
|
|
142
135
|
}
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
const bindingsSetup = generator.generateBindingsSetup(bindings, controlFlows);
|
|
136
|
+
const markerConfigJson = gen.getMarkerConfigJson();
|
|
137
|
+
const renderMethod = gen.generateRenderMethodFromHtml(generatedHtml, styles, markerConfigJson);
|
|
138
|
+
const bindingsSetup = gen.generateBindingsSetup();
|
|
147
139
|
let result = await this.transformImportsForBundle(source, filePath);
|
|
148
140
|
result = await this.transformClass(result, filePath, {
|
|
149
141
|
className, originalSuperClass: 'HTMLElement', newSuperClass: 'FluffElement', injectMethods: [
|
|
150
142
|
{ name: '__render', body: renderMethod }, { name: '__setupBindings', body: bindingsSetup }
|
|
151
143
|
]
|
|
152
144
|
});
|
|
153
|
-
result =
|
|
154
|
-
|
|
145
|
+
result = this.addFluffImport(result);
|
|
146
|
+
const exprAssignments = gen.generateExpressionAssignments();
|
|
147
|
+
if (exprAssignments) {
|
|
148
|
+
result = this.appendCode(result, exprAssignments);
|
|
149
|
+
}
|
|
150
|
+
const bindingsMap = gen.getBindingsMap();
|
|
151
|
+
if (Object.keys(bindingsMap).length > 0) {
|
|
152
|
+
result = this.addBindingsMap(result, className, bindingsMap);
|
|
153
|
+
}
|
|
154
|
+
if (!skipDefine) {
|
|
155
|
+
result = this.addCustomElementsDefine(result, selector, className);
|
|
156
|
+
}
|
|
155
157
|
const tsResult = await this.stripTypeScriptWithSourceMap(result, filePath, sourcemap);
|
|
156
158
|
const watchFiles = [];
|
|
157
159
|
if (templatePath) {
|
|
@@ -178,78 +180,31 @@ export class ComponentCompiler {
|
|
|
178
180
|
return { code: result.code, map: result.map };
|
|
179
181
|
}
|
|
180
182
|
catch (e) {
|
|
181
|
-
|
|
182
|
-
console.error(`Error transforming ${filePath}:`, message);
|
|
183
|
+
console.error(`Error transforming ${filePath}:`, ErrorHelpers.getErrorMessage(e));
|
|
183
184
|
return { code };
|
|
184
185
|
}
|
|
185
186
|
}
|
|
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
187
|
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
|
-
}
|
|
188
|
+
const importOptions = {
|
|
189
|
+
removeImportsFrom: ['lighter'],
|
|
190
|
+
removeDecorators: ['Component', 'Input', 'Output'],
|
|
191
|
+
pathReplacements: {},
|
|
192
|
+
addJsExtension: false
|
|
193
|
+
};
|
|
194
|
+
return this.runBabelTransform(code, filePath, {
|
|
195
|
+
useTypeScriptPreset: true,
|
|
196
|
+
useDecoratorSyntax: true,
|
|
197
|
+
plugins: [[importsPlugin, importOptions]],
|
|
198
|
+
errorContext: 'Failed to transform imports'
|
|
199
|
+
});
|
|
234
200
|
}
|
|
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
|
-
}
|
|
201
|
+
async transformReactiveProperties(code, filePath = 'file.ts', production) {
|
|
202
|
+
return this.runBabelTransform(code, filePath, {
|
|
203
|
+
useTypeScriptPreset: true,
|
|
204
|
+
useDecoratorSyntax: true,
|
|
205
|
+
plugins: [[reactivePlugin, { production: production ?? false }]],
|
|
206
|
+
errorContext: 'Babel transform error'
|
|
207
|
+
});
|
|
253
208
|
}
|
|
254
209
|
async stripTypeScript(code, filePath = 'file.ts') {
|
|
255
210
|
try {
|
|
@@ -259,123 +214,104 @@ export class ComponentCompiler {
|
|
|
259
214
|
return result.code;
|
|
260
215
|
}
|
|
261
216
|
catch (e) {
|
|
262
|
-
|
|
263
|
-
console.error(`Error transforming ${filePath}:`, message);
|
|
217
|
+
console.error(`Error transforming ${filePath}:`, ErrorHelpers.getErrorMessage(e));
|
|
264
218
|
return code;
|
|
265
219
|
}
|
|
266
220
|
}
|
|
267
221
|
async extractComponentMetadata(code, filePath) {
|
|
268
222
|
try {
|
|
269
223
|
componentMetadataMap.delete(filePath);
|
|
270
|
-
await
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
], parserOpts: {
|
|
276
|
-
plugins: ['typescript', 'decorators']
|
|
277
|
-
}
|
|
224
|
+
await this.runBabelTransform(code, filePath, {
|
|
225
|
+
useTypeScriptPreset: true,
|
|
226
|
+
useDecoratorSyntax: true,
|
|
227
|
+
plugins: [componentPlugin],
|
|
228
|
+
errorContext: 'Failed to extract component metadata'
|
|
278
229
|
});
|
|
279
230
|
return componentMetadataMap.get(filePath) ?? null;
|
|
280
231
|
}
|
|
281
232
|
catch (e) {
|
|
282
|
-
|
|
283
|
-
console.error(`Failed to extract component metadata from ${filePath}:`, message);
|
|
233
|
+
console.error(`Failed to extract component metadata from ${filePath}:`, ErrorHelpers.getErrorMessage(e));
|
|
284
234
|
return null;
|
|
285
235
|
}
|
|
286
236
|
}
|
|
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
237
|
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
|
-
}
|
|
238
|
+
return this.runBabelTransform(code, filePath, {
|
|
239
|
+
useTypeScriptPreset: false,
|
|
240
|
+
useDecoratorSyntax: false,
|
|
241
|
+
plugins: [[classTransformPlugin, options]],
|
|
242
|
+
errorContext: 'Failed to transform class'
|
|
243
|
+
});
|
|
329
244
|
}
|
|
330
245
|
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
|
-
}
|
|
246
|
+
const importOptions = {
|
|
247
|
+
pathReplacements: {
|
|
248
|
+
'@/fluff-lib/': '../'
|
|
249
|
+
}, addJsExtension: true
|
|
250
|
+
};
|
|
251
|
+
return this.runBabelTransform(code, filePath, {
|
|
252
|
+
useTypeScriptPreset: true,
|
|
253
|
+
useDecoratorSyntax: false,
|
|
254
|
+
plugins: [[importsPlugin, importOptions]],
|
|
255
|
+
errorContext: 'Failed to transform library imports'
|
|
256
|
+
});
|
|
353
257
|
}
|
|
354
|
-
async
|
|
355
|
-
const
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
258
|
+
async createComponentSourceMap(code, esbuildMap, componentPath, templatePath, stylePath) {
|
|
259
|
+
const consumer = await new SourceMapConsumer(JSON.parse(esbuildMap));
|
|
260
|
+
const generator = new SourceMapGenerator({
|
|
261
|
+
file: path.basename(componentPath)
|
|
262
|
+
.replace('.ts', '.js')
|
|
263
|
+
});
|
|
264
|
+
generator.setSourceContent(componentPath, fs.readFileSync(componentPath, 'utf-8'));
|
|
265
|
+
generator.setSourceContent(templatePath, fs.readFileSync(templatePath, 'utf-8'));
|
|
266
|
+
if (stylePath && fs.existsSync(stylePath)) {
|
|
267
|
+
generator.setSourceContent(stylePath, fs.readFileSync(stylePath, 'utf-8'));
|
|
359
268
|
}
|
|
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
|
-
}
|
|
269
|
+
consumer.eachMapping(mapping => {
|
|
270
|
+
if (mapping.source) {
|
|
271
|
+
generator.addMapping({
|
|
272
|
+
generated: { line: mapping.generatedLine, column: mapping.generatedColumn },
|
|
273
|
+
original: { line: mapping.originalLine, column: mapping.originalColumn },
|
|
274
|
+
source: mapping.source,
|
|
275
|
+
name: mapping.name ?? undefined
|
|
276
|
+
});
|
|
378
277
|
}
|
|
278
|
+
});
|
|
279
|
+
consumer.destroy();
|
|
280
|
+
return generator.toString();
|
|
281
|
+
}
|
|
282
|
+
addFluffImport(code) {
|
|
283
|
+
const ast = parse(code, { sourceType: 'module' });
|
|
284
|
+
const importSpecifiers = [
|
|
285
|
+
t.importSpecifier(t.identifier('FluffBase'), t.identifier('FluffBase')),
|
|
286
|
+
t.importSpecifier(t.identifier('FluffElement'), t.identifier('FluffElement')),
|
|
287
|
+
t.importSpecifier(t.identifier('MarkerManager'), t.identifier('MarkerManager'))
|
|
288
|
+
];
|
|
289
|
+
const importDecl = t.importDeclaration(importSpecifiers, t.stringLiteral('@fluffjs/fluff'));
|
|
290
|
+
ast.program.body.unshift(importDecl);
|
|
291
|
+
return generate(ast, { compact: false }).code;
|
|
292
|
+
}
|
|
293
|
+
appendCode(code, additionalCode) {
|
|
294
|
+
const ast = parse(code, { sourceType: 'module' });
|
|
295
|
+
const additionalAst = parse(additionalCode, { sourceType: 'module' });
|
|
296
|
+
ast.program.body.push(...additionalAst.program.body);
|
|
297
|
+
return generate(ast, { compact: false }).code;
|
|
298
|
+
}
|
|
299
|
+
addBindingsMap(code, className, bindingsMap) {
|
|
300
|
+
const ast = parse(code, { sourceType: 'module' });
|
|
301
|
+
const jsonStr = JSON.stringify(bindingsMap);
|
|
302
|
+
const valueAst = parse(`(${jsonStr})`, { sourceType: 'module' });
|
|
303
|
+
const [valueStmt] = valueAst.program.body;
|
|
304
|
+
if (!t.isExpressionStatement(valueStmt)) {
|
|
305
|
+
return code;
|
|
379
306
|
}
|
|
307
|
+
const assignment = t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(className), t.identifier('__bindings')), valueStmt.expression));
|
|
308
|
+
ast.program.body.push(assignment);
|
|
309
|
+
return generate(ast, { compact: false }).code;
|
|
310
|
+
}
|
|
311
|
+
addCustomElementsDefine(code, selector, className) {
|
|
312
|
+
const ast = parse(code, { sourceType: 'module' });
|
|
313
|
+
const defineCall = t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('customElements'), t.identifier('define')), [t.stringLiteral(selector), t.identifier(className)]));
|
|
314
|
+
ast.program.body.push(defineCall);
|
|
315
|
+
return generate(ast, { compact: false }).code;
|
|
380
316
|
}
|
|
381
317
|
}
|
|
@@ -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
|