update options.customElement/<svelte:options tag='...'> handling (#2025)

pull/2162/head
Conduitry 6 years ago
parent 27ec345f31
commit 1e1784adaf

@ -119,15 +119,14 @@ export default class Component {
this.componentOptions = process_component_options(this, this.ast.html.children); this.componentOptions = process_component_options(this, this.ast.html.children);
this.namespace = namespaces[this.componentOptions.namespace] || this.componentOptions.namespace; this.namespace = namespaces[this.componentOptions.namespace] || this.componentOptions.namespace;
if (compileOptions.customElement === true && !this.componentOptions.tag) { if (compileOptions.customElement) {
throw new Error(`No tag name specified`); // TODO better error this.tag = compileOptions.customElement.tag || this.componentOptions.tag;
if (!this.tag) {
throw new Error(`Cannot compile to a custom element without specifying a tag name via options.customElement or <svelte:options>`);
}
} else {
this.tag = this.name;
} }
this.tag = compileOptions.customElement
? compileOptions.customElement === true
? this.componentOptions.tag
: compileOptions.customElement as string
: this.name;
this.walk_module_js(); this.walk_module_js();
this.walk_instance_js_pre_template(); this.walk_instance_js_pre_template();

@ -3,7 +3,7 @@ import Stats from '../Stats';
import parse from '../parse/index'; import parse from '../parse/index';
import renderDOM from './render-dom/index'; import renderDOM from './render-dom/index';
import renderSSR from './render-ssr/index'; import renderSSR from './render-ssr/index';
import { CompileOptions, Ast, Warning } from '../interfaces'; import { CompileOptions, Ast, Warning, CustomElementOptions } from '../interfaces';
import Component from './Component'; import Component from './Component';
import fuzzymatch from '../utils/fuzzymatch'; import fuzzymatch from '../utils/fuzzymatch';
@ -41,6 +41,10 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
throw new Error(`options.name must be a valid identifier (got '${name}')`); throw new Error(`options.name must be a valid identifier (got '${name}')`);
} }
if ('customElement' in options) {
options.customElement = normalize_customElement_option(options.customElement);
}
if (name && /^[a-z]/.test(name)) { if (name && /^[a-z]/.test(name)) {
const message = `options.name should be capitalised`; const message = `options.name should be capitalised`;
warnings.push({ warnings.push({
@ -52,6 +56,34 @@ function validate_options(options: CompileOptions, warnings: Warning[]) {
} }
} }
const valid_customElement_options = ['tag'];
function normalize_customElement_option(customElement: boolean | string | CustomElementOptions) {
if (typeof customElement === 'boolean') {
return customElement ? {} : null;
} else if (typeof customElement === 'string') {
customElement = { tag: customElement };
} else if (typeof customElement === 'object') {
Object.keys(customElement).forEach(key => {
if (valid_customElement_options.indexOf(key) === -1) {
const match = fuzzymatch(key, valid_customElement_options);
let message = `Unrecognized option 'customElement.${key}'`;
if (match) message += ` (did you mean 'customElement.${match}'?)`;
throw new Error(message);
}
});
} else {
throw new Error(`options.customElement must be a boolean, a string or an object`);
}
if ('tag' in customElement && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(customElement.tag)) {
throw new Error(`options.customElement tag name must be two or more words joined by the '-' character`);
}
return customElement;
}
function get_name(filename) { function get_name(filename) {
if (!filename) return null; if (!filename) return null;
const parts = filename.split(/[\/\\]/); const parts = filename.split(/[\/\\]/);

@ -52,7 +52,7 @@ export interface CompileOptions {
immutable?: boolean; immutable?: boolean;
hydratable?: boolean; hydratable?: boolean;
legacy?: boolean; legacy?: boolean;
customElement?: CustomElementOptions | true; customElement?: CustomElementOptions;
css?: boolean; css?: boolean;
preserveComments?: boolean | false; preserveComments?: boolean | false;
@ -65,7 +65,6 @@ export interface Visitor {
export interface CustomElementOptions { export interface CustomElementOptions {
tag?: string; tag?: string;
props?: string[];
} }
export interface AppendTarget { export interface AppendTarget {

@ -9,7 +9,7 @@ import error from '../utils/error';
interface ParserOptions { interface ParserOptions {
filename?: string; filename?: string;
bind?: boolean; bind?: boolean;
customElement?: CustomElementOptions | true; customElement?: CustomElementOptions;
} }
type ParserState = (parser: Parser) => (ParserState | void); type ParserState = (parser: Parser) => (ParserState | void);
@ -17,7 +17,7 @@ type ParserState = (parser: Parser) => (ParserState | void);
export class Parser { export class Parser {
readonly template: string; readonly template: string;
readonly filename?: string; readonly filename?: string;
readonly customElement: CustomElementOptions | true; readonly customElement: CustomElementOptions;
index = 0; index = 0;
stack: Array<Node> = []; stack: Array<Node> = [];

Loading…
Cancel
Save