mirror of https://github.com/sveltejs/svelte
parent
1273f97808
commit
f209ae5dcb
@ -0,0 +1,3 @@
|
|||||||
|
export function is_string(node) {
|
||||||
|
return node.type === 'TemplateLiteral' || (node.type === 'Literal' && typeof node.value === 'string');
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
import { walk } from 'estree-walker';
|
||||||
|
import { Text, MustacheTag } from '../../interfaces';
|
||||||
|
|
||||||
|
export default function optimise(ast) {
|
||||||
|
walk(ast, {
|
||||||
|
enter(node: any) {
|
||||||
|
if (node.type === 'Element') {
|
||||||
|
optimise_text_content(node.children);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const text_like_node_type = new Set(['MustacheTag', 'Text']);
|
||||||
|
|
||||||
|
function optimise_text_content(children) {
|
||||||
|
let start = 0;
|
||||||
|
let end = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
while (
|
||||||
|
start < children.length &&
|
||||||
|
!text_like_node_type.has(children[start].type)
|
||||||
|
)
|
||||||
|
start++;
|
||||||
|
|
||||||
|
end = start;
|
||||||
|
|
||||||
|
while (end < children.length && text_like_node_type.has(children[end].type))
|
||||||
|
end++;
|
||||||
|
|
||||||
|
if (end > start) {
|
||||||
|
const merged = merge_text_siblings(children.slice(start, end));
|
||||||
|
children.splice(start, end - start, ...merged);
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
} while (start < children.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge_text_siblings(children: Array<Text | MustacheTag>) {
|
||||||
|
if (children.length < 3) {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
const literal = {
|
||||||
|
type: 'TemplateLiteral',
|
||||||
|
expressions: [],
|
||||||
|
quasis: [],
|
||||||
|
};
|
||||||
|
const state = {
|
||||||
|
quasi: {
|
||||||
|
type: 'TemplateElement',
|
||||||
|
value: { raw: '' },
|
||||||
|
start: children[0].start,
|
||||||
|
end: children[0].start
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const child of children) {
|
||||||
|
if (child.type === 'MustacheTag') {
|
||||||
|
literal.quasis.push(state.quasi);
|
||||||
|
literal.expressions.push(child.expression);
|
||||||
|
state.quasi = {
|
||||||
|
type: 'TemplateElement',
|
||||||
|
value: { raw: '' },
|
||||||
|
// @ts-ignore
|
||||||
|
start: child.expression.end + 1,
|
||||||
|
// @ts-ignore
|
||||||
|
end: child.expression.end + 1
|
||||||
|
};
|
||||||
|
} else if (child.type === 'Text') {
|
||||||
|
state.quasi.value.raw += child.data;
|
||||||
|
state.quasi.end = child.end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
literal.quasis.push(state.quasi);
|
||||||
|
|
||||||
|
return [{
|
||||||
|
type: 'MustacheTag',
|
||||||
|
expression: literal,
|
||||||
|
start: children[0].start,
|
||||||
|
end: children[children.length - 1].end,
|
||||||
|
}];
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
import {
|
||||||
|
SvelteComponent,
|
||||||
|
append,
|
||||||
|
detach,
|
||||||
|
element,
|
||||||
|
init,
|
||||||
|
insert,
|
||||||
|
listen,
|
||||||
|
noop,
|
||||||
|
safe_not_equal,
|
||||||
|
set_data,
|
||||||
|
text
|
||||||
|
} from "svelte/internal";
|
||||||
|
|
||||||
|
function create_fragment(ctx) {
|
||||||
|
let button;
|
||||||
|
|
||||||
|
let t_fn = ctx => `
|
||||||
|
Clicked ${ctx.count} ${ctx.count === 1 ? "time" : "times"}
|
||||||
|
`;
|
||||||
|
|
||||||
|
let t_value = t_fn(ctx);
|
||||||
|
let t;
|
||||||
|
let dispose;
|
||||||
|
|
||||||
|
return {
|
||||||
|
c() {
|
||||||
|
button = element("button");
|
||||||
|
t = text(t_value);
|
||||||
|
dispose = listen(button, "click", ctx.increment);
|
||||||
|
},
|
||||||
|
m(target, anchor) {
|
||||||
|
insert(target, button, anchor);
|
||||||
|
append(button, t);
|
||||||
|
},
|
||||||
|
p(changed, ctx) {
|
||||||
|
if (changed.count && t_value !== (t_value = t_fn(ctx))) set_data(t, t_value);
|
||||||
|
},
|
||||||
|
i: noop,
|
||||||
|
o: noop,
|
||||||
|
d(detaching) {
|
||||||
|
if (detaching) detach(button);
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function instance($$self, $$props, $$invalidate) {
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
function increment() {
|
||||||
|
$$invalidate("count", count = count + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { count, increment };
|
||||||
|
}
|
||||||
|
|
||||||
|
class Component extends SvelteComponent {
|
||||||
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
init(this, options, instance, create_fragment, safe_not_equal, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component;
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
let count = 0;
|
||||||
|
function increment() {
|
||||||
|
count = count + 1;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<button on:click={increment}>
|
||||||
|
Clicked {count} {count === 1 ? 'time' : 'times'}
|
||||||
|
</button>
|
@ -0,0 +1,4 @@
|
|||||||
|
<script>let name;</script>
|
||||||
|
<div>Hello {name}!</div>
|
||||||
|
<div>Hello <span>{name}</span>!</div>
|
||||||
|
<div><span>Hello</span> {name}!</div>
|
@ -0,0 +1 @@
|
|||||||
|
{ "optimiseAst": true }
|
@ -0,0 +1,249 @@
|
|||||||
|
{
|
||||||
|
"html": {
|
||||||
|
"start": 27,
|
||||||
|
"end": 127,
|
||||||
|
"type": "Fragment",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"start": 26,
|
||||||
|
"end": 27,
|
||||||
|
"type": "Text",
|
||||||
|
"raw": "\n",
|
||||||
|
"data": "\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 27,
|
||||||
|
"end": 51,
|
||||||
|
"type": "Element",
|
||||||
|
"name": "div",
|
||||||
|
"attributes": [],
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "MustacheTag",
|
||||||
|
"expression": {
|
||||||
|
"type": "TemplateLiteral",
|
||||||
|
"expressions": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 39,
|
||||||
|
"end": 43,
|
||||||
|
"name": "name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quasis": [
|
||||||
|
{
|
||||||
|
"type": "TemplateElement",
|
||||||
|
"value": {
|
||||||
|
"raw": "Hello "
|
||||||
|
},
|
||||||
|
"start": 32,
|
||||||
|
"end": 38
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TemplateElement",
|
||||||
|
"value": {
|
||||||
|
"raw": "!"
|
||||||
|
},
|
||||||
|
"start": 44,
|
||||||
|
"end": 45
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"start": 32,
|
||||||
|
"end": 45
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 51,
|
||||||
|
"end": 52,
|
||||||
|
"type": "Text",
|
||||||
|
"raw": "\n",
|
||||||
|
"data": "\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 52,
|
||||||
|
"end": 89,
|
||||||
|
"type": "Element",
|
||||||
|
"name": "div",
|
||||||
|
"attributes": [],
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"start": 57,
|
||||||
|
"end": 63,
|
||||||
|
"type": "Text",
|
||||||
|
"raw": "Hello ",
|
||||||
|
"data": "Hello "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 63,
|
||||||
|
"end": 82,
|
||||||
|
"type": "Element",
|
||||||
|
"name": "span",
|
||||||
|
"attributes": [],
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"start": 69,
|
||||||
|
"end": 75,
|
||||||
|
"type": "MustacheTag",
|
||||||
|
"expression": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 70,
|
||||||
|
"end": 74,
|
||||||
|
"name": "name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 82,
|
||||||
|
"end": 83,
|
||||||
|
"type": "Text",
|
||||||
|
"raw": "!",
|
||||||
|
"data": "!"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 89,
|
||||||
|
"end": 90,
|
||||||
|
"type": "Text",
|
||||||
|
"raw": "\n",
|
||||||
|
"data": "\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"start": 90,
|
||||||
|
"end": 127,
|
||||||
|
"type": "Element",
|
||||||
|
"name": "div",
|
||||||
|
"attributes": [],
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"start": 95,
|
||||||
|
"end": 113,
|
||||||
|
"type": "Element",
|
||||||
|
"name": "span",
|
||||||
|
"attributes": [],
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"start": 101,
|
||||||
|
"end": 106,
|
||||||
|
"type": "Text",
|
||||||
|
"raw": "Hello",
|
||||||
|
"data": "Hello"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "MustacheTag",
|
||||||
|
"expression": {
|
||||||
|
"type": "TemplateLiteral",
|
||||||
|
"expressions": [
|
||||||
|
{
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 115,
|
||||||
|
"end": 119,
|
||||||
|
"name": "name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quasis": [
|
||||||
|
{
|
||||||
|
"type": "TemplateElement",
|
||||||
|
"value": {
|
||||||
|
"raw": " "
|
||||||
|
},
|
||||||
|
"start": 113,
|
||||||
|
"end": 114
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TemplateElement",
|
||||||
|
"value": {
|
||||||
|
"raw": "!"
|
||||||
|
},
|
||||||
|
"start": 120,
|
||||||
|
"end": 121
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"start": 113,
|
||||||
|
"end": 121
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"instance": {
|
||||||
|
"type": "Script",
|
||||||
|
"start": 0,
|
||||||
|
"end": 26,
|
||||||
|
"context": "default",
|
||||||
|
"content": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 8,
|
||||||
|
"end": 17,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 17
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 8,
|
||||||
|
"end": 17,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 17
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 12,
|
||||||
|
"end": 16,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 12
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 12,
|
||||||
|
"end": 16,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 12
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "name"
|
||||||
|
},
|
||||||
|
"init": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "let"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sourceType": "module"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
export default {
|
||||||
|
html: `<button>Clicked 0 times</button>`,
|
||||||
|
async test({ assert, target, window }) {
|
||||||
|
const buttons = target.querySelectorAll('button');
|
||||||
|
const event = new window.MouseEvent('click');
|
||||||
|
await buttons[0].dispatchEvent(event);
|
||||||
|
assert.htmlEqual(target.innerHTML, `<button>Clicked 1 time</button>`);
|
||||||
|
|
||||||
|
await buttons[0].dispatchEvent(event);
|
||||||
|
assert.htmlEqual(target.innerHTML, `<button>Clicked 2 times</button>`);
|
||||||
|
},
|
||||||
|
};
|
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
let count = 0;
|
||||||
|
function increment() {
|
||||||
|
count = count + 1;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<button on:click={increment}>
|
||||||
|
Clicked {count} {count === 1 ? 'time' : 'times'}
|
||||||
|
</button>
|
Loading…
Reference in new issue