Skip to content

Commit

Permalink
feat(compiler): update structure in get template method (#62)
Browse files Browse the repository at this point in the history
* feat: support svg elements (#60)

* feat: support svg elements

* chore: fix lint and add notes

* feat(compiler): update structure in get template method

* fix(compiler): lint error

* feat(compiler): use handler to distinguish events and on props

* chore(compiler): add EventAttributeDescriptor interface

Co-authored-by: Rongyan Chen <[email protected]>
Co-authored-by: 狒狒神 <[email protected]>
  • Loading branch information
3 people authored Apr 26, 2022
1 parent b38fee5 commit 9c687a5
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 62 deletions.
86 changes: 59 additions & 27 deletions packages/pwc-compiler/__tests__/compileScript.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const multipleKindsOfUsingBindingsComponent = `
attr3="{{this.data3.arr1[0]}}"
attr4="{{this['data-five']}}"
@click="{{this.#fn}}"
onevent="{{this.#fn}}"
@input="{{this.methods.fn2}}"
>
<div>{{ this.#data1 }}</div>
Expand Down Expand Up @@ -146,7 +147,11 @@ export default class CustomElement extends HTMLElement {
const result = compileScript(descriptor);

expect(result.content).toContain(`get template() {
return [\"\\n <p><!--?pwc_t--></p>\\n\", [this.#text]];
return {
templateString: \"\\n <p><!--?pwc_t--></p>\\n\",
templateData: [this.#text],
template: true
};
}`);
});

Expand All @@ -169,7 +174,11 @@ export default class CustomElement extends HTMLElement {
data = {};
get template() {
return ["\\n <p><!--?pwc_t--></p>\\n", [this.#text]];
return {
templateString: "\\n <p><!--?pwc_t--></p>\\n",
templateData: [this.#text],
template: true
};
}
}`);
Expand All @@ -196,7 +205,11 @@ export default class CustomElement extends HTMLElement {
};
get template() {
return ["\\n <p><!--?pwc_t--></p>\\n <p><!--?pwc_t--></p>\\n <p><!--?pwc_t--></p>\\n", [this.data.name, this.arr[0], this.nestedData.obj1.obj2.age]];
return {
templateString: "\\n <p><!--?pwc_t--></p>\\n <p><!--?pwc_t--></p>\\n <p><!--?pwc_t--></p>\\n",
templateData: [this.data.name, this.arr[0], this.nestedData.obj1.obj2.age],
template: true
};
}
}`);
Expand All @@ -214,7 +227,11 @@ export default class CustomElement extends HTMLElement {
accessor insideName = '';
get template() {
return ["\\n <p><!--?pwc_t--></p>\\n <p><!--?pwc_t--></p>\\n", [outsideName, this.insideName]];
return {
templateString: "\\n <p><!--?pwc_t--></p>\\n <p><!--?pwc_t--></p>\\n",
templateData: [outsideName, this.insideName],
template: true
};
}
}`);
Expand All @@ -228,7 +245,11 @@ export default class CustomElement extends HTMLElement {
@customElement(\"custom-element\")
export default class CustomElement extends HTMLElement {
get template() {
return [\"\\n <p>hello</p>\\n\", []];
return {
templateString: "\\n <p>hello</p>\\n",
templateData: [],
template: true
};
}
}`);
Expand All @@ -242,7 +263,11 @@ export default class CustomElement extends HTMLElement {
@customElement('custom-element')
export default class CustomElement extends HTMLElement {
get template() {
return [\"\\n <p>hello</p>\\n\", []];
return {
templateString: "\\n <p>hello</p>\\n",
templateData: [],
template: true
};
}
}`);
Expand Down Expand Up @@ -279,27 +304,34 @@ export default class CustomElement extends HTMLElement {
};
get template() {
return ["\\n <!--?pwc_p--><div>\\n <div><!--?pwc_t--></div>\\n <div><!--?pwc_t--></div>\\n <div><!--?pwc_t--></div>\\n <div><!--?pwc_t--></div>\\n <div><!--?pwc_t--></div>\\n </div>\\n", [[{
name: "attr1",
value: this.#data1
}, {
name: "attr2",
value: this.#data2.name1
}, {
name: "attr3",
value: this.data3.arr1[0]
}, {
name: "attr4",
value: this['data-five']
}, {
name: "onclick",
value: this.#fn,
capture: false
}, {
name: "oninput",
value: this.methods.fn2,
capture: false
}], this.#data1, this.#data2.name1, this.data3.arr1[0], this.data4.obj1.name2, this['data-five']]];
return {
templateString: "\\n <!--?pwc_p--><div>\\n <div><!--?pwc_t--></div>\\n <div><!--?pwc_t--></div>\\n <div><!--?pwc_t--></div>\\n <div><!--?pwc_t--></div>\\n <div><!--?pwc_t--></div>\\n </div>\\n",
templateData: [[{
name: "attr1",
value: this.#data1
}, {
name: "attr2",
value: this.#data2.name1
}, {
name: "attr3",
value: this.data3.arr1[0]
}, {
name: "attr4",
value: this['data-five']
}, {
name: "onclick",
handler: this.#fn,
capture: false
}, {
name: "onevent",
value: this.#fn
}, {
name: "oninput",
handler: this.methods.fn2,
capture: false
}], this.#data1, this.#data2.name1, this.data3.arr1[0], this.data4.obj1.name2, this['data-five']],
template: true
};
}
}`);
Expand Down
29 changes: 23 additions & 6 deletions packages/pwc-compiler/__tests__/compileTemplate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('compileTemplate', () => {
[
{
name: 'onclick',
value: 'handleClick',
handler: 'handleClick',
capture: false,
}
],
Expand All @@ -51,7 +51,7 @@ describe('compileTemplate', () => {
[
{
name: 'onclick',
value: 'this.handleClick',
handler: 'this.handleClick',
capture: false,
}
],
Expand All @@ -68,14 +68,31 @@ describe('compileTemplate', () => {
[
{
name: 'onclick',
value: 'handleClick',
handler: 'handleClick',
capture: true,
}
],
'text'
]);
});

it('compile a template with an attribute start with on', () => {
const { descriptor } = parse('<template><custom-component onevent="{{handleEvent}}">{{text}}</custom-component></template>');
const { templateString, values} = compileTemplateAST(descriptor.template.ast);

expect(templateString).toBe('<!--?pwc_p--><custom-component><!--?pwc_t--></custom-component>');
expect(values).toEqual([
[
{
name: 'onevent',
value: 'handleEvent'
}
],
'text'
]);
});


it('compile a template with attributes', () => {
const { descriptor } = parse('<template><p class="{{className}}">{{text}}</p></template>');
const { templateString, values} = compileTemplateAST(descriptor.template.ast);
Expand Down Expand Up @@ -166,7 +183,7 @@ describe('compileTemplate', () => {
[
{
name: 'onclick',
value: '() => (count++)',
handler: '() => (count++)',
capture: false
}
],
Expand All @@ -182,7 +199,7 @@ describe('compileTemplate', () => {
[
{
name: 'onclick',
value: `() => (say('hello'))`,
handler: `() => (say('hello'))`,
capture: false
}
],
Expand All @@ -198,7 +215,7 @@ describe('compileTemplate', () => {
[
{
name: 'onclick',
value: `(event) => warn('', event)`,
handler: `(event) => warn('', event)`,
capture: false
}
],
Expand Down
1 change: 1 addition & 0 deletions packages/pwc-compiler/build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export default defineConfig({
sourceMaps: 'inline',

transform: {
formats: ['cjs', 'es2017', 'esm'],
excludes: ['**/__tests__/**'],
},
});
3 changes: 2 additions & 1 deletion packages/pwc-compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
"author": "Rax Team",
"homepage": "https://github.com/raxjs/pwc#readme",
"license": "MIT",
"main": "esm/index.js",
"main": "cjs/index.js",
"module": "esm/index.js",
"exports": {
".": {
"es": "./esm/index.js",
"es2017": "./es2017/index.js",
"require": "./cjs/index.js",
"default": "./esm/index.js"
},
"./compileTemplateInRuntime": {
Expand Down
16 changes: 11 additions & 5 deletions packages/pwc-compiler/src/compileTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@ import * as parse5 from 'parse5';
import type { SFCDescriptor, ElementNode } from './parse';
import { dfs, isEventNameInTemplate, isBindings, isMemberExpression, getEventInfo, BINDING_REGEXP, INTERPOLATION_REGEXP } from './utils';

export interface AttributeDescriptor {
export interface NormalAttributeDescriptor {
name: string;
value: string;
capture?: boolean;
}

export interface EventAttributeDescriptor {
name: string;
handler: string;
capture: boolean;
}

export type AttributeDescriptor = NormalAttributeDescriptor | EventAttributeDescriptor;

export type ValueDescriptor = Array<string | Array<AttributeDescriptor>>;

export interface CompileTemplateResult {
Expand Down Expand Up @@ -35,7 +42,7 @@ function createTextNode(value) {

// with side effect in changing node structure
function extractAttributeBindings(node: ElementNode): Array<AttributeDescriptor> {
const tempAttributeDescriptor = [];
const tempAttributeDescriptor: Array<AttributeDescriptor> = [];
// Extract attribute bindings
if (node.attrs?.length > 0) {
let hasInsertComment = false; // Should only insert comment node before current node once
Expand Down Expand Up @@ -68,13 +75,12 @@ function extractAttributeBindings(node: ElementNode): Array<AttributeDescriptor>

tempAttributeDescriptor.push({
name: `on${eventName}`,
value: expression,
handler: expression,
capture: isCapture,
});
} else {
// attributes
let expression = attr.value.replace(BINDING_REGEXP, '$1').trim();

tempAttributeDescriptor.push({
name: attr.name,
value: expression,
Expand Down
48 changes: 34 additions & 14 deletions packages/pwc-compiler/src/transform/genGetTemplateMethod.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import type { File } from '@babel/types';
import * as t from '@babel/types';
import babelTraverse from '@babel/traverse';
import { isBoolean } from '../utils';

import type { CompileTemplateResult, AttributeDescriptor } from '../compileTemplate';
import type { CompileTemplateResult } from '../compileTemplate';

function createObjectProperty(key, value) {
if (key === 'value') {
return t.objectProperty(t.identifier(key), createIdentifier(value));
} else if (key === 'name') {
return t.objectProperty(t.identifier(key), t.stringLiteral(value));
} else if (key === 'capture') {
return t.objectProperty(t.identifier(key), t.booleanLiteral(value));
}
interface objectExpression {
[key: string]: t.Expression;
}

function createObjectExpression(obj: AttributeDescriptor) {
function createObjectProperty(key: string, value: t.Expression) {
return t.objectProperty(t.identifier(key), value);
}

function createObjectExpression(obj: objectExpression) {
return t.objectExpression(Object.entries(obj).map(([key, value]) => {
return createObjectProperty(key, value);
}));
Expand Down Expand Up @@ -45,6 +44,8 @@ function cretateGetTemplateClassMethod(returnExpression) {
);
}

const templateFlag = t.booleanLiteral(true);

export default function genGetTemplateMethod(ast: File, templateResult: CompileTemplateResult): void {
babelTraverse(ast, {
ClassDeclaration(path) {
Expand All @@ -66,7 +67,7 @@ export default function genGetTemplateMethod(ast: File, templateResult: CompileT
[
{
name: 'onclick',
value: 'onClick',
handler: 'onClick',
capture: true,
},
{
Expand All @@ -76,11 +77,30 @@ export default function genGetTemplateMethod(ast: File, templateResult: CompileT
]
*/
return createArrayExpression(val.map(attr => {
return createObjectExpression(attr);
}));
const attributeEntries = Object.entries(attr).map(([key, val]) => {
let expression;
if (key === 'name') {
expression = t.stringLiteral(val);
} else if (key === 'value' || key === 'handler') {
expression = createIdentifier(val);
} else if (key === 'capture') {
expression = t.booleanLiteral(val);
}
return [key, expression];
});
const attributeObjectExpression = Object.fromEntries(attributeEntries);
return createObjectExpression(attributeObjectExpression);
},
));
}
}));
const returnExpression = createArrayExpression([templateStringExpression, templateValuesExpression]);

const returnExpression = createObjectExpression({
templateString: templateStringExpression,
templateData: templateValuesExpression,
template: templateFlag,
});

node.body.body.push(cretateGetTemplateClassMethod(returnExpression));
}
}
Expand Down
4 changes: 4 additions & 0 deletions packages/pwc-compiler/src/utils/is.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,7 @@ export function isMemberExpression(path: string): boolean {
}
return !currentOpenBracketCount && !currentOpenParensCount;
}

export function isBoolean(val: unknown): boolean {
return typeof val === 'boolean';
}
Loading

0 comments on commit 9c687a5

Please sign in to comment.