|
import { string_literal } from '../utils/stringify.js'; |
|
import add_to_set from '../utils/add_to_set.js'; |
|
import Node from './shared/Node.js'; |
|
import Expression from './shared/Expression.js'; |
|
import { x } from 'code-red'; |
|
import compiler_warnings from '../compiler_warnings.js'; |
|
|
|
|
|
export default class Attribute extends Node { |
|
|
|
scope; |
|
|
|
|
|
name; |
|
|
|
|
|
is_spread; |
|
|
|
|
|
is_true; |
|
|
|
|
|
is_static; |
|
|
|
|
|
expression; |
|
|
|
|
|
chunks; |
|
|
|
|
|
dependencies; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor(component, parent, scope, info) { |
|
super(component, parent, scope, info); |
|
this.scope = scope; |
|
|
|
if (info.type === 'Spread') { |
|
this.name = null; |
|
this.is_spread = true; |
|
this.is_true = false; |
|
this.expression = new Expression(component, this, scope, info.expression); |
|
this.dependencies = this.expression.dependencies; |
|
this.chunks = null; |
|
this.is_static = false; |
|
} else { |
|
this.name = info.name; |
|
this.is_true = info.value === true; |
|
this.is_static = true; |
|
this.dependencies = new Set(); |
|
this.chunks = this.is_true |
|
? [] |
|
: info.value.map((node) => { |
|
if (node.type === 'Text') return node; |
|
this.is_static = false; |
|
const expression = new Expression(component, this, scope, node.expression); |
|
add_to_set(this.dependencies, expression.dependencies); |
|
return expression; |
|
}); |
|
} |
|
|
|
if (this.dependencies.size > 0) { |
|
parent.cannot_use_innerhtml(); |
|
parent.not_static_content(); |
|
} |
|
|
|
|
|
if ( |
|
this.name && |
|
this.name.includes(':') && |
|
!this.name.startsWith('xmlns:') && |
|
!this.name.startsWith('xlink:') && |
|
!this.name.startsWith('xml:') |
|
) { |
|
component.warn(this, compiler_warnings.illegal_attribute_character); |
|
} |
|
} |
|
get_dependencies() { |
|
if (this.is_spread) return this.expression.dynamic_dependencies(); |
|
|
|
|
|
const dependencies = new Set(); |
|
this.chunks.forEach((chunk) => { |
|
if (chunk.type === 'Expression') { |
|
add_to_set(dependencies, chunk.dynamic_dependencies()); |
|
} |
|
}); |
|
return Array.from(dependencies); |
|
} |
|
|
|
|
|
get_value(block) { |
|
if (this.is_true) return x`true`; |
|
if (this.chunks.length === 0) return x`""`; |
|
if (this.chunks.length === 1) { |
|
return this.chunks[0].type === 'Text' |
|
? string_literal( (this.chunks[0]).data) |
|
: (this.chunks[0]).manipulate( |
|
block |
|
); |
|
} |
|
let expression = this.chunks |
|
.map( |
|
(chunk) => |
|
chunk.type === 'Text' ? string_literal(chunk.data) : chunk.manipulate(block) |
|
) |
|
.reduce((lhs, rhs) => x`${lhs} + ${rhs}`); |
|
if (this.chunks[0].type !== 'Text') { |
|
expression = x`"" + ${expression}`; |
|
} |
|
return expression; |
|
} |
|
get_static_value() { |
|
if (!this.is_static) return null; |
|
return this.is_true |
|
? true |
|
: this.chunks[0] |
|
? |
|
(this.chunks[0]).data |
|
: ''; |
|
} |
|
should_cache() { |
|
return this.is_static |
|
? false |
|
: this.chunks.length === 1 |
|
? |
|
this.chunks[0].node.type !== 'Identifier' || this.scope.names.has(this.chunks[0].node.name) |
|
: true; |
|
} |
|
} |
|
|