Merge branch 'master' into pr/5004

pull/5004/head
Conduitry 5 years ago
commit fb0b2b22cd

@ -3,6 +3,7 @@ on: [push, pull_request]
jobs:
Tests:
runs-on: ${{ matrix.os }}
timeout-minutes: 6
strategy:
matrix:
node-version: [8, 10, 12, 14]
@ -18,12 +19,14 @@ jobs:
CI: true
Lint:
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
- run: 'npm i && npm run lint'
Unit:
runs-on: ${{ matrix.os }}
timeout-minutes: 3
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]

@ -2,10 +2,20 @@
## Unreleased
* Support nullish coalescing (`??`) and optional chaining (`?.`) operators ([#1972](https://github.com/sveltejs/svelte/issues/1972))
* Support `import.meta` ([#4379](https://github.com/sveltejs/svelte/issues/4379))
* Fix placement of `{@html}` when used at the root of a slot, at the root of a component, or in `<svelte:head>` ([#5012](https://github.com/sveltejs/svelte/issues/5012), [#5071](https://github.com/sveltejs/svelte/pull/5071))
* Fix certain handling of two-way bound `contenteditable` elements ([#5018](https://github.com/sveltejs/svelte/issues/5018))
* Fix handling of `import`ed value that is used as a store and is also mutated ([#5019](https://github.com/sveltejs/svelte/issues/5019))
* Do not display `a11y-missing-content` warning on elements with `contenteditable` bindings ([#5020](https://github.com/sveltejs/svelte/issues/5020))
* Fix handling of `this` in inline function expressions in the template ([#5033](https://github.com/sveltejs/svelte/issues/5033))
* Fix collapsing HTML with static content ([#5040](https://github.com/sveltejs/svelte/issues/5040))
* Prevent use of `$store` at compile time when top-level `store` has been shadowed ([#5048](https://github.com/sveltejs/svelte/issues/5048))
* Update `<select>` with one-way `value` binding when the available `<option>`s change ([#5051](https://github.com/sveltejs/svelte/issues/5051))
* Fix published `tweened` types so the `.set()` and `.update()` options are optional ([#5062](https://github.com/sveltejs/svelte/issues/5062))
* Fix contextual `bind:this` inside `{#each}` block ([#5067](https://github.com/sveltejs/svelte/issues/5067))
* Preprocess self-closing `<script>` and `<style>` tags ([#5080](https://github.com/sveltejs/svelte/issues/5080))
* Fix types for animation- and transition-related param objects so each param is optional ([#5083](https://github.com/sveltejs/svelte/pull/5083))
## 3.23.2

28
package-lock.json generated

@ -167,9 +167,9 @@
"dev": true
},
"@types/estree": {
"version": "0.0.39",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"version": "0.0.45",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.45.tgz",
"integrity": "sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==",
"dev": true
},
"@types/is-windows": {
@ -315,9 +315,9 @@
"dev": true
},
"acorn": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
"integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
"dev": true
},
"acorn-globals": {
@ -769,12 +769,12 @@
"dev": true
},
"code-red": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/code-red/-/code-red-0.1.2.tgz",
"integrity": "sha512-GFNCdH1eTXpmZGzG+/w0L60gO35Kf803UPmAIDlD1220EUk+AtfQuvxnyeRzxIa7FXte0aANnQgySGdoU67I3Q==",
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/code-red/-/code-red-0.1.3.tgz",
"integrity": "sha512-3n9i1Jv0om4+2Aq7pCL8M5xRgc2wTXsblsYUxXJDpgBZ3wJP1zbcNzu4XgUqrG0rjc1to2yh+3n9rwHsJa7qSA==",
"dev": true,
"requires": {
"acorn": "^7.1.0",
"acorn": "^7.3.1",
"is-reference": "^1.1.4",
"periscopic": "^2.0.1",
"sourcemap-codec": "^1.4.6"
@ -2250,12 +2250,12 @@
"dev": true
},
"is-reference": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz",
"integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"dev": true,
"requires": {
"@types/estree": "0.0.39"
"@types/estree": "*"
}
},
"is-regex": {

@ -68,10 +68,10 @@
"@types/node": "^8.10.53",
"@typescript-eslint/eslint-plugin": "^3.0.2",
"@typescript-eslint/parser": "^3.0.2",
"acorn": "^7.1.0",
"acorn": "^7.3.1",
"agadoo": "^1.1.0",
"c8": "^5.0.1",
"code-red": "0.1.2",
"code-red": "^0.1.3",
"codecov": "^3.5.0",
"css-tree": "1.0.0-alpha22",
"eslint": "^7.1.0",

@ -57,7 +57,7 @@ What about a more 'real world' example? Conveniently, the [RealWorld](https://gi
<aside><p>Code-splitting isn't free — if the reference implementation used code-splitting, it would be larger still</p></aside>
The entire app costs 132.7kb (39.9kb zipped), which is significantly smaller than the reference React/Redux implementation at 327kb (85.7kb), but even if was as large it would *feel* faster because of code-splitting. And that's a crucial point. We're told we need to code-split our apps, but if your app uses a traditional framework like React or Vue then there's a hard lower bound on the size of your initial code-split chunk — the framework itself, which is likely to be a significant portion of your total app size. With the Svelte approach, that's no longer the case.
The entire app costs 132.7kb (39.9kb zipped), which is significantly smaller than the reference React/Redux implementation at 327kb (85.7kb), but even if it was as large it would *feel* faster because of code-splitting. And that's a crucial point. We're told we need to code-split our apps, but if your app uses a traditional framework like React or Vue then there's a hard lower bound on the size of your initial code-split chunk — the framework itself, which is likely to be a significant portion of your total app size. With the Svelte approach, that's no longer the case.
But size is only part of the story. Svelte apps are also extremely performant and memory-efficient, and the framework includes powerful features that you would sacrifice if you chose a 'minimal' or 'simple' UI library.

@ -1,5 +1,5 @@
---
question: How can I get VSCode to syntax-highlight my .svelte files?
question: How can I get VS Code to syntax-highlight my .svelte files?
---
There is an [official VSCode extension for Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), however it is still in the **beta** testing stage, and not all issues have been ironed out.
There is an [official VS Code extension for Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).

@ -1,10 +1,11 @@
---
question: What about Typescript support?
question: What about TypeScript support?
---
You need to install a preprocessor such as [svelte-preprocess](https://github.com/sveltejs/svelte-preprocess). Work is ongoing to improve [IDE support](https://github.com/sveltejs/language-tools/issues/83). You can also run type checking from the command line with [svelte-check](https://www.npmjs.com/package/svelte-check).
You need to install a preprocessor such as [svelte-preprocess](https://github.com/sveltejs/svelte-preprocess). You can run type checking from the command line with [svelte-check](https://www.npmjs.com/package/svelte-check).
To declare the type of a reactive variable in a Svelte template, you should use the following syntax:
To declare the type of a reactive variable in a Svelte template, you can use the following syntax:
```
let x: number;
$: x = count + 1;

@ -1281,9 +1281,9 @@
}
},
"@sveltejs/site-kit": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.1.5.tgz",
"integrity": "sha512-Rs2quQ/H00DAN/ZTFa+unLefL335UW3Yo4I2rTocW5JwW73Kvi5++d7BcY8LsjhMCbG1PkwQmJE2RVrIIxQcOw==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@sveltejs/site-kit/-/site-kit-1.2.0.tgz",
"integrity": "sha512-C7puq+1so3fKPPZAnQJQlKfyCG6FsnSSFSS2LRIhWD8VK2FL5j8Eq7DIKSxUvWbGw1AsxnzO3dIHJWPB7fwjKg==",
"dev": true,
"requires": {
"@sindresorhus/slugify": "^0.9.1",
@ -1291,9 +1291,9 @@
}
},
"@sveltejs/svelte-repl": {
"version": "0.1.19",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.19.tgz",
"integrity": "sha512-35R94X6uYgy6PHLQnQCsKcZ4zb6rGGQXjBYqjuCkoCykIlSLx8/avq6BGqudmE5pzVWDP3kk4063cHgccy1xYg==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.2.0.tgz",
"integrity": "sha512-2vLQnOVrsmn2d2K4a6urGm8OulGGSPhZCGNySSb1H8nOPsgKrdcTt5qoaxNYXgcyVp55Yow2SvXYXsyJKd4KEQ==",
"dev": true,
"requires": {
"codemirror": "^5.49.2",
@ -1601,9 +1601,9 @@
"dev": true
},
"codemirror": {
"version": "5.53.2",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.53.2.tgz",
"integrity": "sha512-wvSQKS4E+P8Fxn/AQ+tQtJnF1qH5UOlxtugFLpubEZ5jcdH2iXTVinb+Xc/4QjshuOxRm4fUsU2QPF1JJKiyXA==",
"version": "5.55.0",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.55.0.tgz",
"integrity": "sha512-TumikSANlwiGkdF/Blnu/rqovZ0Y3Jh8yy9TqrPbSM0xxSucq3RgnpVDQ+mD9q6JERJEIT2FMuF/fBGfkhIR/g==",
"dev": true
},
"color-convert": {

@ -36,8 +36,8 @@
"@babel/preset-env": "^7.6.0",
"@babel/runtime": "^7.6.0",
"@sindresorhus/slugify": "^0.9.1",
"@sveltejs/site-kit": "^1.1.5",
"@sveltejs/svelte-repl": "^0.1.19",
"@sveltejs/site-kit": "^1.2.0",
"@sveltejs/svelte-repl": "^0.2.0",
"degit": "^2.1.4",
"dotenv": "^8.1.0",
"esm": "^3.2.25",

@ -13,6 +13,10 @@ const mode = process.env.NODE_ENV;
const dev = mode === 'development';
const legacy = !!process.env.SAPPER_LEGACY_BUILD;
if (!dev && !process.env.MAPBOX_ACCESS_TOKEN) {
throw new Error('MAPBOX_ACCESS_TOKEN is missing. Please add the token in the .env file before generating the production build.');
}
const onwarn = (warning, onwarn) => (warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]@sapper[/\\]/.test(warning.message)) || onwarn(warning);
const dedupe = importee => importee === 'svelte' || importee.startsWith('svelte/');

@ -85,7 +85,7 @@ export default function() {
renderer.heading = (text, level, rawtext) => {
let slug;
const match = /<a href="([^"]+)">(.+)<\/a>/.exec(text);
const match = /<a href="([^"]+)"[^>]*>(.+)<\/a>/.exec(text);
if (match) {
slug = match[1];
text = match[2];

@ -836,7 +836,7 @@ export default class Component {
});
}
warn_on_undefined_store_value_references(node, parent, scope) {
warn_on_undefined_store_value_references(node, parent, scope: Scope) {
if (
node.type === 'LabeledStatement' &&
node.label.name === '$' &&
@ -852,8 +852,17 @@ export default class Component {
const object = get_object(node);
const { name } = object;
if (name[0] === '$' && !scope.has(name)) {
this.warn_if_undefined(name, object, null);
if (name[0] === '$') {
if (!scope.has(name)) {
this.warn_if_undefined(name, object, null);
}
if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
this.error(node, {
code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
});
}
}
}
}

@ -1,5 +1,5 @@
import { x } from 'code-red';
import { Node, Identifier, RestElement, Property } from 'estree';
import { Node, Identifier } from 'estree';
export interface Context {
key: Identifier;
@ -34,12 +34,10 @@ export function unpack_destructuring(contexts: Context[], node: Node, modifier:
const used_properties = [];
node.properties.forEach((property) => {
const props: (RestElement | Property) = (property as any);
if (props.type === 'RestElement') {
if (property.type === 'RestElement') {
unpack_destructuring(
contexts,
props.argument,
property.argument,
node => x`@object_without_properties(${modifier(node)}, [${used_properties}])` as Node
);
} else {

@ -78,11 +78,14 @@ export default class Expression {
if (scope.has(name)) return;
if (name[0] === '$' && template_scope.names.has(name.slice(1))) {
component.error(node, {
code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
});
if (name[0] === '$') {
const store_name = name.slice(1);
if (template_scope.names.has(store_name) || scope.has(store_name)) {
component.error(node, {
code: `contextual-store`,
message: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
});
}
}
if (template_scope.is_let(name)) {
@ -198,7 +201,7 @@ export default class Expression {
scope = map.get(node);
}
if (is_reference(node, parent)) {
if (node.type === 'Identifier' && is_reference(node, parent)) {
const { name } = flatten_reference(node);
if (scope.has(name)) return;

@ -6,7 +6,6 @@ import { is_void, sanitize } from '../../../../utils/names';
import FragmentWrapper from '../Fragment';
import { escape_html, string_literal } from '../../../utils/stringify';
import TextWrapper from '../Text';
import TagWrapper from '../shared/Tag';
import fix_attribute_casing from './fix_attribute_casing';
import { b, x, p } from 'code-red';
import { namespaces } from '../../../../utils/namespaces';
@ -27,6 +26,8 @@ import { Identifier } from 'estree';
import EventHandler from './EventHandler';
import { extract_names } from 'periscopic';
import Action from '../../../nodes/Action';
import MustacheTagWrapper from '../MustacheTag';
import RawMustacheTagWrapper from '../RawMustacheTag';
interface BindingGroup {
events: string[];
@ -341,8 +342,7 @@ export default class ElementWrapper extends Wrapper {
if (!this.node.namespace && (this.can_use_innerhtml || can_use_textcontent) && this.fragment.nodes.length > 0) {
if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
block.chunks.create.push(
// @ts-ignore todo: should it be this.fragment.nodes[0].node.data instead?
b`${node}.textContent = ${string_literal(this.fragment.nodes[0].data)};`
b`${node}.textContent = ${string_literal((this.fragment.nodes[0] as TextWrapper).data)};`
);
} else {
const state = {
@ -929,9 +929,9 @@ export default class ElementWrapper extends Wrapper {
}
}
function to_html(wrappers: Array<ElementWrapper | TextWrapper | TagWrapper>, block: Block, literal: any, state: any, can_use_raw_text?: boolean) {
function to_html(wrappers: Array<ElementWrapper | TextWrapper | MustacheTagWrapper | RawMustacheTagWrapper>, block: Block, literal: any, state: any, can_use_raw_text?: boolean) {
wrappers.forEach(wrapper => {
if (wrapper.node.type === 'Text') {
if (wrapper instanceof TextWrapper) {
if ((wrapper as TextWrapper).use_space()) state.quasi.value.raw += ' ';
const parent = wrapper.node.parent as Element;
@ -942,13 +942,13 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper | TagWrapper>, blo
can_use_raw_text
);
state.quasi.value.raw += (raw ? wrapper.node.data : escape_html(wrapper.node.data))
state.quasi.value.raw += (raw ? wrapper.data : escape_html(wrapper.data))
.replace(/\\/g, '\\\\')
.replace(/`/g, '\\`')
.replace(/\$/g, '\\$');
}
else if (wrapper.node.type === 'MustacheTag' || wrapper.node.type === 'RawMustacheTag' ) {
else if (wrapper instanceof MustacheTagWrapper || wrapper instanceof RawMustacheTagWrapper) {
literal.quasis.push(state.quasi);
literal.expressions.push(wrapper.node.expression.manipulate(block));
state.quasi = {
@ -987,8 +987,8 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper | TagWrapper>, blo
state.quasi.value.raw += '>';
if (!(wrapper as ElementWrapper).void) {
to_html((wrapper as ElementWrapper).fragment.nodes as Array<ElementWrapper | TextWrapper>, block, literal, state);
if (!wrapper.void) {
to_html(wrapper.fragment.nodes as Array<ElementWrapper | TextWrapper>, block, literal, state);
state.quasi.value.raw += `</${wrapper.node.name}>`;
}

@ -39,7 +39,7 @@ export default class RawMustacheTagWrapper extends Tag {
}
else {
const needs_anchor = in_head || (this.next && !this.next.is_dom_node());
const needs_anchor = in_head || (this.next ? !this.next.is_dom_node() : (!this.parent || !this.parent.is_dom_node()));
const html_tag = block.get_unique_name('html_tag');
const html_anchor = needs_anchor && block.get_unique_name('html_anchor');
@ -51,7 +51,7 @@ export default class RawMustacheTagWrapper extends Tag {
content => x`${html_tag}.p(${content})`
);
const update_anchor = in_head ? 'null' : needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
const update_anchor = needs_anchor ? html_anchor : this.next ? this.next.var : 'null';
block.chunks.hydrate.push(b`${html_tag} = new @HtmlTag(${update_anchor});`);
block.chunks.mount.push(b`${html_tag}.m(${init}, ${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`);

@ -11,7 +11,7 @@ export default function bind_this(component: Component, block: Block, binding: B
block.renderer.add_to_context(fn.name);
const callee = block.renderer.reference(fn.name);
const { contextual_dependencies, mutation, lhs } = binding.handler;
const { contextual_dependencies, mutation } = binding.handler;
const dependencies = binding.get_dependencies();
const body = b`
@ -29,7 +29,6 @@ export default function bind_this(component: Component, block: Block, binding: B
}));
component.partly_hoisted.push(b`
function ${fn}($$value, ${params}) {
if (${lhs} === $$value) return;
@binding_callbacks[$$value ? 'unshift' : 'push'](() => {
${body}
});

@ -94,8 +94,8 @@ export default async function preprocess(
for (const fn of script) {
source = await replace_async(
source,
/<!--[^]*?-->|<script(\s[^]*?)?>([^]*?)<\/script>/gi,
async (match, attributes = '', content) => {
/<!--[^]*?-->|<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi,
async (match, attributes = '', content = '') => {
if (!attributes && !content) {
return match;
}
@ -114,8 +114,8 @@ export default async function preprocess(
for (const fn of style) {
source = await replace_async(
source,
/<!--[^]*?-->|<style(\s[^]*?)?>([^]*?)<\/style>/gi,
async (match, attributes = '', content) => {
/<!--[^]*?-->|<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi,
async (match, attributes = '', content = '') => {
if (!attributes && !content) {
return match;
}

@ -11,9 +11,9 @@ export interface AnimationConfig {
}
interface FlipParams {
delay: number;
duration: number | ((len: number) => number);
easing: (t: number) => number;
delay?: number;
duration?: number | ((len: number) => number);
easing?: (t: number) => number;
}
export function flip(node: Element, animation: { from: DOMRect; to: DOMRect }, params: FlipParams): AnimationConfig {

@ -73,7 +73,7 @@ export function dataset_dev(node: HTMLElement, property: string, value?: any) {
export function set_data_dev(text, data) {
data = '' + data;
if (text.data === data) return;
if (text.wholeText === data) return;
dispatch_dev("SvelteDOMSetData", { node: text, data });
text.data = data;

@ -193,7 +193,7 @@ export function claim_space(nodes) {
export function set_data(text, data) {
data = '' + data;
if (text.data !== data) text.data = data;
if (text.wholeText !== data) text.data = data;
}
export function set_input_value(input, value) {

@ -64,9 +64,9 @@ interface Options<T> {
type Updater<T> = (target_value: T, value: T) => T;
interface Tweened<T> extends Readable<T> {
set(value: T, opts: Options<T>): Promise<void>;
set(value: T, opts?: Options<T>): Promise<void>;
update(updater: Updater<T>, opts: Options<T>): Promise<void>;
update(updater: Updater<T>, opts?: Options<T>): Promise<void>;
}
export function tweened<T>(value?: T, defaults: Options<T> = {}): Tweened<T> {
@ -75,7 +75,7 @@ export function tweened<T>(value?: T, defaults: Options<T> = {}): Tweened<T> {
let task: Task;
let target_value = value;
function set(new_value: T, opts: Options<T>) {
function set(new_value: T, opts?: Options<T>) {
if (value == null) {
store.set(value = new_value);
return Promise.resolve();
@ -98,7 +98,7 @@ export function tweened<T>(value?: T, defaults: Options<T> = {}): Tweened<T> {
previous_task.abort();
previous_task = null;
}
store.set(value = target_value);
return Promise.resolve();
}
@ -137,7 +137,7 @@ export function tweened<T>(value?: T, defaults: Options<T> = {}): Tweened<T> {
return {
set,
update: (fn, opts: Options<T>) => set(fn(target_value, value), opts),
update: (fn, opts?: Options<T>) => set(fn(target_value, value), opts),
subscribe: store.subscribe
};
}

@ -12,11 +12,11 @@ export interface TransitionConfig {
}
interface BlurParams {
delay: number;
duration: number;
delay?: number;
duration?: number;
easing?: EasingFunction;
amount: number;
opacity: number;
amount?: number;
opacity?: number;
}
export function blur(node: Element, {
@ -41,9 +41,9 @@ export function blur(node: Element, {
}
interface FadeParams {
delay: number;
duration: number;
easing: EasingFunction;
delay?: number;
duration?: number;
easing?: EasingFunction;
}
export function fade(node: Element, {
@ -62,12 +62,12 @@ export function fade(node: Element, {
}
interface FlyParams {
delay: number;
duration: number;
easing: EasingFunction;
x: number;
y: number;
opacity: number;
delay?: number;
duration?: number;
easing?: EasingFunction;
x?: number;
y?: number;
opacity?: number;
}
export function fly(node: Element, {
@ -95,9 +95,9 @@ export function fly(node: Element, {
}
interface SlideParams {
delay: number;
duration: number;
easing: EasingFunction;
delay?: number;
duration?: number;
easing?: EasingFunction;
}
export function slide(node: Element, {
@ -133,11 +133,11 @@ export function slide(node: Element, {
}
interface ScaleParams {
delay: number;
duration: number;
easing: EasingFunction;
start: number;
opacity: number;
delay?: number;
duration?: number;
easing?: EasingFunction;
start?: number;
opacity?: number;
}
export function scale(node: Element, {
@ -166,10 +166,10 @@ export function scale(node: Element, {
}
interface DrawParams {
delay: number;
speed: number;
duration: number | ((len: number) => number);
easing: EasingFunction;
delay?: number;
speed?: number;
duration?: number | ((len: number) => number);
easing?: EasingFunction;
}
export function draw(node: SVGElement & { getTotalLength(): number }, {
@ -199,9 +199,9 @@ export function draw(node: SVGElement & { getTotalLength(): number }, {
}
interface CrossfadeParams {
delay: number;
duration: number | ((len: number) => number);
easing: EasingFunction;
delay?: number;
duration?: number | ((len: number) => number);
easing?: EasingFunction;
}
type ClientRectMap = Map<any, { rect: ClientRect }>;

@ -18,9 +18,7 @@ function create_fragment(ctx) {
return {
c() {
details = element("details");
details.innerHTML = `<summary>summary</summary>content
`;
details.innerHTML = `<summary>summary</summary>content`;
},
m(target, anchor) {
insert(target, details, anchor);

@ -0,0 +1,189 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponent,
attr,
create_component,
destroy_component,
detach,
element,
init,
insert,
mount_component,
safe_not_equal,
set_data,
space,
text,
transition_in,
transition_out
} from "svelte/internal";
function create_fragment(ctx) {
let t0_value = /*a*/ ctx[0].normal + "";
let t0;
let t1_value = /*b*/ ctx[1]?.optional + "";
let t1;
let t2;
let t3_value = /*c*/ ctx[2]["computed"] + "";
let t3;
let t4_value = /*d*/ ctx[3]?.["computed_optional"] + "";
let t4;
let t5;
let t6_value = /*e*/ ctx[4]() + "";
let t6;
let t7_value = /*f*/ ctx[5]?.() + "";
let t7;
let t8;
let div;
let div_a_value;
let div_b_value;
let div_c_value;
let div_d_value;
let div_e_value;
let div_f_value;
let t9;
let component;
let current;
component = new /*Component*/ ctx[6]({
props: {
a: /*a*/ ctx[0].normal,
b: /*b*/ ctx[1]?.optional,
c: /*c*/ ctx[2]["computed"],
d: /*d*/ ctx[3]?.["computed_optional"],
e: /*e*/ ctx[4](),
f: /*f*/ ctx[5]?.()
}
});
return {
c() {
t0 = text(t0_value);
t1 = text(t1_value);
t2 = space();
t3 = text(t3_value);
t4 = text(t4_value);
t5 = space();
t6 = text(t6_value);
t7 = text(t7_value);
t8 = space();
div = element("div");
t9 = space();
create_component(component.$$.fragment);
attr(div, "a", div_a_value = /*a*/ ctx[0].normal);
attr(div, "b", div_b_value = /*b*/ ctx[1]?.optional);
attr(div, "c", div_c_value = /*c*/ ctx[2]["computed"]);
attr(div, "d", div_d_value = /*d*/ ctx[3]?.["computed_optional"]);
attr(div, "e", div_e_value = /*e*/ ctx[4]());
attr(div, "f", div_f_value = /*f*/ ctx[5]?.());
},
m(target, anchor) {
insert(target, t0, anchor);
insert(target, t1, anchor);
insert(target, t2, anchor);
insert(target, t3, anchor);
insert(target, t4, anchor);
insert(target, t5, anchor);
insert(target, t6, anchor);
insert(target, t7, anchor);
insert(target, t8, anchor);
insert(target, div, anchor);
insert(target, t9, anchor);
mount_component(component, target, anchor);
current = true;
},
p(ctx, [dirty]) {
if ((!current || dirty & /*a*/ 1) && t0_value !== (t0_value = /*a*/ ctx[0].normal + "")) set_data(t0, t0_value);
if ((!current || dirty & /*b*/ 2) && t1_value !== (t1_value = /*b*/ ctx[1]?.optional + "")) set_data(t1, t1_value);
if ((!current || dirty & /*c*/ 4) && t3_value !== (t3_value = /*c*/ ctx[2]["computed"] + "")) set_data(t3, t3_value);
if ((!current || dirty & /*d*/ 8) && t4_value !== (t4_value = /*d*/ ctx[3]?.["computed_optional"] + "")) set_data(t4, t4_value);
if ((!current || dirty & /*e*/ 16) && t6_value !== (t6_value = /*e*/ ctx[4]() + "")) set_data(t6, t6_value);
if ((!current || dirty & /*f*/ 32) && t7_value !== (t7_value = /*f*/ ctx[5]?.() + "")) set_data(t7, t7_value);
if (!current || dirty & /*a*/ 1 && div_a_value !== (div_a_value = /*a*/ ctx[0].normal)) {
attr(div, "a", div_a_value);
}
if (!current || dirty & /*b*/ 2 && div_b_value !== (div_b_value = /*b*/ ctx[1]?.optional)) {
attr(div, "b", div_b_value);
}
if (!current || dirty & /*c*/ 4 && div_c_value !== (div_c_value = /*c*/ ctx[2]["computed"])) {
attr(div, "c", div_c_value);
}
if (!current || dirty & /*d*/ 8 && div_d_value !== (div_d_value = /*d*/ ctx[3]?.["computed_optional"])) {
attr(div, "d", div_d_value);
}
if (!current || dirty & /*e*/ 16 && div_e_value !== (div_e_value = /*e*/ ctx[4]())) {
attr(div, "e", div_e_value);
}
if (!current || dirty & /*f*/ 32 && div_f_value !== (div_f_value = /*f*/ ctx[5]?.())) {
attr(div, "f", div_f_value);
}
const component_changes = {};
if (dirty & /*a*/ 1) component_changes.a = /*a*/ ctx[0].normal;
if (dirty & /*b*/ 2) component_changes.b = /*b*/ ctx[1]?.optional;
if (dirty & /*c*/ 4) component_changes.c = /*c*/ ctx[2]["computed"];
if (dirty & /*d*/ 8) component_changes.d = /*d*/ ctx[3]?.["computed_optional"];
if (dirty & /*e*/ 16) component_changes.e = /*e*/ ctx[4]();
if (dirty & /*f*/ 32) component_changes.f = /*f*/ ctx[5]?.();
component.$set(component_changes);
},
i(local) {
if (current) return;
transition_in(component.$$.fragment, local);
current = true;
},
o(local) {
transition_out(component.$$.fragment, local);
current = false;
},
d(detaching) {
if (detaching) detach(t0);
if (detaching) detach(t1);
if (detaching) detach(t2);
if (detaching) detach(t3);
if (detaching) detach(t4);
if (detaching) detach(t5);
if (detaching) detach(t6);
if (detaching) detach(t7);
if (detaching) detach(t8);
if (detaching) detach(div);
if (detaching) detach(t9);
destroy_component(component, detaching);
}
};
}
function instance($$self, $$props, $$invalidate) {
let { a } = $$props;
let { b } = $$props;
let { c } = $$props;
let { d } = $$props;
let { e } = $$props;
let { f } = $$props;
let Component;
$$self.$set = $$props => {
if ("a" in $$props) $$invalidate(0, a = $$props.a);
if ("b" in $$props) $$invalidate(1, b = $$props.b);
if ("c" in $$props) $$invalidate(2, c = $$props.c);
if ("d" in $$props) $$invalidate(3, d = $$props.d);
if ("e" in $$props) $$invalidate(4, e = $$props.e);
if ("f" in $$props) $$invalidate(5, f = $$props.f);
};
return [a, b, c, d, e, f, Component];
}
class Component_1 extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { a: 0, b: 1, c: 2, d: 3, e: 4, f: 5 });
}
}
export default Component_1;

@ -0,0 +1,31 @@
<script>
export let a;
export let b;
export let c;
export let d;
export let e;
export let f;
let Component;
</script>
{a.normal}{b?.optional}
{c['computed']}{d?.['computed_optional']}
{e()}{f?.()}
<div
a={a.normal}
b={b?.optional}
c={c['computed']}
d={d?.['computed_optional']}
e={e()}
f={f?.()}
/>
<Component
a={a.normal}
b={b?.optional}
c={c['computed']}
d={d?.['computed_optional']}
e={e()}
f={f?.()}
/>

@ -64,7 +64,8 @@
"value": "tooltip msg",
"raw": "'tooltip msg'"
}
]
],
"optional": false
}
}
],

@ -52,10 +52,10 @@
}
],
"context": {
"start": 17,
"end": 22,
"type": "Identifier",
"name": "thing"
"name": "thing",
"start": 17,
"end": 22
},
"key": {
"type": "Identifier",

@ -26,10 +26,10 @@
},
"value": null,
"error": {
"start": 47,
"end": 55,
"type": "Identifier",
"name": "theError"
"name": "theError",
"start": 47,
"end": 55
},
"pending": {
"start": 19,
@ -152,7 +152,8 @@
},
"name": "message"
},
"computed": false
"computed": false,
"optional": false
}
}
]

@ -25,16 +25,16 @@
"name": "thePromise"
},
"value": {
"start": 46,
"end": 54,
"type": "Identifier",
"name": "theValue"
"name": "theValue",
"start": 46,
"end": 54
},
"error": {
"start": 96,
"end": 104,
"type": "Identifier",
"name": "theError"
"name": "theError",
"start": 96,
"end": 104
},
"pending": {
"start": 19,
@ -209,7 +209,8 @@
},
"name": "message"
},
"computed": false
"computed": false,
"optional": false
}
}
]

@ -275,7 +275,8 @@
},
"name": "then"
},
"computed": false
"computed": false,
"optional": false
},
"arguments": [
{
@ -403,7 +404,8 @@
},
"name": "log"
},
"computed": false
"computed": false,
"optional": false
},
"arguments": [
{
@ -452,21 +454,25 @@
},
"name": "default"
},
"computed": false
"computed": false,
"optional": false
}
]
],
"optional": false
}
}
]
}
}
]
],
"optional": false
}
}
]
}
}
]
],
"optional": false
}
}
],

@ -57,10 +57,10 @@
}
],
"context": {
"start": 18,
"end": 24,
"type": "Identifier",
"name": "animal"
"name": "animal",
"start": 18,
"end": 24
},
"else": {
"start": 50,

@ -85,10 +85,10 @@
}
],
"context": {
"start": 18,
"end": 24,
"type": "Identifier",
"name": "animal"
"name": "animal",
"start": 18,
"end": 24
},
"index": "i"
}

@ -57,10 +57,10 @@
}
],
"context": {
"start": 16,
"end": 20,
"type": "Identifier",
"name": "todo"
"name": "todo",
"start": 16,
"end": 20
},
"key": {
"type": "MemberExpression",
@ -108,7 +108,8 @@
},
"name": "id"
},
"computed": false
"computed": false,
"optional": false
}
}
]

@ -57,10 +57,10 @@
}
],
"context": {
"start": 18,
"end": 24,
"type": "Identifier",
"name": "animal"
"name": "animal",
"start": 18,
"end": 24
}
}
]

@ -116,10 +116,10 @@
"raw": "true"
},
"value": {
"start": 97,
"end": 98,
"type": "Identifier",
"name": "f"
"name": "f",
"start": 97,
"end": 98
},
"error": null,
"pending": {
@ -204,10 +204,10 @@
"raw": "true"
},
"value": {
"start": 137,
"end": 138,
"type": "Identifier",
"name": "f"
"name": "f",
"start": 137,
"end": 138
},
"error": null,
"pending": {

@ -57,10 +57,10 @@
}
],
"context": {
"start": 17,
"end": 19,
"type": "Identifier",
"name": "𐊧"
"name": "𐊧",
"start": 17,
"end": 19
}
}
]

@ -0,0 +1,12 @@
import * as assert from "assert";
export default {
preprocess: {
script: ({ content, attributes }) => {
assert.equal(content, "");
return {
code: `console.log("${attributes["the-answer"]}");`
};
}
}
};

@ -0,0 +1 @@
<script the-answer="42">console.log("42");</script>

@ -0,0 +1,12 @@
import * as assert from "assert";
export default {
preprocess: {
style: ({ content, attributes: { color } }) => {
assert.equal(content, "");
return {
code: `div { color: ${color}; }`
};
}
}
};

@ -0,0 +1,3 @@
<div class='brand-color'>$brand</div>
<style color="red"/>

@ -0,0 +1,3 @@
<div class='brand-color'>$brand</div>
<style color="red">div { color: red; }</style>

@ -0,0 +1,53 @@
let calls = [];
function callback(refs) {
calls.push(refs.map(({ ref }) => ({ ref })));
}
export default {
html: ``,
props: {
callback,
},
after_test() {
calls = [];
},
async test({ assert, component, target }) {
assert.equal(calls.length, 1);
assert.equal(calls[0].length, 0);
await component.addItem();
let divs = target.querySelectorAll("div");
assert.equal(calls.length, 3);
assert.equal(calls[1].length, 1);
assert.equal(calls[1][0].ref, null);
assert.equal(calls[2].length, 1);
assert.equal(calls[2][0].ref, divs[0]);
await component.addItem();
divs = target.querySelectorAll("div");
assert.equal(calls.length, 5);
assert.equal(calls[3].length, 2);
assert.equal(calls[3][0].ref, divs[0]);
assert.equal(calls[3][1].ref, null);
assert.equal(calls[4].length, 2);
assert.equal(calls[4][0].ref, divs[0]);
assert.equal(calls[4][1].ref, divs[1]);
await component.addItem();
divs = target.querySelectorAll("div");
assert.equal(calls.length, 7);
assert.equal(calls[5].length, 3);
assert.equal(calls[5][0].ref, divs[0]);
assert.equal(calls[5][1].ref, divs[1]);
assert.equal(calls[5][2].ref, null);
assert.equal(calls[6].length, 3);
assert.equal(calls[6][0].ref, divs[0]);
assert.equal(calls[6][1].ref, divs[1]);
assert.equal(calls[6][2].ref, divs[2]);
},
};

@ -0,0 +1,17 @@
<script>
import { tick } from 'svelte';
let refs = [];
export function addItem() {
refs = refs.concat({ ref: null });
return tick();
}
export let callback;
$: callback(refs);
</script>
{#each refs as xxx}
<div bind:this={xxx.ref} />
{/each}

@ -0,0 +1,15 @@
export default {
html: `
<div contenteditable=""></div>
`,
async test({ assert, component, target, window }) {
const div = target.querySelector('div');
const text = window.document.createTextNode('a');
div.insertBefore(text, null);
const event = new window.InputEvent('input');
await div.dispatchEvent(event);
assert.equal(div.textContent, 'a');
}
};

@ -0,0 +1,6 @@
<script>
let text = '';
const updater = (event) => {text = event.target.textContent}
</script>
<div contenteditable on:input={updater}>{text}</div>

@ -0,0 +1,8 @@
export default {
html: `
<span>
Style:
<a href="https://getbootstrap.com/" target="_blank">Bootstrap</a>.
</span>
`
};

@ -0,0 +1,5 @@
<span>
Style:
<!-- prettier-ignore -->
<a href="https://getbootstrap.com/" target="_blank">Bootstrap</a>.
</span>

@ -0,0 +1,5 @@
<script>
export let content;
</script>
{@html content}

@ -0,0 +1,33 @@
export default {
html: `
<button>Switch</button>
<p>Another first line</p>
<p>This line should be last.</p>
`,
async test({ assert, target, window }) {
const btn = target.querySelector("button");
const clickEvent = new window.MouseEvent("click");
await btn.dispatchEvent(clickEvent);
assert.htmlEqual(
target.innerHTML,
`
<button>Switch</button>
<p>First line</p>
<p>This line should be last.</p>
`
);
await btn.dispatchEvent(clickEvent);
assert.htmlEqual(
target.innerHTML,
`
<button>Switch</button>
<p>Another first line</p>
<p>This line should be last.</p>
`
);
},
};

@ -0,0 +1,17 @@
<script>
import RawMustache from './RawMustache.svelte';
let content1 = `<p>First line</p>`;
let content2 = `<p>Another first line</p>`;
let show = false;
$: content = show ? content1 : content2;
</script>
<button on:click={() => show = !show}>
Switch
</button>
<RawMustache {content} />
<p>This line should be last.</p>

@ -0,0 +1,16 @@
export default {
async test({ assert, target, window }) {
const btn = target.querySelector("button");
const clickEvent = new window.MouseEvent("click");
assert.equal(window.document.head.innerHTML.includes('<style>body { color: blue; }</style><style>body { color: green; }</style>'), true);
await btn.dispatchEvent(clickEvent);
assert.equal(window.document.head.innerHTML.includes('<style>body { color: red; }</style><style>body { color: green; }</style>'), true);
await btn.dispatchEvent(clickEvent);
assert.equal(window.document.head.innerHTML.includes('<style>body { color: blue; }</style><style>body { color: green; }</style>'), true);
},
};

@ -0,0 +1,16 @@
<script>
let content1 = `<style>body { color: red; }</style>`;
let content2 = `<style>body { color: blue; }</style>`
let show = false;
$: content = show ? content1 : content2;
</script>
<button on:click={() => show = !show}>
Switch
</button>
<svelte:head>
{@html content}
<style>body { color: green; }</style>
</svelte:head>

@ -0,0 +1,2 @@
<slot />
<p>This line should be last.</p>

@ -0,0 +1,33 @@
export default {
html: `
<button>Switch</button>
<p>Another first line</p>
<p>This line should be last.</p>
`,
async test({ assert, target, window }) {
const btn = target.querySelector("button");
const clickEvent = new window.MouseEvent("click");
await btn.dispatchEvent(clickEvent);
assert.htmlEqual(
target.innerHTML,
`
<button>Switch</button>
<p>First line</p>
<p>This line should be last.</p>
`
);
await btn.dispatchEvent(clickEvent);
assert.htmlEqual(
target.innerHTML,
`
<button>Switch</button>
<p>Another first line</p>
<p>This line should be last.</p>
`
);
},
};

@ -0,0 +1,17 @@
<script>
import Component from './Component.svelte';
let content1 = `<p>First line</p>`;
let content2 = `<p>Another first line</p>`
let show = false;
$: content = show ? content1 : content2;
</script>
<button on:click={() => show = !show}>
Switch
</button>
<Component>
{@html content}
</Component>

@ -0,0 +1,3 @@
export default {
error: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
};

@ -0,0 +1,9 @@
<script>
import { writable } from 'svelte/store';
const store = writable();
function foo() {
let store = 1;
$store = 2;
}
</script>

@ -0,0 +1,3 @@
export default {
error: `Stores must be declared at the top level of the component (this may change in a future version of Svelte)`
};

@ -0,0 +1,9 @@
<script>
import { writable } from 'svelte/store';
const store = writable();
</script>
<button
on:click={(store) => {
$store = Math.random();
}} />
Loading…
Cancel
Save