@ -2,222 +2,197 @@ import { set_current_component, current_component } from './lifecycle';
import { run_all , blank_object } from './utils' ;
import { boolean_attributes } from '../../shared/boolean_attributes' ;
export { is_void } from '../../shared/utils/names' ;
export const invalid_attribute_name_character =
/ [ \ s ' " > / = \ u { F D D 0 } - \ u { F D E F } \ u { F F F E } \ u { F F F F } \ u { 1 F F F E } \ u { 1 F F F F } \ u { 2 F F F E } \ u { 2 F F F F } \ u { 3 F F F E } \ u { 3 F F F F } \ u { 4 F F F E } \ u { 4 F F F F } \ u { 5 F F F E } \ u { 5 F F F F } \ u { 6 F F F E } \ u { 6 F F F F } \ u { 7 F F F E } \ u { 7 F F F F } \ u { 8 F F F E } \ u { 8 F F F F } \ u { 9 F F F E } \ u { 9 F F F F } \ u { A F F F E } \ u { A F F F F } \ u { B F F F E } \ u { B F F F F } \ u { C F F F E } \ u { C F F F F } \ u { D F F F E } \ u { D F F F F } \ u { E F F F E } \ u { E F F F F } \ u { F F F F E } \ u { F F F F F } \ u { 1 0 F F F E } \ u { 1 0 F F F F } ] / u ;
export const invalid_attribute_name_character = / [ \ s ' " > / = \ u { F D D 0 } - \ u { F D E F } \ u { F F F E } \ u { F F F F } \ u { 1 F F F E } \ u { 1 F F F F } \ u { 2 F F F E } \ u { 2 F F F F } \ u { 3 F F F E } \ u { 3 F F F F } \ u { 4 F F F E } \ u { 4 F F F F } \ u { 5 F F F E } \ u { 5 F F F F } \ u { 6 F F F E } \ u { 6 F F F F } \ u { 7 F F F E } \ u { 7 F F F F } \ u { 8 F F F E } \ u { 8 F F F F } \ u { 9 F F F E } \ u { 9 F F F F } \ u { A F F F E } \ u { A F F F F } \ u { B F F F E } \ u { B F F F F } \ u { C F F F E } \ u { C F F F F } \ u { D F F F E } \ u { D F F F F } \ u { E F F F E } \ u { E F F F F } \ u { F F F F E } \ u { F F F F F } \ u { 1 0 F F F E } \ u { 1 0 F F F F } ] / u ;
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
// https://infra.spec.whatwg.org/#noncharacter
/** @returns {string} */
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 ;
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 ;
}
/** @returns {{}} */
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 ] = val ue;
}
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 ;
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 )
contin ue;
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 ;
}
const ATTR_REGEX = /[&"]/g ;
const CONTENT_REGEX = /[&<]/g ;
/ * *
* Note : this method is performance sensitive and has been optimized
* https : //github.com/sveltejs/svelte/pull/5701
* @param { unknown } value
* @returns { string }
* /
export function escape ( value : unknown , is_attr = false ) {
const str = String ( value ) ;
const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX ;
pattern . lastIndex = 0 ;
let escaped = '' ;
let last = 0 ;
while ( pattern . test ( str ) ) {
const i = pattern . lastIndex - 1 ;
const ch = str [ i ] ;
escaped += str . substring ( last , i ) + ( ch === '&' ? '&' : ch === '"' ? '"' : '<' ) ;
last = i + 1 ;
}
return escaped + str . substring ( last ) ;
export function escape ( value , is_attr = false ) {
const str = String ( value ) ;
const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX ;
pattern . lastIndex = 0 ;
let escaped = '' ;
let last = 0 ;
while ( pattern . test ( str ) ) {
const i = pattern . lastIndex - 1 ;
const ch = str [ i ] ;
escaped += str . substring ( last , i ) + ( ch === '&' ? '&' : ch === '"' ? '"' : '<' ) ;
last = i + 1 ;
}
return escaped + str . substring ( last ) ;
}
/** @returns {any} */
export function escape_attribute_value ( value ) {
// keep booleans, null, and undefined for the sake of `spread`
const should_escape = typeof value === 'string' || ( value && typeof value === 'object' ) ;
return should_escape ? escape ( value , true ) : value ;
// keep booleans, null, and undefined for the sake of `spread`
const should_escape = typeof value === 'string' || ( value && typeof value === 'object' ) ;
return should_escape ? escape ( value , true ) : value ;
}
/** @returns {{}} */
export function escape_object ( obj ) {
const result = { } ;
for ( const key in obj ) {
result [ key ] = escape_attribute_value ( obj [ key ] ) ;
}
return result ;
const result = { } ;
for ( const key in obj ) {
result [ key ] = escape_attribute_value ( obj [ key ] ) ;
}
return result ;
}
/** @returns {string} */
export function each ( items , fn ) {
let str = '' ;
for ( let i = 0 ; i < items . length ; i += 1 ) {
str += fn ( items [ i ] , i ) ;
}
return str ;
let str = '' ;
for ( let i = 0 ; i < items . length ; i += 1 ) {
str += fn ( items [ i ] , i ) ;
}
return str ;
}
export const missing_component = {
$ $render : ( ) = > ''
$ $render : ( ) = > ''
} ;
/** @returns {any} */
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 ;
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 ;
}
/** @returns {string} */
export function debug ( file , line , column , values ) {
console . log ( ` {@debug} ${ file ? file + ' ' : '' } ( ${ line } : ${ column } ) ` ) ; // eslint-disable-line no-console
console . log ( values ) ; // eslint-disable-line no-console
return '' ;
console . log ( ` {@debug} ${ file ? file + ' ' : '' } ( ${ line } : ${ column } ) ` ) ; // eslint-disable-line no-console
console . log ( values ) ; // eslint-disable-line no-console
return '' ;
}
let on_destroy ;
/** @returns {{ render: (props?: {}, { $$slots, context }?: { $$slots?: {}; context?: Map<any, any>; }) => { html: any; css: { code: string; map: any; }; head: string; }; $$render: (result: any, props: any, bindings: any, slots: any, context: any) => any; }} */
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 : [ ] ) ) ,
// these will be immediately discarded
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 : string ;
head : string ;
css : Set < {
map : null ;
code : string ;
} > ;
} = { 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 // TODO
} ,
head : result.title + result . head
} ;
} ,
$ $render
} ;
/** @returns {any} */
function $ $render ( result , props , bindings , slots , context ) {
const parent_component = current_component ;
const $ $ = {
on_destroy ,
context : new Map ( context || ( parent_component ? parent_component . $ $ . context : [ ] ) ) ,
// these will be immediately discarded
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 // TODO
} ,
head : result.title + result . head
} ;
} ,
$ $render
} ;
}
/** @returns {string} */
export function add_attribute ( name , value , boolean ) {
if ( value == null || ( boolean && ! value ) ) return '' ;
const assignment = boolean && value === true ? '' : ` =" ${ escape ( value , true ) } " ` ;
return ` ${ name } ${ assignment } ` ;
if ( value == null || ( boolean && ! value ) )
return '' ;
const assignment = boolean && value === true ? '' : ` =" ${ escape ( value , true ) } " ` ;
return ` ${ name } ${ assignment } ` ;
}
/** @returns {string} */
export function add_classes ( classes ) {
return classes ? ` class=" ${ classes } " ` : '' ;
return classes ? ` class=" ${ classes } " ` : '' ;
}
/** @returns {string} */
function style_object_to_string ( style_object ) {
return Object . keys ( style_object )
. filter ( ( key ) = > style_object [ key ] )
. map ( ( key ) = > ` ${ key } : ${ escape_attribute_value ( style_object [ key ] ) } ; ` )
. join ( ' ' ) ;
return Object . keys ( style_object )
. filter ( ( key ) = > style_object [ key ] )
. map ( ( key ) = > ` ${ key } : ${ escape_attribute_value ( style_object [ key ] ) } ; ` )
. join ( ' ' ) ;
}
/** @returns {string} */
export function add_styles ( style_object ) {
const styles = style_object_to_string ( style_object ) ;
return styles ? ` style=" ${ styles } " ` : '' ;
const styles = style_object_to_string ( style_object ) ;
return styles ? ` style=" ${ styles } " ` : '' ;
}