|
import { set_current_component, current_component } from './lifecycle.js'; |
|
import { run_all, blank_object } from './utils.js'; |
|
import { boolean_attributes } from '../../shared/boolean_attributes.js'; |
|
import { ensure_array_like } from './each.js'; |
|
import { escape } from '../../shared/utils/escape.js'; |
|
export { is_void } from '../../shared/utils/names.js'; |
|
export { escape }; |
|
|
|
export const invalid_attribute_name_character = |
|
/[\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; |
|
|
|
|
|
|
|
|
|
export function spread(args, attrs_to_add) { |
|
const attributes = Object.assign({}, ...args); |
|
if (attrs_to_add) { |
|
const classes_to_add = attrs_to_add.classes; |
|
const styles_to_add = attrs_to_add.styles; |
|
if (classes_to_add) { |
|
if (attributes.class == null) { |
|
attributes.class = classes_to_add; |
|
} else { |
|
attributes.class += ' ' + classes_to_add; |
|
} |
|
} |
|
if (styles_to_add) { |
|
if (attributes.style == null) { |
|
attributes.style = style_object_to_string(styles_to_add); |
|
} else { |
|
attributes.style = style_object_to_string( |
|
merge_ssr_styles(attributes.style, styles_to_add) |
|
); |
|
} |
|
} |
|
} |
|
let str = ''; |
|
Object.keys(attributes).forEach((name) => { |
|
if (invalid_attribute_name_character.test(name)) return; |
|
const value = attributes[name]; |
|
if (value === true) str += ' ' + name; |
|
else if (boolean_attributes.has(name.toLowerCase())) { |
|
if (value) str += ' ' + name; |
|
} else if (value != null) { |
|
str += ` ${name}="${value}"`; |
|
} |
|
}); |
|
return str; |
|
} |
|
|
|
|
|
export function merge_ssr_styles(style_attribute, style_directive) { |
|
const style_object = {}; |
|
for (const individual_style of style_attribute.split(';')) { |
|
const colon_index = individual_style.indexOf(':'); |
|
const name = individual_style.slice(0, colon_index).trim(); |
|
const value = individual_style.slice(colon_index + 1).trim(); |
|
if (!name) continue; |
|
style_object[name] = value; |
|
} |
|
for (const name in style_directive) { |
|
const value = style_directive[name]; |
|
if (value) { |
|
style_object[name] = value; |
|
} else { |
|
delete style_object[name]; |
|
} |
|
} |
|
return style_object; |
|
} |
|
|
|
export function escape_attribute_value(value) { |
|
|
|
const should_escape = typeof value === 'string' || (value && typeof value === 'object'); |
|
return should_escape ? escape(value, true) : value; |
|
} |
|
|
|
|
|
export function escape_object(obj) { |
|
const result = {}; |
|
for (const key in obj) { |
|
result[key] = escape_attribute_value(obj[key]); |
|
} |
|
return result; |
|
} |
|
|
|
|
|
export function each(items, fn) { |
|
items = ensure_array_like(items); |
|
let str = ''; |
|
for (let i = 0; i < items.length; i += 1) { |
|
str += fn(items[i], i); |
|
} |
|
return str; |
|
} |
|
|
|
export const missing_component = { |
|
$$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. Otherwise you may need to fix a <${name}>.` |
|
); |
|
} |
|
return component; |
|
} |
|
|
|
|
|
export function debug(file, line, column, values) { |
|
console.log(`{@debug} ${file ? file + ' ' : ''}(${line}:${column})`); |
|
console.log(values); |
|
return ''; |
|
} |
|
|
|
let on_destroy; |
|
|
|
|
|
export function create_ssr_component(fn) { |
|
function $$render(result, props, bindings, slots, context) { |
|
const parent_component = current_component; |
|
const $$ = { |
|
on_destroy, |
|
context: new Map(context || (parent_component ? parent_component.$$.context : [])), |
|
|
|
on_mount: [], |
|
before_update: [], |
|
after_update: [], |
|
callbacks: blank_object() |
|
}; |
|
set_current_component({ $$ }); |
|
const html = fn(result, props, bindings, slots); |
|
set_current_component(parent_component); |
|
return html; |
|
} |
|
return { |
|
render: (props = {}, { $$slots = {}, context = new Map() } = {}) => { |
|
on_destroy = []; |
|
const result = { title: '', head: '', css: new Set() }; |
|
const html = $$render(result, props, {}, $$slots, context); |
|
run_all(on_destroy); |
|
return { |
|
html, |
|
css: { |
|
code: Array.from(result.css) |
|
.map((css) => css.code) |
|
.join('\n'), |
|
map: null |
|
}, |
|
head: result.title + result.head |
|
}; |
|
}, |
|
$$render |
|
}; |
|
} |
|
|
|
|
|
export function add_attribute(name, value, boolean) { |
|
if (value == null || (boolean && !value)) return ''; |
|
const assignment = boolean && value === true ? '' : `="${escape(value, true)}"`; |
|
return ` ${name}${assignment}`; |
|
} |
|
|
|
|
|
export function add_classes(classes) { |
|
return classes ? ` class="${classes}"` : ''; |
|
} |
|
|
|
|
|
function style_object_to_string(style_object) { |
|
return Object.keys(style_object) |
|
.filter((key) => style_object[key] != null && style_object[key] !== '') |
|
.map((key) => `${key}: ${escape_attribute_value(style_object[key])};`) |
|
.join(' '); |
|
} |
|
|
|
|
|
export function add_styles(style_object) { |
|
const styles = style_object_to_string(style_object); |
|
return styles ? ` style="${styles}"` : ''; |
|
} |
|
|