Merge pull request #2021 from sveltejs/gh-2017

rename `<svelte:meta>` to `<svelte:options>`
pull/2026/head
Rich Harris 6 years ago committed by GitHub
commit 96d14a15ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,4 +1,4 @@
<svelte:meta immutable/>
<svelte:options immutable/>
<script>
import ImmutableTodo from './ImmutableTodo.html';

@ -1,4 +1,4 @@
<svelte:meta immutable/>
<svelte:options immutable/>
<script>
import { afterUpdate } from 'svelte';

@ -23,7 +23,7 @@ import getObject from '../utils/getObject';
import deindent from '../utils/deindent';
import globalWhitelist from '../utils/globalWhitelist';
type Meta = {
type ComponentOptions = {
namespace?: string;
tag?: string;
immutable?: boolean;
@ -45,13 +45,13 @@ export default class Component {
source: string;
code: MagicString;
name: string;
options: CompileOptions;
compileOptions: CompileOptions;
fragment: Fragment;
module_scope: Scope;
instance_scope: Scope;
instance_scope_map: WeakMap<Node, Scope>;
meta: Meta;
componentOptions: ComponentOptions;
namespace: string;
tag: string;
@ -90,7 +90,7 @@ export default class Component {
ast: Ast,
source: string,
name: string,
options: CompileOptions,
compileOptions: CompileOptions,
stats: Stats
) {
this.name = name;
@ -98,34 +98,34 @@ export default class Component {
this.stats = stats;
this.ast = ast;
this.source = source;
this.options = options;
this.compileOptions = compileOptions;
this.file = options.filename && (
typeof process !== 'undefined' ? options.filename.replace(process.cwd(), '').replace(/^[\/\\]/, '') : options.filename
this.file = compileOptions.filename && (
typeof process !== 'undefined' ? compileOptions.filename.replace(process.cwd(), '').replace(/^[\/\\]/, '') : compileOptions.filename
);
this.locate = getLocator(this.source);
this.code = new MagicString(source);
// styles
this.stylesheet = new Stylesheet(source, ast, options.filename, options.dev);
this.stylesheet = new Stylesheet(source, ast, compileOptions.filename, compileOptions.dev);
this.stylesheet.validate(this);
this.meta = process_meta(this, this.ast.html.children);
this.namespace = namespaces[this.meta.namespace] || this.meta.namespace;
this.componentOptions = process_component_options(this, this.ast.html.children);
this.namespace = namespaces[this.componentOptions.namespace] || this.componentOptions.namespace;
if (this.meta.props) {
if (this.componentOptions.props) {
this.has_reactive_assignments = true;
}
if (options.customElement === true && !this.meta.tag) {
if (compileOptions.customElement === true && !this.componentOptions.tag) {
throw new Error(`No tag name specified`); // TODO better error
}
this.tag = options.customElement
? options.customElement === true
? this.meta.tag
: options.customElement as string
this.tag = compileOptions.customElement
? compileOptions.customElement === true
? this.componentOptions.tag
: compileOptions.customElement as string
: this.name;
this.walk_module_js();
@ -136,7 +136,7 @@ export default class Component {
this.walk_instance_js_post_template();
if (!options.customElement) this.stylesheet.reify();
if (!compileOptions.customElement) this.stylesheet.reify();
this.stylesheet.warnOnUnusedSelectors(stats);
}
@ -196,18 +196,18 @@ export default class Component {
}
generate(result: string) {
const { options, name } = this;
const { format = 'esm' } = options;
const { compileOptions, name } = this;
const { format = 'esm' } = compileOptions;
const banner = `/* ${this.file ? `${this.file} ` : ``}generated by Svelte v${"__VERSION__"} */`;
const helpers = new Set();
// TODO use same regex for both
result = result.replace(options.generate === 'ssr' ? /(@+|#+)(\w*(?:-\w*)?)/g : /(@+)(\w*(?:-\w*)?)/g, (match: string, sigil: string, name: string) => {
result = result.replace(compileOptions.generate === 'ssr' ? /(@+|#+)(\w*(?:-\w*)?)/g : /(@+)(\w*(?:-\w*)?)/g, (match: string, sigil: string, name: string) => {
if (sigil === '@') {
if (internal_exports.has(name)) {
if (options.dev && internal_exports.has(`${name}Dev`)) name = `${name}Dev`;
if (compileOptions.dev && internal_exports.has(`${name}Dev`)) name = `${name}Dev`;
helpers.add(name);
}
@ -228,10 +228,10 @@ export default class Component {
result,
format,
name,
options,
compileOptions,
this.stats,
banner,
options.sveltePath,
compileOptions.sveltePath,
importedHelpers,
this.imports,
this.vars.filter(variable => variable.module && variable.export_name).map(variable => ({
@ -252,7 +252,7 @@ export default class Component {
});
}
const { filename } = options;
const { filename } = compileOptions;
// special case — the source file doesn't actually get used anywhere. we need
// to add an empty file to populate map.sources and map.sourcesContent
@ -281,15 +281,15 @@ export default class Component {
addString(finalChunk);
const css = options.customElement ?
const css = compileOptions.customElement ?
{ code: null, map: null } :
this.stylesheet.render(options.cssOutputFilename, true);
this.stylesheet.render(compileOptions.cssOutputFilename, true);
const js = {
code: compiled.toString(),
map: compiled.generateMap({
includeContent: true,
file: options.outputFilename,
file: compileOptions.outputFilename,
})
};
@ -355,7 +355,7 @@ export default class Component {
source: this.source,
start: pos.start,
end: pos.end,
filename: this.options.filename
filename: this.compileOptions.filename
});
}
@ -385,7 +385,7 @@ export default class Component {
start,
end,
pos: pos.start,
filename: this.options.filename,
filename: this.compileOptions.filename,
toString: () => `${warning.message} (${start.line + 1}:${start.column})\n${frame}`,
});
}
@ -692,7 +692,7 @@ export default class Component {
rewrite_props() {
const component = this;
const { code, instance_scope, instance_scope_map: map, meta } = this;
const { code, instance_scope, instance_scope_map: map, componentOptions } = this;
let scope = instance_scope;
const coalesced_declarations = [];
@ -718,10 +718,10 @@ export default class Component {
extractNames(declarator.id).forEach(name => {
const variable = component.var_lookup.get(name);
if (name === meta.props_object) {
if (name === componentOptions.props_object) {
if (variable.export_name) {
component.error(declarator, {
code: 'exported-meta-props',
code: 'exported-options-props',
message: `Cannot export props binding`
});
}
@ -1073,12 +1073,12 @@ export default class Component {
}
}
function process_meta(component, nodes) {
const meta: Meta = {
immutable: component.options.immutable || false
function process_component_options(component: Component, nodes) {
const componentOptions: ComponentOptions = {
immutable: component.compileOptions.immutable || false
};
const node = nodes.find(node => node.name === 'svelte:meta');
const node = nodes.find(node => node.name === 'svelte:options');
function get_value(attribute, code, message) {
const { value } = attribute;
@ -1119,7 +1119,7 @@ function process_meta(component, nodes) {
});
}
meta.tag = tag;
componentOptions.tag = tag;
break;
}
@ -1145,7 +1145,7 @@ function process_meta(component, nodes) {
}
}
meta.namespace = ns;
componentOptions.namespace = ns;
break;
}
@ -1156,13 +1156,13 @@ function process_meta(component, nodes) {
if (typeof value !== 'boolean') component.error(attribute, { code, message });
meta.immutable = value;
componentOptions.immutable = value;
break;
default:
component.error(attribute, {
code: `invalid-meta-attribute`,
message: `<svelte:meta> unknown attribute`
code: `invalid-options-attribute`,
message: `<svelte:options> unknown attribute`
});
}
}
@ -1170,26 +1170,26 @@ function process_meta(component, nodes) {
else if (attribute.type === 'Binding') {
if (attribute.name !== 'props') {
component.error(attribute, {
code: `invalid-meta-binding`,
message: `<svelte:meta> only supports bind:props`
code: `invalid-options-binding`,
message: `<svelte:options> only supports bind:props`
});
}
const { start, end } = attribute.expression;
const { name } = flattenReference(attribute.expression);
meta.props = `[✂${start}-${end}✂]`;
meta.props_object = name;
componentOptions.props = `[✂${start}-${end}✂]`;
componentOptions.props_object = name;
}
else {
component.error(attribute, {
code: `invalid-meta-attribute`,
message: `<svelte:meta> can only have static 'tag', 'namespace' and 'immutable' attributes, or a bind:props directive`
code: `invalid-options-attribute`,
message: `<svelte:options> can only have static 'tag', 'namespace' and 'immutable' attributes, or a bind:props directive`
});
}
});
}
return meta;
return componentOptions;
}

@ -618,7 +618,7 @@ export default class Element extends Node {
}
}
if (component.options.legacy && (modifier === 'once' || modifier === 'passive')) {
if (component.compileOptions.legacy && (modifier === 'once' || modifier === 'passive')) {
// TODO this could be supported, but it would need a few changes to
// how event listeners work
component.error(handler, {
@ -695,4 +695,4 @@ function shouldHaveAttribute(
code: `a11y-missing-attribute`,
message: `A11y: <${name}> element should have ${article} ${sequence} attribute`
});
}
}

@ -1,5 +0,0 @@
import Node from './shared/Node';
export default class Meta extends Node {
type: 'Meta';
}

@ -0,0 +1,5 @@
import Node from './shared/Node';
export default class Options extends Node {
type: 'Options';
}

@ -49,7 +49,7 @@ export default class Node {
}
warnIfEmptyBlock() {
if (!this.component.options.dev) return;
if (!this.component.compileOptions.dev) return;
if (!/Block$/.test(this.type) || !this.children) return;
if (this.children.length > 1) return;
@ -62,4 +62,4 @@ export default class Node {
});
}
}
}
}

@ -6,8 +6,8 @@ import Element from '../Element';
import Head from '../Head';
import IfBlock from '../IfBlock';
import InlineComponent from '../InlineComponent';
import Meta from '../Meta';
import MustacheTag from '../MustacheTag';
import Options from '../Options';
import RawMustacheTag from '../RawMustacheTag';
import DebugTag from '../DebugTag';
import Slot from '../Slot';
@ -26,8 +26,8 @@ function getConstructor(type): typeof Node {
case 'Head': return Head;
case 'IfBlock': return IfBlock;
case 'InlineComponent': return InlineComponent;
case 'Meta': return Meta;
case 'MustacheTag': return MustacheTag;
case 'Options': return Options;
case 'RawMustacheTag': return RawMustacheTag;
case 'DebugTag': return DebugTag;
case 'Slot': return Slot;

@ -28,7 +28,7 @@ export default function dom(
const builder = new CodeBuilder();
if (component.options.dev) {
if (component.compileOptions.dev) {
builder.addLine(`const ${renderer.fileVar} = ${JSON.stringify(component.file)};`);
}
@ -37,7 +37,7 @@ export default function dom(
`${css.code}\n/*# sourceMappingURL=${css.map.toUrl()} */` :
css.code, { onlyEscapeAtSymbol: true });
if (styles && component.options.css !== false && !options.customElement) {
if (styles && component.compileOptions.css !== false && !options.customElement) {
builder.addBlock(deindent`
function @add_css() {
var style = @createElement("style");
@ -73,13 +73,13 @@ export default function dom(
const props = component.vars.filter(variable => !variable.module && variable.export_name);
const writable_props = props.filter(variable => variable.writable);
const set = (component.meta.props || writable_props.length > 0 || renderer.slots.size > 0)
const set = (component.componentOptions.props || writable_props.length > 0 || renderer.slots.size > 0)
? deindent`
$$props => {
${component.meta.props && deindent`
if (!${component.meta.props}) ${component.meta.props} = {};
@assign(${component.meta.props}, $$props);
$$invalidate('${component.meta.props_object}', ${component.meta.props_object});
${component.componentOptions.props && deindent`
if (!${component.componentOptions.props}) ${component.componentOptions.props} = {};
@assign(${component.componentOptions.props}, $$props);
$$invalidate('${component.componentOptions.props_object}', ${component.componentOptions.props_object});
`}
${writable_props.map(prop =>
`if ('${prop.export_name}' in $$props) $$invalidate('${prop.name}', ${prop.name} = $$props.${prop.export_name});`)}
@ -91,7 +91,7 @@ export default function dom(
const body = [];
const not_equal = component.meta.immutable ? `@not_equal` : `@safe_not_equal`;
const not_equal = component.componentOptions.immutable ? `@not_equal` : `@safe_not_equal`;
let dev_props_check;
props.forEach(x => {
@ -118,7 +118,7 @@ export default function dom(
@flush();
}
`);
} else if (component.options.dev) {
} else if (component.compileOptions.dev) {
body.push(deindent`
set ${x.export_name}(value) {
throw new Error("<${component.tag}>: Cannot set read-only property '${x.export_name}'");
@ -127,7 +127,7 @@ export default function dom(
}
});
if (component.options.dev) {
if (component.compileOptions.dev) {
// TODO check no uunexpected props were passed, as well as
// checking that expected ones were passed
const expected = props.filter(prop => !prop.initialised);
@ -306,7 +306,7 @@ export default function dom(
const reactive_store_subscriptions = reactive_stores.length > 0 && reactive_stores
.map(({ name }) => deindent`
let ${name};
${component.options.dev && `@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
${component.compileOptions.dev && `@validate_store(${name.slice(1)}, '${name.slice(1)}');`}
$$self.$$.on_destroy.push(${name.slice(1)}.subscribe($$value => { ${name} = $$value; $$invalidate('${name}', ${name}); }));
`)
.join('\n\n');
@ -355,7 +355,7 @@ export default function dom(
@insert(options.target, this, options.anchor);
}
${(props.length > 0 || component.meta.props) && deindent`
${(props.length > 0 || component.componentOptions.props) && deindent`
if (options.props) {
this.$set(options.props);
@flush();

@ -64,9 +64,9 @@ export default class AttributeWrapper {
? '@setXlinkAttribute'
: '@setAttribute';
const isLegacyInputType = element.renderer.component.options.legacy && name === 'type' && this.parent.node.name === 'input';
const isLegacyInputType = element.renderer.component.compileOptions.legacy && name === 'type' && this.parent.node.name === 'input';
const isDataSet = /^data-/.test(name) && !element.renderer.component.options.legacy && !element.node.namespace;
const isDataSet = /^data-/.test(name) && !element.renderer.component.compileOptions.legacy && !element.node.namespace;
const camelCaseName = isDataSet ? name.replace('data-', '').replace(/(-\w)/g, function (m) {
return m[1].toUpperCase();
}) : name;

@ -29,8 +29,8 @@ const wrappers = {
Head,
IfBlock,
InlineComponent,
Meta: null,
MustacheTag,
Options: null,
RawMustacheTag,
Slot,
Text,

@ -138,7 +138,7 @@ export default class InlineComponentWrapper extends Wrapper {
});
}
if (component.options.dev) {
if (component.compileOptions.dev) {
// TODO this is a terrible hack, but without it the component
// will complain that options.target is missing. This would
// work better if components had separate public and private
@ -507,4 +507,4 @@ function isComputed(node: Node) {
}
return false;
}
}

@ -162,9 +162,9 @@ export default class WindowWrapper extends Wrapper {
const handler_name = block.getUniqueName(`onlinestatuschanged`);
block.builders.init.addBlock(deindent`
function ${handler_name}(event) {
${component.options.dev && `component._updatingReadonlyProperty = true;`}
${component.compileOptions.dev && `component._updatingReadonlyProperty = true;`}
#component.set({ ${bindings.online}: navigator.onLine });
${component.options.dev && `component._updatingReadonlyProperty = false;`}
${component.compileOptions.dev && `component._updatingReadonlyProperty = false;`}
}
window.addEventListener("online", ${handler_name});
window.addEventListener("offline", ${handler_name});

@ -27,8 +27,8 @@ const handlers: Record<string, Handler> = {
Head,
IfBlock,
InlineComponent,
Meta: noop,
MustacheTag: Tag, // TODO MustacheTag is an anachronism
Options: noop,
RawMustacheTag: HtmlTag,
Slot,
Text,

@ -38,7 +38,7 @@ export default function ssr(
const reactive_store_values = reactive_stores.map(({ name }) => {
const assignment = `const ${name} = @get_store_value(${name.slice(1)});`;
return component.options.dev
return component.compileOptions.dev
? `@validate_store(${name.slice(1)}, '${name.slice(1)}'); ${assignment}`
: assignment;
});

@ -12,7 +12,7 @@ const validTagName = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
const metaTags = new Map([
['svelte:head', 'Head'],
['svelte:meta', 'Meta'],
['svelte:options', 'Options'],
['svelte:window', 'Window'],
['svelte:body', 'Body']
]);

@ -1,3 +1,3 @@
<svelte:meta tag="my-element"/>
<svelte:options tag="my-element"/>
<p>Hello world!</p>
<p>Hello world!</p>

@ -1,4 +1,4 @@
<svelte:meta tag="custom-element"/>
<svelte:options tag="custom-element"/>
<script>
export function updateFoo(value) {
@ -8,4 +8,4 @@
export let foo;
</script>
<p>{foo}</p>
<p>{foo}</p>

@ -1,4 +1,4 @@
<svelte:meta tag="custom-element"/>
<svelte:options tag="custom-element"/>
<span class='icon'></span>
@ -6,4 +6,4 @@
.icon::before {
content: '\ff'
}
</style>
</style>

@ -1,4 +1,4 @@
<svelte:meta tag="custom-element"/>
<svelte:options tag="custom-element"/>
<div>
<slot>
@ -8,4 +8,4 @@
<slot name='foo'>
<p>foo fallback content</p>
</slot>
</div>
</div>

@ -1,7 +1,7 @@
<svelte:meta tag="custom-element"/>
<svelte:options tag="custom-element"/>
<script>
export let name;
</script>
<h1>Hello {name}!</h1>
<h1>Hello {name}!</h1>

@ -1,7 +1,7 @@
<svelte:meta tag="my-counter"/>
<svelte:options tag="my-counter"/>
<script>
export let count = 0;
</script>
<button on:click='{() => count += 1}'>count: {count}</button>
<button on:click='{() => count += 1}'>count: {count}</button>

@ -1,4 +1,4 @@
<svelte:meta tag="my-app"/>
<svelte:options tag="my-app"/>
<script>
import Counter from './Counter.html';
@ -7,4 +7,4 @@
</script>
<Counter bind:count/>
<p>clicked {count} times</p>
<p>clicked {count} times</p>

@ -1,4 +1,4 @@
<svelte:meta tag="custom-element"/>
<svelte:options tag="custom-element"/>
<p>styled</p>
@ -6,4 +6,4 @@
p {
color: red;
}
</style>
</style>

@ -1,7 +1,7 @@
<svelte:meta tag="custom-element"/>
<svelte:options tag="custom-element"/>
<script>
export let name;
</script>
<h1>Hello {name}!</h1>
<h1>Hello {name}!</h1>

@ -1,4 +1,4 @@
<svelte:meta tag="my-app"/>
<svelte:options tag="my-app"/>
<script>
export let foo;
@ -6,4 +6,4 @@
</script>
<p>foo: {foo}</p>
<p>bar: {bar}</p>
<p>bar: {bar}</p>

@ -1,4 +1,4 @@
<svelte:meta tag="my-app"/>
<svelte:options tag="my-app"/>
<script>
import { onMount } from 'svelte';
@ -9,4 +9,3 @@
wasCreated = true;
});
</script>

@ -1,4 +1,4 @@
<svelte:meta tag="custom-element"/>
<svelte:options tag="custom-element"/>
<script>
import './my-widget.html';
@ -6,4 +6,4 @@
export let items = ['a', 'b', 'c'];
</script>
<my-widget class="foo" {items}/>
<my-widget class="foo" {items}/>

@ -1,8 +1,8 @@
<svelte:meta tag="my-widget"/>
<svelte:options tag="my-widget"/>
<script>
export let items = [];
</script>
<p>{items.length} items</p>
<p>{items.join(', ')}</p>
<p>{items.join(', ')}</p>

@ -1,7 +1,7 @@
<svelte:meta immutable/>
<svelte:options immutable/>
<script>
const Nested = window.Nested;
</script>
<Nested foo='bar'/>
<Nested foo='bar'/>

@ -1,4 +1,4 @@
<svelte:meta tag="custom-element"/>
<svelte:options tag="custom-element"/>
<div>fades in</div>
@ -11,4 +11,4 @@
0% { opacity: 0; }
100% { opacity: 1; }
}
</style>
</style>

@ -1,6 +1,6 @@
{
"code": "invalid-tag-name",
"message": "Valid <svelte:...> tag names are svelte:head, svelte:meta, svelte:window, svelte:body, svelte:self or svelte:component",
"message": "Valid <svelte:...> tag names are svelte:head, svelte:options, svelte:window, svelte:body, svelte:self or svelte:component",
"pos": 10,
"start": {
"character": 10,

@ -1,4 +1,4 @@
<svelte:meta immutable={false}/>
<svelte:options immutable={false}/>
<script>
export let count = 0;
@ -9,4 +9,4 @@
<div>
<h3>Called {count} times.</h3>
</div>
</div>

@ -1,4 +1,4 @@
<svelte:meta immutable/>
<svelte:options immutable/>
<script>
export let count = 0;
@ -9,4 +9,4 @@
<div>
<h3>Called {count} times.</h3>
</div>
</div>

@ -1,4 +1,4 @@
<svelte:meta bind:props/>
<svelte:options bind:props/>
<script>
import Widget from './Widget.html';

@ -1,4 +1,4 @@
<svelte:meta namespace="svg"/>
<svelte:options namespace="svg"/>
<script>
export let x;

@ -1,4 +1,4 @@
<svelte:meta namespace="http://www.w3.org/2000/svg"/>
<svelte:options namespace="http://www.w3.org/2000/svg"/>
<script>
export let x;

@ -1,15 +1,15 @@
[{
"code": "invalid-namespace-property",
"message": "Invalid namespace 'lol'",
"pos": 13,
"pos": 16,
"start": {
"line": 1,
"column": 13,
"character": 13
"column": 16,
"character": 16
},
"end": {
"line": 1,
"column": 28,
"character": 28
"column": 31,
"character": 31
}
}]

@ -1 +1 @@
<svelte:meta namespace="lol"/>
<svelte:options namespace="lol"/>

@ -1,15 +1,15 @@
[{
"code": "invalid-namespace-property",
"message": "Invalid namespace 'http://www.w3.org/1999/svg' (did you mean 'http://www.w3.org/2000/svg'?)",
"pos": 13,
"pos": 16,
"start": {
"line": 1,
"column": 13,
"character": 13
"column": 16,
"character": 16
},
"end": {
"line": 1,
"column": 51,
"character": 51
"column": 54,
"character": 54
}
}]

@ -1 +1 @@
<svelte:meta namespace="http://www.w3.org/1999/svg"/>
<svelte:options namespace="http://www.w3.org/1999/svg"/>

@ -1,15 +1,15 @@
[{
"code": "invalid-namespace-attribute",
"message": "The 'namespace' attribute must be a string literal representing a valid namespace",
"pos": 13,
"pos": 16,
"start": {
"line": 1,
"column": 13,
"character": 13
"column": 16,
"character": 16
},
"end": {
"line": 1,
"column": 27,
"character": 27
"column": 30,
"character": 30
}
}]

@ -1 +1 @@
<svelte:meta namespace={ns}/>
<svelte:options namespace={ns}/>

@ -1,4 +1,4 @@
<svelte:meta namespace="svg"/>
<svelte:options namespace="svg"/>
<script>
export let x;

@ -3,13 +3,13 @@
"message": "tag name must be two or more words joined by the '-' character",
"start": {
"line": 1,
"column": 13,
"character": 13
"column": 16,
"character": 16
},
"end": {
"line": 1,
"column": 26,
"character": 26
"column": 29,
"character": 29
},
"pos": 13
}]
"pos": 16
}]

@ -1 +1 @@
<svelte:meta tag="invalid"/>
<svelte:options tag="invalid"/>

@ -3,13 +3,13 @@
"message": "'tag' must be a string literal",
"start": {
"line": 1,
"column": 13,
"character": 13
"column": 16,
"character": 16
},
"end": {
"line": 1,
"column": 21,
"character": 21
"column": 24,
"character": 24
},
"pos": 13
}]
"pos": 16
}]

@ -1 +1 @@
<svelte:meta tag={42}/>
<svelte:options tag={42}/>

Loading…
Cancel
Save