mirror of https://github.com/sveltejs/svelte
106 lines
2.7 KiB
106 lines
2.7 KiB
import { set_current_component } from './lifecycle.js';
|
|
import { run_all, blankObject } from './utils.js';
|
|
|
|
export const invalidAttributeNameCharacter = /[\s'">\/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u;
|
|
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
|
|
// https://infra.spec.whatwg.org/#noncharacter
|
|
|
|
export function spread(args) {
|
|
const attributes = Object.assign({}, ...args);
|
|
let str = '';
|
|
|
|
Object.keys(attributes).forEach(name => {
|
|
if (invalidAttributeNameCharacter.test(name)) return;
|
|
|
|
const value = attributes[name];
|
|
if (value === undefined) return;
|
|
if (value === true) str += " " + name;
|
|
|
|
const escaped = String(value)
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''');
|
|
|
|
str += " " + name + "=" + JSON.stringify(escaped);
|
|
});
|
|
|
|
return str;
|
|
}
|
|
|
|
export const escaped = {
|
|
'"': '"',
|
|
"'": ''',
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>'
|
|
};
|
|
|
|
export function escape(html) {
|
|
return String(html).replace(/["'&<>]/g, match => escaped[match]);
|
|
}
|
|
|
|
export function each(items, fn) {
|
|
let str = '';
|
|
for (let i = 0; i < items.length; i += 1) {
|
|
str += fn(items[i], i);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
export const missingComponent = {
|
|
$$render: () => ''
|
|
};
|
|
|
|
export function validate_component(component, name) {
|
|
if (!component || !component.$$render) {
|
|
if (name === 'svelte:component') name += ' this={...}';
|
|
throw new Error(`<${name}> is not a valid SSR component. You may need to review your build config to ensure that dependencies are compiled, rather than imported as pre-compiled modules`);
|
|
}
|
|
|
|
return component;
|
|
}
|
|
|
|
export function debug(file, line, column, values) {
|
|
console.log(`{@debug} ${file ? file + ' ' : ''}(${line}:${column})`);
|
|
console.log(values);
|
|
return '';
|
|
}
|
|
|
|
export function create_ssr_component($$render) {
|
|
return {
|
|
render: (props = {}, options = {}) => {
|
|
// TODO do we need on_ready, since on_mount,
|
|
// before_render and after_render don't run?
|
|
const $$ = {
|
|
on_mount: [],
|
|
on_destroy: [],
|
|
before_render: [],
|
|
after_render: [],
|
|
callbacks: blankObject()
|
|
};
|
|
|
|
set_current_component({ $$ });
|
|
|
|
const result = { head: '', css: new Set() };
|
|
const html = $$render(result, props, {}, options);
|
|
|
|
run_all($$.on_destroy);
|
|
|
|
return {
|
|
html,
|
|
css: {
|
|
code: Array.from(result.css).map(css => css.code).join('\n'),
|
|
map: null // TODO
|
|
},
|
|
head: result.head
|
|
};
|
|
},
|
|
|
|
$$render
|
|
};
|
|
}
|
|
|
|
export function get_store_value(store) {
|
|
let value;
|
|
store.subscribe(_ => value = _)();
|
|
return value;
|
|
} |