@fluffjs/cli 0.4.4 → 0.5.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 (47) hide show
  1. package/BabelHelpers.js +8 -5
  2. package/Cli.d.ts +9 -5
  3. package/Cli.js +218 -155
  4. package/CodeGenerator.d.ts +19 -10
  5. package/CodeGenerator.js +146 -106
  6. package/ComponentCompiler.d.ts +19 -3
  7. package/ComponentCompiler.js +175 -47
  8. package/DevServer.d.ts +6 -4
  9. package/DevServer.js +102 -23
  10. package/DomPreProcessor.js +22 -40
  11. package/IndexHtmlTransformer.js +20 -28
  12. package/PluginLoader.d.ts +22 -0
  13. package/PluginLoader.js +286 -0
  14. package/PluginManager.d.ts +39 -0
  15. package/PluginManager.js +209 -0
  16. package/TemplateParser.d.ts +5 -0
  17. package/TemplateParser.js +55 -0
  18. package/babel-plugin-directive.d.ts +12 -0
  19. package/babel-plugin-directive.js +78 -0
  20. package/babel-plugin-reactive.js +19 -14
  21. package/fluff-esbuild-plugin.js +66 -22
  22. package/interfaces/ClassTransformContext.d.ts +8 -0
  23. package/interfaces/ClassTransformContext.js +1 -0
  24. package/interfaces/CodeGenContext.d.ts +9 -0
  25. package/interfaces/CodeGenContext.js +1 -0
  26. package/interfaces/DiscoveryInfo.d.ts +15 -0
  27. package/interfaces/DiscoveryInfo.js +1 -0
  28. package/interfaces/EntryPointContext.d.ts +6 -0
  29. package/interfaces/EntryPointContext.js +1 -0
  30. package/interfaces/FluffConfigInterface.d.ts +2 -0
  31. package/interfaces/FluffPlugin.d.ts +26 -0
  32. package/interfaces/FluffPlugin.js +1 -0
  33. package/interfaces/FluffPluginOptions.d.ts +3 -0
  34. package/interfaces/FluffTarget.d.ts +1 -0
  35. package/interfaces/HtmlTransformOptions.d.ts +2 -0
  36. package/interfaces/PluginCustomTable.d.ts +6 -0
  37. package/interfaces/PluginCustomTable.js +1 -0
  38. package/interfaces/PluginHookDependency.d.ts +5 -0
  39. package/interfaces/PluginHookDependency.js +1 -0
  40. package/interfaces/PluginHookName.d.ts +2 -0
  41. package/interfaces/PluginHookName.js +1 -0
  42. package/interfaces/ScopeElementConfig.d.ts +5 -0
  43. package/interfaces/ScopeElementConfig.js +1 -0
  44. package/interfaces/index.d.ts +8 -0
  45. package/package.json +5 -3
  46. package/PeerDependencies.d.ts +0 -6
  47. package/PeerDependencies.js +0 -7
package/TemplateParser.js CHANGED
@@ -10,10 +10,14 @@ export class TemplateParser {
10
10
  templateRefs = new Set();
11
11
  scopeStack = [];
12
12
  getterDependencyMap = new Map();
13
+ scopeElements = [];
13
14
  testYieldBeforeGetterDepsLookup = null;
14
15
  setGetterDependencyMap(map) {
15
16
  this.getterDependencyMap = map;
16
17
  }
18
+ setScopeElements(configs) {
19
+ this.scopeElements = configs;
20
+ }
17
21
  __setTestYieldBeforeGetterDepsLookup(callback) {
18
22
  this.testYieldBeforeGetterDepsLookup = callback;
19
23
  }
@@ -193,8 +197,59 @@ export class TemplateParser {
193
197
  else if (tagName === 'x-fluff-text') {
194
198
  return this.processTextElement(element);
195
199
  }
200
+ const scopeConfig = this.findScopeElementConfig(element);
201
+ if (scopeConfig) {
202
+ return this.processScopedElement(element, scopeConfig);
203
+ }
196
204
  return this.processRegularElement(element);
197
205
  }
206
+ findScopeElementConfig(element) {
207
+ for (const config of this.scopeElements) {
208
+ if (element.tagName === config.tagName && this.getAttr(element, config.letAttribute) !== null) {
209
+ return config;
210
+ }
211
+ }
212
+ return null;
213
+ }
214
+ async processScopedElement(element, config) {
215
+ const scopeVariable = this.getAttr(element, config.letAttribute) ?? '';
216
+ const bindings = [];
217
+ const attributes = {};
218
+ let hasBindings = false;
219
+ for (const attr of element.attrs) {
220
+ if (attr.name === config.letAttribute) {
221
+ continue;
222
+ }
223
+ if (attr.name.startsWith('x-fluff-attrib-')) {
224
+ const bindingInfo = await this.parseBindingAttribute(attr.value);
225
+ if (bindingInfo) {
226
+ bindings.push(bindingInfo);
227
+ hasBindings = true;
228
+ if (bindingInfo.binding === 'ref') {
229
+ this.templateRefs.add(bindingInfo.name);
230
+ }
231
+ }
232
+ }
233
+ else {
234
+ attributes[attr.name] = attr.value;
235
+ }
236
+ }
237
+ this.pushScope(scopeVariable.split(',').map(v => v.trim()).filter(v => v.length > 0));
238
+ const children = await this.processNodes(element.childNodes ?? []);
239
+ this.popScope();
240
+ const node = {
241
+ type: 'element',
242
+ tagName: element.tagName,
243
+ attributes,
244
+ bindings,
245
+ children,
246
+ namespaceURI: element.namespaceURI
247
+ };
248
+ if (hasBindings) {
249
+ node.id = `l${this.bindingId++}`;
250
+ }
251
+ return node;
252
+ }
198
253
  async processForElement(element) {
199
254
  const iterator = this.getAttr(element, 'x-fluff-iterator') ?? 'item';
200
255
  const iterableRaw = this.getAttr(element, 'x-fluff-iterable') ?? '';
@@ -0,0 +1,12 @@
1
+ import type { PluginObj } from '@babel/core';
2
+ export interface DirectiveMetadata {
3
+ selector: string;
4
+ className: string;
5
+ }
6
+ interface BabelPluginDirectiveState {
7
+ filename?: string;
8
+ }
9
+ export declare const directiveMetadataMap: Map<string, DirectiveMetadata>;
10
+ export default function directivePlugin(): PluginObj<BabelPluginDirectiveState>;
11
+ export {};
12
+ //# sourceMappingURL=babel-plugin-directive.d.ts.map
@@ -0,0 +1,78 @@
1
+ import { types as t } from '@babel/core';
2
+ export const directiveMetadataMap = new Map();
3
+ function getDecoratorName(decorator) {
4
+ if (t.isCallExpression(decorator.expression) && t.isIdentifier(decorator.expression.callee)) {
5
+ return decorator.expression.callee.name;
6
+ }
7
+ if (t.isIdentifier(decorator.expression)) {
8
+ return decorator.expression.name;
9
+ }
10
+ return null;
11
+ }
12
+ export default function directivePlugin() {
13
+ return {
14
+ name: 'babel-plugin-directive', visitor: {
15
+ ClassDeclaration(path, state) {
16
+ const decorators = path.node.decorators ?? [];
17
+ const directiveDecorator = decorators.find(dec => {
18
+ if (t.isCallExpression(dec.expression)) {
19
+ const { callee } = dec.expression;
20
+ return t.isIdentifier(callee) && callee.name === 'Directive';
21
+ }
22
+ return false;
23
+ });
24
+ if (!directiveDecorator)
25
+ return;
26
+ if (!t.isCallExpression(directiveDecorator.expression))
27
+ return;
28
+ const args = directiveDecorator.expression.arguments;
29
+ if (args.length === 0)
30
+ return;
31
+ const [configArg] = args;
32
+ if (!t.isObjectExpression(configArg))
33
+ return;
34
+ const metadata = {};
35
+ if (path.node.id) {
36
+ metadata.className = path.node.id.name;
37
+ }
38
+ for (const prop of configArg.properties) {
39
+ if (!t.isObjectProperty(prop))
40
+ continue;
41
+ if (!t.isIdentifier(prop.key))
42
+ continue;
43
+ const key = prop.key.name;
44
+ const { value } = prop;
45
+ if (key === 'selector' && t.isStringLiteral(value)) {
46
+ metadata.selector = value.value;
47
+ }
48
+ }
49
+ const filename = state.filename ?? 'unknown';
50
+ if (metadata.selector && metadata.className) {
51
+ directiveMetadataMap.set(filename, {
52
+ selector: metadata.selector,
53
+ className: metadata.className
54
+ });
55
+ }
56
+ const hostElementProps = [];
57
+ const classBody = path.node.body.body;
58
+ for (const member of classBody) {
59
+ if (!t.isClassProperty(member))
60
+ continue;
61
+ if (!t.isIdentifier(member.key))
62
+ continue;
63
+ const memberDecorators = member.decorators ?? [];
64
+ const hostElementDecIdx = memberDecorators.findIndex(dec => getDecoratorName(dec) === 'HostElement');
65
+ if (hostElementDecIdx !== -1) {
66
+ hostElementProps.push(member.key.name);
67
+ memberDecorators.splice(hostElementDecIdx, 1);
68
+ }
69
+ }
70
+ if (hostElementProps.length > 0) {
71
+ const assignments = hostElementProps.map(propName => t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.thisExpression(), t.identifier(propName)), t.identifier('hostElement'))));
72
+ const setHostElementMethod = t.classMethod('method', t.identifier('__assignHostElementProps'), [t.identifier('hostElement')], t.blockStatement(assignments), false, false);
73
+ classBody.push(setHostElementMethod);
74
+ }
75
+ }
76
+ }
77
+ };
78
+ }
@@ -356,6 +356,20 @@ export default function reactivePlugin() {
356
356
  propsToRemove.push(memberPath);
357
357
  privateFields.push(privateField);
358
358
  }
359
+ const reactiveProps = state.reactiveProperties ?? new Set();
360
+ const constructorStatements = [];
361
+ for (const { propName, className, privateName } of classHostBindingDefs) {
362
+ constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('__defineClassHostBinding')), [t.stringLiteral(propName), t.stringLiteral(className), t.stringLiteral(privateName)])));
363
+ }
364
+ const initHostBindingsStatements = [];
365
+ for (const { updateMethodName, watchedProps } of getterHostBindingUpdates) {
366
+ initHostBindingsStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier(updateMethodName)), [])));
367
+ for (const prop of watchedProps) {
368
+ if (reactiveProps.has(prop)) {
369
+ initHostBindingsStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier('__baseSubscriptions')), t.identifier('push')), [t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier(`__${prop}`)), t.identifier('onChange')), t.identifier('subscribe')), [t.arrowFunctionExpression([], t.callExpression(t.memberExpression(t.thisExpression(), t.identifier(updateMethodName)), []))])])));
370
+ }
371
+ }
372
+ }
359
373
  for (const p of propsToRemove) {
360
374
  p.remove();
361
375
  }
@@ -398,19 +412,6 @@ export default function reactivePlugin() {
398
412
  }
399
413
  }
400
414
  }
401
- const reactiveProps = state.reactiveProperties ?? new Set();
402
- const constructorStatements = [];
403
- for (const { propName, className, privateName } of classHostBindingDefs) {
404
- constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('__defineClassHostBinding')), [t.stringLiteral(propName), t.stringLiteral(className), t.stringLiteral(privateName)])));
405
- }
406
- for (const { updateMethodName, watchedProps } of getterHostBindingUpdates) {
407
- constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier(updateMethodName)), [])));
408
- for (const prop of watchedProps) {
409
- if (reactiveProps.has(prop)) {
410
- constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier('__baseSubscriptions')), t.identifier('push')), [t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier(`__${prop}`)), t.identifier('onChange')), t.identifier('subscribe')), [t.arrowFunctionExpression([], t.callExpression(t.memberExpression(t.thisExpression(), t.identifier(updateMethodName)), []))])])));
411
- }
412
- }
413
- }
414
415
  for (const { propName, privateName } of propertyHostBindingInits) {
415
416
  constructorStatements.push(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.thisExpression(), t.identifier(propName)), t.memberExpression(t.thisExpression(), t.identifier(privateName)))));
416
417
  }
@@ -477,7 +478,7 @@ export default function reactivePlugin() {
477
478
  }
478
479
  const handlerFn = t.arrowFunctionExpression([t.identifier('__ev')], t.blockStatement([handlerBody]));
479
480
  if (target === 'this') {
480
- constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('addEventListener')), [
481
+ initHostBindingsStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('__getHostElement')), []), t.identifier('addEventListener')), [
481
482
  t.stringLiteral(baseEvent),
482
483
  handlerFn
483
484
  ])));
@@ -493,6 +494,10 @@ export default function reactivePlugin() {
493
494
  globalListenerCleanups.push(t.expressionStatement(t.callExpression(t.memberExpression(target === 'document' ? t.identifier('document') : t.identifier('window'), t.identifier('removeEventListener')), [t.stringLiteral(baseEvent), t.memberExpression(t.thisExpression(), t.identifier(handlerPropName))])));
494
495
  }
495
496
  }
497
+ if (initHostBindingsStatements.length > 0) {
498
+ const initHostBindingsMethod = t.classMethod('method', t.identifier('__initHostBindings'), [], t.blockStatement(initHostBindingsStatements));
499
+ path.unshiftContainer('body', initHostBindingsMethod);
500
+ }
496
501
  if (constructorStatements.length > 0) {
497
502
  const constructor = path.node.body.find((m) => t.isClassMethod(m) && m.kind === 'constructor');
498
503
  if (constructor) {
@@ -1,8 +1,8 @@
1
+ import { parse } from '@babel/parser';
2
+ import * as t from '@babel/types';
1
3
  import * as fs from 'fs';
2
4
  import * as path from 'path';
3
5
  import { fileURLToPath } from 'url';
4
- import { parse } from '@babel/parser';
5
- import * as t from '@babel/types';
6
6
  import { generate } from './BabelHelpers.js';
7
7
  import { CodeGenerator } from './CodeGenerator.js';
8
8
  import { ComponentCompiler } from './ComponentCompiler.js';
@@ -31,11 +31,10 @@ function getEntryPointPath(build) {
31
31
  return null;
32
32
  }
33
33
  function detectDecorators(source) {
34
- const result = { hasComponent: false, hasPipe: false };
34
+ const result = { hasComponent: false, hasDirective: false, hasPipe: false };
35
35
  try {
36
36
  const ast = parse(source, {
37
- sourceType: 'module',
38
- plugins: ['typescript', 'decorators']
37
+ sourceType: 'module', plugins: ['typescript', 'decorators']
39
38
  });
40
39
  for (const node of ast.program.body) {
41
40
  if (t.isClassDeclaration(node) && node.decorators) {
@@ -44,6 +43,8 @@ function detectDecorators(source) {
44
43
  const { name } = decorator.expression.callee;
45
44
  if (name === 'Component')
46
45
  result.hasComponent = true;
46
+ if (name === 'Directive')
47
+ result.hasDirective = true;
47
48
  if (name === 'Pipe')
48
49
  result.hasPipe = true;
49
50
  }
@@ -55,6 +56,8 @@ function detectDecorators(source) {
55
56
  const { name } = decorator.expression.callee;
56
57
  if (name === 'Component')
57
58
  result.hasComponent = true;
59
+ if (name === 'Directive')
60
+ result.hasDirective = true;
58
61
  if (name === 'Pipe')
59
62
  result.hasPipe = true;
60
63
  }
@@ -66,6 +69,8 @@ function detectDecorators(source) {
66
69
  const { name } = decorator.expression.callee;
67
70
  if (name === 'Component')
68
71
  result.hasComponent = true;
72
+ if (name === 'Directive')
73
+ result.hasDirective = true;
69
74
  if (name === 'Pipe')
70
75
  result.hasPipe = true;
71
76
  }
@@ -82,20 +87,35 @@ export function fluffPlugin(options) {
82
87
  const fluffSrcPath = findFluffSourcePath();
83
88
  const compiledCache = new Map();
84
89
  let entryPointPath = null;
90
+ const { pluginManager } = options;
91
+ if (pluginManager) {
92
+ compiler.setPluginManager(pluginManager);
93
+ }
85
94
  // noinspection JSUnusedGlobalSymbols
86
95
  return {
87
- name: 'fluff',
88
- setup(build) {
96
+ name: 'fluff', setup(build) {
89
97
  entryPointPath = getEntryPointPath(build);
90
98
  build.onStart(async () => {
91
99
  CodeGenerator.resetGlobalState();
92
100
  compiledCache.clear();
93
101
  const componentPaths = await compiler.discoverComponents(options.srcDir);
102
+ if (pluginManager?.hasPlugins) {
103
+ await pluginManager.runAfterDiscovery({
104
+ components: componentPaths.flatMap(p => {
105
+ const metadata = compiler.getComponentMetadata(p);
106
+ return metadata ? [{ filePath: p, metadata }] : [];
107
+ }),
108
+ directives: compiler.getDirectivePaths()
109
+ .flatMap(p => {
110
+ const metadata = compiler.getDirectiveMetadata(p);
111
+ return metadata ? [{ filePath: p, metadata }] : [];
112
+ })
113
+ });
114
+ }
94
115
  for (const componentPath of componentPaths) {
95
116
  const result = await compiler.compileComponentForBundle(componentPath, options.minify, options.sourcemap, options.skipDefine, options.production);
96
117
  compiledCache.set(componentPath, {
97
- code: result.code,
98
- watchFiles: result.watchFiles
118
+ code: result.code, watchFiles: result.watchFiles
99
119
  });
100
120
  }
101
121
  });
@@ -120,40 +140,64 @@ export function fluffPlugin(options) {
120
140
  watchFiles: result.watchFiles
121
141
  };
122
142
  }
143
+ if (decorators.hasDirective) {
144
+ const result = await compiler.compileDirectiveForBundle(args.path, options.sourcemap, options.production);
145
+ return {
146
+ contents: result.code, loader: 'js', resolveDir: path.dirname(args.path)
147
+ };
148
+ }
123
149
  if (decorators.hasPipe) {
124
150
  const transformed = await compiler.transformPipeDecorators(source, args.path);
125
151
  DecoratorValidator.validate(transformed, args.path);
126
152
  return {
127
- contents: transformed,
128
- loader: 'ts',
129
- resolveDir: path.dirname(args.path)
153
+ contents: transformed, loader: 'ts', resolveDir: path.dirname(args.path)
130
154
  };
131
155
  }
132
156
  if (!entryPointPath || args.path !== entryPointPath) {
133
157
  return null;
134
158
  }
135
159
  const ast = parse(source, {
136
- sourceType: 'module',
137
- plugins: ['typescript', 'decorators']
160
+ sourceType: 'module', plugins: ['typescript', 'decorators']
138
161
  });
139
162
  const exprTableImport = t.importDeclaration([], t.stringLiteral(VIRTUAL_EXPR_TABLE_ID));
140
163
  ast.program.body.unshift(exprTableImport);
141
164
  const output = generate(ast, { compact: false });
142
165
  return {
143
- contents: output.code,
144
- loader: 'ts',
145
- resolveDir: path.dirname(args.path)
166
+ contents: output.code, loader: 'ts', resolveDir: path.dirname(args.path)
146
167
  };
147
168
  });
148
169
  build.onResolve({ filter: new RegExp(`^${VIRTUAL_EXPR_TABLE_ID.replace('/', '\\/')}$`) }, () => {
149
170
  return { path: VIRTUAL_EXPR_TABLE_ID, namespace: 'fluff-virtual' };
150
171
  });
151
- build.onLoad({ filter: /.*/, namespace: 'fluff-virtual' }, () => {
152
- const exprTable = CodeGenerator.generateGlobalExprTable();
172
+ build.onLoad({ filter: /.*/, namespace: 'fluff-virtual' }, async () => {
173
+ const directivePaths = compiler.getDirectivePaths();
174
+ const directiveImports = directivePaths.map(p => `import '${p}';`)
175
+ .join('\n');
176
+ const exprTable = CodeGenerator.generateGlobalExprTable(pluginManager);
177
+ let runtimeImports = '';
178
+ if (pluginManager?.hasPlugins) {
179
+ const imports = pluginManager.collectRuntimeImports();
180
+ runtimeImports = imports.map(imp => `import '${imp}';`)
181
+ .join('\n');
182
+ }
183
+ let globalStylesCode = '';
184
+ if (options.globalStylesCss) {
185
+ const escapedCss = options.globalStylesCss.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
186
+ globalStylesCode = 'import { FluffElement } from \'@fluffjs/fluff\';\n' +
187
+ 'const __fluffGlobalSheet = new CSSStyleSheet();\n' +
188
+ `__fluffGlobalSheet.replaceSync(\`${escapedCss}\`);\n` +
189
+ 'FluffElement.__addGlobalStyleSheet(__fluffGlobalSheet);\n';
190
+ }
191
+ let entryContent = directiveImports + '\n' + runtimeImports + '\n' + globalStylesCode + (exprTable || '');
192
+ if (pluginManager?.hasPlugins) {
193
+ const entryAst = parse(entryContent, { sourceType: 'module' });
194
+ await pluginManager.runModifyEntryPoint({
195
+ program: entryAst.program, srcDir: options.srcDir
196
+ });
197
+ entryContent = generate(entryAst, { compact: false }).code;
198
+ }
153
199
  return {
154
- contents: exprTable || '',
155
- loader: 'js',
156
- resolveDir: options.srcDir
200
+ contents: entryContent, loader: 'js', resolveDir: options.srcDir
157
201
  };
158
202
  });
159
203
  if (fluffSrcPath) {
@@ -0,0 +1,8 @@
1
+ import type * as t from '@babel/types';
2
+ import type { ComponentMetadata } from './ComponentMetadata.js';
3
+ export interface ClassTransformContext {
4
+ ast: t.File;
5
+ filePath: string;
6
+ metadata: ComponentMetadata;
7
+ }
8
+ //# sourceMappingURL=ClassTransformContext.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import type * as parse5 from 'parse5';
2
+ import type { CompactBinding } from '../CodeGenerator.js';
3
+ export interface CodeGenContext {
4
+ componentSelector: string;
5
+ generatedFragment: parse5.DefaultTreeAdapterMap['documentFragment'];
6
+ markerConfigs: Map<number, unknown>;
7
+ bindingsMap: Map<string, CompactBinding[]>;
8
+ }
9
+ //# sourceMappingURL=CodeGenContext.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { ComponentMetadata } from './ComponentMetadata.js';
2
+ import type { DirectiveMetadata } from '../babel-plugin-directive.js';
3
+ export interface DiscoveryInfo {
4
+ components: ComponentDiscoveryEntry[];
5
+ directives: DirectiveDiscoveryEntry[];
6
+ }
7
+ export interface ComponentDiscoveryEntry {
8
+ filePath: string;
9
+ metadata: ComponentMetadata;
10
+ }
11
+ export interface DirectiveDiscoveryEntry {
12
+ filePath: string;
13
+ metadata: DirectiveMetadata;
14
+ }
15
+ //# sourceMappingURL=DiscoveryInfo.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import type * as t from '@babel/types';
2
+ export interface EntryPointContext {
3
+ program: t.Program;
4
+ srcDir: string;
5
+ }
6
+ //# sourceMappingURL=EntryPointContext.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -3,5 +3,7 @@ export interface FluffConfig {
3
3
  version: string;
4
4
  targets: Record<string, FluffTarget>;
5
5
  defaultTarget?: string;
6
+ plugins?: string[];
7
+ pluginConfig?: Record<string, Record<string, unknown>>;
6
8
  }
7
9
  //# sourceMappingURL=FluffConfigInterface.d.ts.map
@@ -0,0 +1,26 @@
1
+ import type * as parse5 from 'parse5';
2
+ import type { FluffConfig } from './FluffConfigInterface.js';
3
+ import type { DiscoveryInfo } from './DiscoveryInfo.js';
4
+ import type { ParsedTemplate } from './ParsedTemplate.js';
5
+ import type { CodeGenContext } from './CodeGenContext.js';
6
+ import type { ClassTransformContext } from './ClassTransformContext.js';
7
+ import type { EntryPointContext } from './EntryPointContext.js';
8
+ import type { PluginHookName } from './PluginHookName.js';
9
+ import type { PluginCustomTable } from './PluginCustomTable.js';
10
+ import type { ScopeElementConfig } from './ScopeElementConfig.js';
11
+ export interface FluffPlugin {
12
+ readonly name: string;
13
+ dependencies?: Partial<Record<PluginHookName, string[]>>;
14
+ afterConfig?: (config: FluffConfig, pluginConfig: Record<string, unknown>) => void | Promise<void>;
15
+ afterDiscovery?: (discovery: DiscoveryInfo) => void | Promise<void>;
16
+ beforeTemplatePreProcess?: (fragment: parse5.DefaultTreeAdapterMap['documentFragment'], componentSelector: string) => void | Promise<void>;
17
+ afterTemplateParse?: (template: ParsedTemplate, componentSelector: string) => void | Promise<void>;
18
+ afterCodeGeneration?: (context: CodeGenContext) => void | Promise<void>;
19
+ beforeClassTransform?: (context: ClassTransformContext) => void | Promise<void>;
20
+ modifyEntryPoint?: (context: EntryPointContext) => void | Promise<void>;
21
+ modifyIndexHtml?: (document: parse5.DefaultTreeAdapterMap['document']) => void | Promise<void>;
22
+ registerRuntimeImports?: () => string[];
23
+ registerCustomTables?: () => PluginCustomTable[];
24
+ registerScopeElements?: () => ScopeElementConfig[];
25
+ }
26
+ //# sourceMappingURL=FluffPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { PluginManager } from '../PluginManager.js';
1
2
  export interface FluffPluginOptions {
2
3
  srcDir: string;
3
4
  outDir?: string;
@@ -5,5 +6,7 @@ export interface FluffPluginOptions {
5
6
  sourcemap?: boolean;
6
7
  skipDefine?: boolean;
7
8
  production?: boolean;
9
+ pluginManager?: PluginManager;
10
+ globalStylesCss?: string;
8
11
  }
9
12
  //# sourceMappingURL=FluffPluginOptions.d.ts.map
@@ -10,6 +10,7 @@ export interface FluffTarget {
10
10
  exclude?: string[];
11
11
  indexHtml?: string;
12
12
  styles?: string[];
13
+ globalStyles?: string[];
13
14
  assets?: string[];
14
15
  bundle?: BundleOptions;
15
16
  serve?: ServeOptions;
@@ -1,3 +1,4 @@
1
+ import type { PluginManager } from '../PluginManager.js';
1
2
  export interface HtmlTransformOptions {
2
3
  jsBundle: string;
3
4
  cssBundle?: string;
@@ -6,5 +7,6 @@ export interface HtmlTransformOptions {
6
7
  gzScriptTag?: boolean;
7
8
  minify?: boolean;
8
9
  liveReload?: boolean;
10
+ pluginManager?: PluginManager;
9
11
  }
10
12
  //# sourceMappingURL=HtmlTransformOptions.d.ts.map
@@ -0,0 +1,6 @@
1
+ import type * as t from '@babel/types';
2
+ export interface PluginCustomTable {
3
+ name: string;
4
+ elements: t.Expression[];
5
+ }
6
+ //# sourceMappingURL=PluginCustomTable.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export interface PluginHookDependency {
2
+ pluginName?: string;
3
+ hookName?: string;
4
+ }
5
+ //# sourceMappingURL=PluginHookDependency.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export type PluginHookName = 'afterConfig' | 'afterDiscovery' | 'beforeTemplatePreProcess' | 'afterTemplateParse' | 'afterCodeGeneration' | 'beforeClassTransform' | 'modifyEntryPoint' | 'modifyIndexHtml' | 'registerRuntimeImports' | 'registerCustomTables' | 'registerScopeElements';
2
+ //# sourceMappingURL=PluginHookName.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export interface ScopeElementConfig {
2
+ readonly tagName: string;
3
+ readonly letAttribute: string;
4
+ }
5
+ //# sourceMappingURL=ScopeElementConfig.d.ts.map
@@ -0,0 +1 @@
1
+ export {};
@@ -1,21 +1,28 @@
1
1
  export type { BindingInfo } from './BindingInfo.js';
2
2
  export type { BreakNode } from './BreakNode.js';
3
3
  export type { BundleOptions } from './BundleOptions.js';
4
+ export type { ClassTransformContext } from './ClassTransformContext.js';
4
5
  export type { CliOptions } from './CliOptions.js';
5
6
  export type { ClassTransformOptions } from './ClassTransformOptions.js';
7
+ export type { CodeGenContext } from './CodeGenContext.js';
6
8
  export type { CommentNode } from './CommentNode.js';
7
9
  export type { CompileResult } from './CompileResult.js';
8
10
  export type { CompilerOptions } from './CompilerOptions.js';
11
+ export type { ComponentDiscoveryEntry, DirectiveDiscoveryEntry, DiscoveryInfo } from './DiscoveryInfo.js';
9
12
  export type { ComponentInfo } from './ComponentInfo.js';
10
13
  export type { ComponentMetadata } from './ComponentMetadata.js';
11
14
  export type { ControlFlow, SwitchCaseOld } from './ControlFlow.js';
12
15
  export type { ControlFlowNode } from './ControlFlowNode.js';
13
16
  export type { ElementNode } from './ElementNode.js';
17
+ export type { EntryPointContext } from './EntryPointContext.js';
14
18
  export type { FluffConfig } from './FluffConfigInterface.js';
19
+ export type { FluffPlugin } from './FluffPlugin.js';
15
20
  export type { FluffPluginOptions } from './FluffPluginOptions.js';
16
21
  export type { FluffTarget } from './FluffTarget.js';
17
22
  export type { ForNode } from './ForNode.js';
18
23
  export type { HtmlTransformOptions } from './HtmlTransformOptions.js';
24
+ export type { PluginCustomTable } from './PluginCustomTable.js';
25
+ export type { PluginHookName } from './PluginHookName.js';
19
26
  export type { IfBranch } from './IfBranch.js';
20
27
  export type { IfNode } from './IfNode.js';
21
28
  export type { ImportTransformOptions } from './ImportTransformOptions.js';
@@ -24,6 +31,7 @@ export type { ParsedTemplate } from './ParsedTemplate.js';
24
31
  export type { ParsedTemplateOld } from './ParsedTemplateOld.js';
25
32
  export type { PropertyChain } from './PropertyChain.js';
26
33
  export type { Scope } from './Scope.js';
34
+ export type { ScopeElementConfig } from './ScopeElementConfig.js';
27
35
  export type { ServeOptions } from './ServeOptions.js';
28
36
  export type { SwitchCase } from './SwitchCase.js';
29
37
  export type { SwitchNode } from './SwitchNode.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluffjs/cli",
3
- "version": "0.4.4",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",
@@ -40,12 +40,14 @@
40
40
  "picomatch": "^4.0.2",
41
41
  "postcss": "^8.5.6",
42
42
  "source-map": "^0.7.6",
43
- "tslib": "^2.3.0"
43
+ "tslib": "^2.3.0",
44
+ "ws": "^8.19.0"
44
45
  },
45
46
  "devDependencies": {
46
47
  "@types/he": "^1.2.3",
47
48
  "@types/http-proxy": "^1.17.16",
48
- "@types/jsesc": "^3.0.3"
49
+ "@types/jsesc": "^3.0.3",
50
+ "@types/ws": "^8.18.1"
49
51
  },
50
52
  "publishConfig": {
51
53
  "access": "public"
@@ -1,6 +0,0 @@
1
- export interface PeerDependency {
2
- name: string;
3
- version: string;
4
- }
5
- export declare function getCliPeerDependencies(): PeerDependency[];
6
- //# sourceMappingURL=PeerDependencies.d.ts.map
@@ -1,7 +0,0 @@
1
- export function getCliPeerDependencies() {
2
- return [
3
- { name: 'cssnano', version: '^7.1.2' },
4
- { name: 'postcss', version: '^8.5.6' },
5
- { name: 'jsesc', version: '^3.1.0' }
6
- ];
7
- }