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