!158 feat(transpiler): add packageName options
* fix: transpiler * feat(transpiler): add packageName options * chore: remove dist
This commit is contained in:
parent
553613bbc6
commit
2640177de5
|
@ -4,5 +4,7 @@
|
|||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
/packages/**/node_modules
|
||||
dist
|
||||
# to ignore all dist folders in all levels
|
||||
**/dist
|
||||
.history
|
||||
dumped*
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"scripts": {
|
||||
"test": "vitest --ui",
|
||||
"bench": "vitest bench",
|
||||
"dump-test": "babel tests --out-dir dumped-tests --extensions .tsx --presets=babel-preset-inula-jsx --copy-files --out-file-extension .ts"
|
||||
"dump-test": "babel tests --out-dir dumped-tests --extensions .ts,.tsx --presets babel-preset-inula-jsx --copy-files --out-file-extension .ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/cli": "^7.23.9",
|
||||
|
|
|
@ -26,7 +26,7 @@ export default defineConfig({
|
|||
},
|
||||
plugins: [
|
||||
// @ts-expect-error TODO: fix vite plugin interface is not compatible
|
||||
inula(),
|
||||
inula({ packageName: 'inula-reactive' }),
|
||||
],
|
||||
test: {
|
||||
environment: 'jsdom', // or 'jsdom', 'node'
|
||||
|
|
|
@ -8,7 +8,7 @@ import { attributeMap, htmlTags, importMap } from './const';
|
|||
|
||||
|
||||
export class PluginProvider {
|
||||
private static readonly inulaPackageName = 'inula-reactive';
|
||||
private inulaPackageName = 'inula-reactive';
|
||||
// ---- Plugin Level ----
|
||||
private readonly babelApi: typeof babel
|
||||
private readonly t: typeof t
|
||||
|
@ -34,6 +34,7 @@ export class PluginProvider {
|
|||
this.htmlTags = options.htmlTags ?? htmlTags;
|
||||
this.parseTemplate = options.parseTemplate ?? true;
|
||||
this.attributeMap = options.attributeMap ?? attributeMap;
|
||||
options.packageName && (this.inulaPackageName = options.packageName);
|
||||
}
|
||||
|
||||
// ---- Two levels of enter:
|
||||
|
@ -56,7 +57,7 @@ export class PluginProvider {
|
|||
this.t.isImportDeclaration(n)
|
||||
) as t.ImportDeclaration[];
|
||||
const inulaImports = this.allImports.filter(
|
||||
n => n.source.value === PluginProvider.inulaPackageName
|
||||
n => n.source.value === this.inulaPackageName
|
||||
);
|
||||
// ---- @Enter2
|
||||
if (inulaImports.length === 0) {
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
import babel, { transform, types as t, parseSync } from '@babel/core';
|
||||
import babel, { transform, types as t, parseSync } from '@babel/core';
|
||||
import inula from '../';
|
||||
import babelJSX from '@babel/plugin-syntax-jsx';
|
||||
import generate from '@babel/generator';
|
||||
import { expect as ep } from 'vitest';
|
||||
|
||||
function formatCode(code: string) {
|
||||
return generate(
|
||||
parseSync(code, {plugins: [babelJSX]})!
|
||||
)!.code;
|
||||
return generate(parseSync(code, { plugins: [babelJSX] })!)!.code;
|
||||
}
|
||||
|
||||
export function transformInula(code: string) {
|
||||
return transform(code, {
|
||||
presets: [[inula, {'files': '*'}]]
|
||||
presets: [[inula, { files: '*', packageName: 'inula' }]],
|
||||
})?.code;
|
||||
}
|
||||
|
||||
export function expect(ori: string, expected: string) {
|
||||
const transformed = transformInula(ori)!;
|
||||
ep(formatCode(transformed)).toBe(formatCode(expected));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,9 @@ export interface InulaOption {
|
|||
* @example { createElement: 'createElement' }
|
||||
*/
|
||||
parseTemplate?: boolean
|
||||
/**
|
||||
* @brief The package name of inula. It will be used to identify whether we should transform the file.
|
||||
* @default inula
|
||||
*/
|
||||
packageName?: string
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,217 +0,0 @@
|
|||
import { ViewUnit, UnitProp } from '@inula/jsx-view-parser';
|
||||
import Babel, { types, traverse } from '@babel/core';
|
||||
|
||||
interface ViewGeneratorConfig {
|
||||
babelApi: typeof Babel;
|
||||
importMap: Record<string, string>;
|
||||
/**
|
||||
* @brief Using AttributeMap to identify propertyfied attributes
|
||||
* Reason for adding this:
|
||||
* `el.prop = xxx` is faster than `el.setAttribute('prop', xxx)`
|
||||
* @example { href: ["a", "area", "base", "link"], id: ["*"] }
|
||||
*/
|
||||
attributeMap?: Record<string, string[]>;
|
||||
}
|
||||
|
||||
declare class BaseGenerator {
|
||||
readonly viewUnit: ViewUnit;
|
||||
readonly config: ViewGeneratorConfig;
|
||||
readonly t: typeof types;
|
||||
readonly traverse: typeof traverse;
|
||||
readonly elementAttributeMap: Record<string, string[]>;
|
||||
readonly importMap: Record<string, string>;
|
||||
constructor(viewUnit: ViewUnit, config: ViewGeneratorConfig);
|
||||
private readonly initStatements;
|
||||
addStatement(...statements: types.Statement[]): void;
|
||||
private readonly templates;
|
||||
addTemplate(...template: types.Statement[]): void;
|
||||
/**
|
||||
* @brief To be implemented by the subclass
|
||||
*/
|
||||
run(): string;
|
||||
generate(): [string, types.Statement[], types.Statement[]];
|
||||
/**
|
||||
* @brief Check if the expression is reactive, which satisfies the following conditions:
|
||||
* 1. Contains .get() property
|
||||
* 2. The whole expression is not a function
|
||||
* @param expression
|
||||
* @returns
|
||||
*/
|
||||
checkReactive(expression: types.Expression): boolean;
|
||||
private readonly prefixMap;
|
||||
nodeIdx: number;
|
||||
geneNodeName(idx?: number): string;
|
||||
templateIdx: number;
|
||||
generateTemplateName(): string;
|
||||
/**
|
||||
* @brief Wrap the value in a file
|
||||
* @param node
|
||||
* @returns wrapped value
|
||||
*/
|
||||
wrapWithFile(node: types.Expression): types.File;
|
||||
addWatch(value: types.Expression): types.CallExpression;
|
||||
createCollector(): [types.Statement[], (statement: types.Statement | types.Statement[] | null) => void];
|
||||
parseViewProp(prop: UnitProp, generateView: (units: ViewUnit[], config: ViewGeneratorConfig, templateIdx: number) => [types.Statement[], types.ExpressionStatement]): types.Expression;
|
||||
parseProps(props: Record<string, UnitProp>, generateView: (units: ViewUnit[], config: ViewGeneratorConfig) => [types.Statement[], types.ExpressionStatement]): {
|
||||
[k: string]: types.Expression;
|
||||
};
|
||||
}
|
||||
|
||||
declare class CompGenerator extends BaseGenerator {
|
||||
run(): string;
|
||||
/**
|
||||
* @View
|
||||
* const $el = createComponent(tag, {
|
||||
* ...props
|
||||
* }, spreadProps)
|
||||
*/
|
||||
declareCompNode(tag: types.Expression, props: Record<string, types.Expression>, children: ViewUnit[]): [string, types.Statement];
|
||||
}
|
||||
|
||||
declare class HTMLPropGenerator extends BaseGenerator {
|
||||
static DelegatedEvents: Set<string>;
|
||||
addHTMLProp(nodeName: string, tag: string, key: string, value: types.Expression): types.Statement;
|
||||
/**
|
||||
* @View
|
||||
* setStyle($node, value)
|
||||
*/
|
||||
private setStyle;
|
||||
/**
|
||||
* @View
|
||||
* setDataset($node, value)
|
||||
*/
|
||||
private setDataset;
|
||||
/**
|
||||
* @View
|
||||
* $node.key = value
|
||||
*/
|
||||
private setStaticProperty;
|
||||
/**
|
||||
* @View
|
||||
* setProperty($node, key, value)
|
||||
*/
|
||||
private setDynamicProperty;
|
||||
/**
|
||||
* @View
|
||||
* $node.setAttribute(key, value)
|
||||
*/
|
||||
private setStaticAttribute;
|
||||
/**
|
||||
* @View
|
||||
* setAttribute($node, key, value)
|
||||
*/
|
||||
private setDynamicAttribute;
|
||||
/**
|
||||
* @View
|
||||
* delegateEvent($node, eventName, value)
|
||||
*/
|
||||
private setDelegatedEvent;
|
||||
/**
|
||||
* @View
|
||||
* $node.addEventListener(eventName, value)
|
||||
*/
|
||||
private setStaticEvent;
|
||||
/**
|
||||
* @View
|
||||
* addEventListener($node, eventName, value)
|
||||
*/
|
||||
private setDynamicEvent;
|
||||
private setDynamicHTMLProp;
|
||||
/**
|
||||
* @brief Check if the attribute is internal, i.e., can be accessed as js property
|
||||
* @param tag
|
||||
* @param attribute
|
||||
* @returns true if the attribute is internal
|
||||
*/
|
||||
isInternalAttribute(tag: string, attribute: string): boolean;
|
||||
}
|
||||
|
||||
declare class HTMLGenerator extends HTMLPropGenerator {
|
||||
run(): string;
|
||||
/**
|
||||
* @View
|
||||
* const $el = createElement(tag)
|
||||
*/
|
||||
declareHTMLNode(tag: types.Expression): [string, types.Statement];
|
||||
/**
|
||||
* @View
|
||||
* $insert($el, childNode)
|
||||
*/
|
||||
private insertChildNode;
|
||||
}
|
||||
|
||||
declare class TemplateGenerator extends HTMLPropGenerator {
|
||||
run(): string;
|
||||
private generateTemplate;
|
||||
/**
|
||||
* @View
|
||||
* const $el = template.cloneNode(true)
|
||||
*/
|
||||
private declareTemplateNode;
|
||||
/**
|
||||
* @View
|
||||
* $insert($el, childNode)
|
||||
*/
|
||||
private insertChildNode;
|
||||
/**
|
||||
* @View
|
||||
* ${dlNodeName}.firstChild
|
||||
* or
|
||||
* ${dlNodeName}.firstChild.nextSibling
|
||||
* or
|
||||
* ...
|
||||
* ${dlNodeName}.childNodes[${num}]
|
||||
*/
|
||||
private insertElement;
|
||||
/**
|
||||
* @brief Insert elements to the template node from the paths
|
||||
* @param paths
|
||||
* @param dlNodeName
|
||||
* @returns
|
||||
*/
|
||||
private insertElements;
|
||||
/**
|
||||
* @brief Extract common prefix from paths
|
||||
* e.g.
|
||||
* [0, 1, 2, 3] + [0, 1, 2, 4] => [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 4]
|
||||
* [0, 1, 2] is the common prefix
|
||||
* @param paths
|
||||
* @returns paths with common prefix
|
||||
*/
|
||||
private static pathWithCommonPrefix;
|
||||
/**
|
||||
* @brief Find the best node name and path for the given path by looking into the nameMap.
|
||||
* If there's a full match, return the name and an empty path
|
||||
* If there's a partly match, return the name and the remaining path
|
||||
* If there's a nextSibling match, return the name and the remaining path with sibling offset
|
||||
* @param nameMap
|
||||
* @param path
|
||||
* @param defaultName
|
||||
* @returns [name, path, siblingOffset]
|
||||
*/
|
||||
private static findBestNodeAndPath;
|
||||
}
|
||||
|
||||
declare class TextGenerator extends BaseGenerator {
|
||||
run(): string;
|
||||
declareTextNode(content: types.Literal): [string, types.Statement];
|
||||
}
|
||||
|
||||
declare class ExpressionGenerator extends BaseGenerator {
|
||||
run(): string;
|
||||
declareExpressionNode(expression: types.Expression): [string, types.Statement];
|
||||
}
|
||||
|
||||
declare const viewGeneratorMap: {
|
||||
readonly html: typeof HTMLGenerator;
|
||||
readonly comp: typeof CompGenerator;
|
||||
readonly template: typeof TemplateGenerator;
|
||||
readonly text: typeof TextGenerator;
|
||||
readonly exp: typeof ExpressionGenerator;
|
||||
readonly if: typeof CompGenerator;
|
||||
readonly env: typeof CompGenerator;
|
||||
};
|
||||
declare function generateNew(oldGenerator: any, viewUnit: ViewUnit, resetIdx?: boolean): [string, types.Statement[], types.Statement[]];
|
||||
declare function generateView(viewUnits: ViewUnit[], config: ViewGeneratorConfig, templateIdx?: number): [types.Statement[], types.ExpressionStatement];
|
||||
|
||||
export { ViewGeneratorConfig, generateNew, generateView, viewGeneratorMap };
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -146,7 +146,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
|||
value: t.Expression,
|
||||
) {
|
||||
return this.t.callExpression(
|
||||
this.t.identifier(this.importMap.delegateEvents),
|
||||
this.t.identifier(this.importMap.delegateEvent),
|
||||
[this.t.identifier(nodeName), this.t.stringLiteral(eventName), value]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
|
||||
export const importMap = [
|
||||
'createElement',
|
||||
'setStyle',
|
||||
'setAttribute',
|
||||
'setDataset',
|
||||
'setProperty',
|
||||
'setEvent',
|
||||
'delegateEvent',
|
||||
'createElement',
|
||||
'setStyle',
|
||||
'setAttribute',
|
||||
'setDataset',
|
||||
'setProperty',
|
||||
'setEvent',
|
||||
'delegateEvent',
|
||||
'addEventListener',
|
||||
'watch',
|
||||
'insert',
|
||||
|
@ -510,4 +510,4 @@ export const attributeMap = {
|
|||
ariaRowIndex: ['*'],
|
||||
ariaRowSpan: ['*'],
|
||||
ariaSetSize: ['*'],
|
||||
};
|
||||
};
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,73 +0,0 @@
|
|||
import Babel, { types } from '@babel/core';
|
||||
|
||||
interface UnitProp {
|
||||
value: types.Expression;
|
||||
viewPropMap: Record<string, ViewUnit[]>;
|
||||
specifier?: string;
|
||||
}
|
||||
interface TextUnit {
|
||||
type: 'text';
|
||||
content: types.Literal;
|
||||
}
|
||||
type MutableUnit = ViewUnit & {
|
||||
path: number[];
|
||||
};
|
||||
interface TemplateProp {
|
||||
tag: types.Expression;
|
||||
name: string;
|
||||
key: string;
|
||||
path: number[];
|
||||
value: types.Expression;
|
||||
}
|
||||
interface TemplateUnit {
|
||||
type: 'template';
|
||||
template: HTMLUnit;
|
||||
mutableUnits: MutableUnit[];
|
||||
props: TemplateProp[];
|
||||
}
|
||||
interface HTMLUnit {
|
||||
type: 'html';
|
||||
tag: types.Expression;
|
||||
props: Record<string, UnitProp>;
|
||||
children: ViewUnit[];
|
||||
}
|
||||
interface CompUnit {
|
||||
type: 'comp';
|
||||
tag: types.Expression;
|
||||
props: Record<string, UnitProp>;
|
||||
children: ViewUnit[];
|
||||
}
|
||||
interface IfBranch {
|
||||
condition: types.Expression;
|
||||
children: ViewUnit[];
|
||||
}
|
||||
interface IfUnit {
|
||||
type: 'if';
|
||||
branches: IfBranch[];
|
||||
}
|
||||
interface ExpUnit {
|
||||
type: 'exp';
|
||||
content: UnitProp;
|
||||
}
|
||||
interface EnvUnit {
|
||||
type: 'env';
|
||||
props: Record<string, UnitProp>;
|
||||
children: ViewUnit[];
|
||||
}
|
||||
type ViewUnit = TextUnit | HTMLUnit | CompUnit | IfUnit | ExpUnit | EnvUnit | TemplateUnit;
|
||||
interface ViewParserConfig {
|
||||
babelApi: typeof Babel;
|
||||
htmlTags: string[];
|
||||
parseTemplate?: boolean;
|
||||
}
|
||||
type AllowedJSXNode = types.JSXElement | types.JSXFragment | types.JSXText | types.JSXExpressionContainer | types.JSXSpreadChild;
|
||||
|
||||
/**
|
||||
* @brief Generate view units from a babel ast
|
||||
* @param statement
|
||||
* @param config
|
||||
* @returns ViewUnit[]
|
||||
*/
|
||||
declare function parseView(node: AllowedJSXNode, config: ViewParserConfig): ViewUnit[];
|
||||
|
||||
export { AllowedJSXNode, CompUnit, EnvUnit, ExpUnit, HTMLUnit, IfBranch, IfUnit, MutableUnit, TemplateProp, TemplateUnit, TextUnit, UnitProp, ViewParserConfig, ViewUnit, parseView };
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue