parent
c632f41e75
commit
a57016e14e
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@bd/core",
|
"name": "@bd/core",
|
||||||
"version": "1.3.0",
|
"version": "1.4.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "百搭UI组件库的核心",
|
"description": "百搭UI组件库的核心",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|
|
@ -27,7 +27,8 @@ const boolMap = Object.create(null)
|
||||||
'noShade',
|
'noShade',
|
||||||
'open',
|
'open',
|
||||||
'readOnly',
|
'readOnly',
|
||||||
'selected'
|
'selected',
|
||||||
|
'loading'
|
||||||
].forEach(function (name) {
|
].forEach(function (name) {
|
||||||
boolMap[name.toLowerCase()] = name
|
boolMap[name.toLowerCase()] = name
|
||||||
})
|
})
|
||||||
|
|
305
src/html.js
305
src/html.js
|
@ -1,80 +1,57 @@
|
||||||
import { WC_PART, NO_CHANGE, NOTHING } from './constants.js'
|
import { boolMap, WC_PART, NO_CHANGE, NOTHING } from './constants.js'
|
||||||
|
|
||||||
var ENABLE_EXTRA_SECURITY_HOOKS = true
|
const boundAttributeSuffix = '$wc$'
|
||||||
|
const marker = `wc$${String(Math.random()).slice(9)}$`
|
||||||
var identityFunction = value => value
|
const markerMatch = '?' + marker
|
||||||
var noopSanitizer = (_node, _name, _type) => identityFunction
|
const nodeMarker = `<${markerMatch}>`
|
||||||
var setSanitizer = newSanitizer => {
|
const createMarker = (v = '') => document.createComment(v)
|
||||||
if (!ENABLE_EXTRA_SECURITY_HOOKS) {
|
const isPrimitive = value =>
|
||||||
return
|
|
||||||
}
|
|
||||||
if (sanitizerFactoryInternal !== noopSanitizer) {
|
|
||||||
throw new Error(
|
|
||||||
`Attempted to overwrite existing lit-html security policy. setSanitizeDOMValueFactory should be called at most once.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
sanitizerFactoryInternal = newSanitizer
|
|
||||||
}
|
|
||||||
var _testOnlyClearSanitizerFactoryDoNotCallOrElse = () => {
|
|
||||||
sanitizerFactoryInternal = noopSanitizer
|
|
||||||
}
|
|
||||||
var createSanitizer = (node, name, type) => {
|
|
||||||
return sanitizerFactoryInternal(node, name, type)
|
|
||||||
}
|
|
||||||
var boundAttributeSuffix = '$wc$'
|
|
||||||
var marker = `wc$${String(Math.random()).slice(9)}$`
|
|
||||||
var markerMatch = '?' + marker
|
|
||||||
var nodeMarker = `<${markerMatch}>`
|
|
||||||
var createMarker = (v = '') => document.createComment(v)
|
|
||||||
var isPrimitive = value =>
|
|
||||||
value === null || (typeof value != 'object' && typeof value != 'function')
|
value === null || (typeof value != 'object' && typeof value != 'function')
|
||||||
var isArray = Array.isArray
|
const isArray = Array.isArray
|
||||||
var isIterable = value =>
|
const isIterable = value =>
|
||||||
isArray(value) ||
|
isArray(value) ||
|
||||||
typeof (value === null || value === void 0
|
typeof (value === null || value === void 0
|
||||||
? false
|
? false
|
||||||
: value[Symbol.iterator]) === 'function'
|
: value[Symbol.iterator]) === 'function'
|
||||||
var SPACE_CHAR = `[ \n\f\r]`
|
const SPACE_CHAR = `[ \n\f\r]`
|
||||||
var ATTR_VALUE_CHAR = `[^ \n\f\r"'\`<>=]`
|
const ATTR_VALUE_CHAR = `[^ \n\f\r"'\`<>=]`
|
||||||
var NAME_CHAR = `[^\\s"'>=/]`
|
const NAME_CHAR = `[^\\s"'>=/]`
|
||||||
var textEndRegex = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g
|
const textEndRegex = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g
|
||||||
var COMMENT_START = 1
|
const COMMENT_START = 1
|
||||||
var TAG_NAME = 2
|
const TAG_NAME = 2
|
||||||
var DYNAMIC_TAG_NAME = 3
|
const DYNAMIC_TAG_NAME = 3
|
||||||
var commentEndRegex = /-->/g
|
const commentEndRegex = /-->/g
|
||||||
var comment2EndRegex = />/g
|
const comment2EndRegex = />/g
|
||||||
var tagEndRegex = new RegExp(
|
const tagEndRegex = new RegExp(
|
||||||
`>|${SPACE_CHAR}(?:(${NAME_CHAR}+)(${SPACE_CHAR}*=${SPACE_CHAR}*(?:${ATTR_VALUE_CHAR}|("|')|))|$)`,
|
`>|${SPACE_CHAR}(?:(${NAME_CHAR}+)(${SPACE_CHAR}*=${SPACE_CHAR}*(?:${ATTR_VALUE_CHAR}|("|')|))|$)`,
|
||||||
'g'
|
'g'
|
||||||
)
|
)
|
||||||
var ENTIRE_MATCH = 0
|
const ENTIRE_MATCH = 0
|
||||||
var ATTRIBUTE_NAME = 1
|
const ATTRIBUTE_NAME = 1
|
||||||
var SPACES_AND_EQUALS = 2
|
const SPACES_AND_EQUALS = 2
|
||||||
var QUOTE_CHAR = 3
|
const QUOTE_CHAR = 3
|
||||||
var singleQuoteAttrEndRegex = /'/g
|
const singleQuoteAttrEndRegex = /'/g
|
||||||
var doubleQuoteAttrEndRegex = /"/g
|
const doubleQuoteAttrEndRegex = /"/g
|
||||||
var rawTextElement = /^(?:script|style|textarea|title)$/i
|
const rawTextElement = /^(?:script|style|textarea|title)$/i
|
||||||
var HTML_RESULT = 1
|
const HTML_RESULT = 1
|
||||||
var SVG_RESULT = 2
|
const SVG_RESULT = 2
|
||||||
var ATTRIBUTE_PART = 1
|
const ATTRIBUTE_PART = 1
|
||||||
var CHILD_PART = 2
|
const CHILD_PART = 2
|
||||||
var PROPERTY_PART = 3
|
const EVENT_PART = 5
|
||||||
var BOOLEAN_ATTRIBUTE_PART = 4
|
const ELEMENT_PART = 6
|
||||||
var EVENT_PART = 5
|
const COMMENT_PART = 7
|
||||||
var ELEMENT_PART = 6
|
|
||||||
var COMMENT_PART = 7
|
|
||||||
|
|
||||||
var templateCache = new WeakMap()
|
const templateCache = new WeakMap()
|
||||||
var walker = document.createTreeWalker(document, 129, null, false)
|
const walker = document.createTreeWalker(document, 129, null, false)
|
||||||
var sanitizerFactoryInternal = noopSanitizer
|
|
||||||
var getTemplateHtml = (strings, type) => {
|
function getTemplateHtml(strings, type) {
|
||||||
const len = strings.length - 1
|
let len = strings.length - 1
|
||||||
const attrNames = []
|
let attrNames = []
|
||||||
let html2 = type === SVG_RESULT ? '<svg>' : ''
|
let html2 = type === SVG_RESULT ? '<svg>' : ''
|
||||||
let rawTextEndRegex
|
let rawTextEndRegex
|
||||||
let regex = textEndRegex
|
let regex = textEndRegex
|
||||||
for (let i = 0; i < len; i++) {
|
for (let i = 0; i < len; i++) {
|
||||||
const s = strings[i]
|
let s = strings[i]
|
||||||
let attrNameEndIndex = -1
|
let attrNameEndIndex = -1
|
||||||
let attrName
|
let attrName
|
||||||
let lastIndex = 0
|
let lastIndex = 0
|
||||||
|
@ -131,7 +108,7 @@ var getTemplateHtml = (strings, type) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const end =
|
let end =
|
||||||
regex === tagEndRegex && strings[i + 1].startsWith('/>') ? ' ' : ''
|
regex === tagEndRegex && strings[i + 1].startsWith('/>') ? ' ' : ''
|
||||||
html2 +=
|
html2 +=
|
||||||
regex === textEndRegex
|
regex === textEndRegex
|
||||||
|
@ -147,7 +124,7 @@ var getTemplateHtml = (strings, type) => {
|
||||||
marker +
|
marker +
|
||||||
(attrNameEndIndex === -2 ? (attrNames.push(void 0), i) : end)
|
(attrNameEndIndex === -2 ? (attrNames.push(void 0), i) : end)
|
||||||
}
|
}
|
||||||
const htmlResult =
|
let htmlResult =
|
||||||
html2 + (strings[len] || '<?>') + (type === SVG_RESULT ? '</svg>' : '')
|
html2 + (strings[len] || '<?>') + (type === SVG_RESULT ? '</svg>' : '')
|
||||||
if (!Array.isArray(strings) || !strings.hasOwnProperty('raw')) {
|
if (!Array.isArray(strings) || !strings.hasOwnProperty('raw')) {
|
||||||
let message = 'invalid template strings array'
|
let message = 'invalid template strings array'
|
||||||
|
@ -162,44 +139,43 @@ class Template {
|
||||||
let node
|
let node
|
||||||
let nodeIndex = 0
|
let nodeIndex = 0
|
||||||
let attrNameIndex = 0
|
let attrNameIndex = 0
|
||||||
const partCount = strings.length - 1
|
let partCount = strings.length - 1
|
||||||
const parts = this.parts
|
let parts = this.parts
|
||||||
const [html2, attrNames] = getTemplateHtml(strings, type)
|
let [html2, attrNames] = getTemplateHtml(strings, type)
|
||||||
this.el = Template.createElement(html2, options)
|
this.el = Template.createElement(html2, options)
|
||||||
walker.currentNode = this.el.content
|
walker.currentNode = this.el.content
|
||||||
if (type === SVG_RESULT) {
|
if (type === SVG_RESULT) {
|
||||||
const content = this.el.content
|
let content = this.el.content
|
||||||
const svgElement = content.firstChild
|
let svgElement = content.firstChild
|
||||||
svgElement.remove()
|
svgElement.remove()
|
||||||
content.append(...svgElement.childNodes)
|
content.append(...svgElement.childNodes)
|
||||||
}
|
}
|
||||||
while ((node = walker.nextNode()) !== null && parts.length < partCount) {
|
while ((node = walker.nextNode()) !== null && parts.length < partCount) {
|
||||||
if (node.nodeType === 1) {
|
if (node.nodeType === 1) {
|
||||||
if (node.hasAttributes()) {
|
if (node.hasAttributes()) {
|
||||||
const attrsToRemove = []
|
let attrsToRemove = []
|
||||||
for (const name of node.getAttributeNames()) {
|
for (let name of node.getAttributeNames()) {
|
||||||
if (
|
if (
|
||||||
name.endsWith(boundAttributeSuffix) ||
|
name.endsWith(boundAttributeSuffix) ||
|
||||||
name.startsWith(marker)
|
name.startsWith(marker)
|
||||||
) {
|
) {
|
||||||
const realName = attrNames[attrNameIndex++]
|
let realName = attrNames[attrNameIndex++]
|
||||||
attrsToRemove.push(name)
|
attrsToRemove.push(name)
|
||||||
if (realName !== void 0) {
|
if (realName !== void 0) {
|
||||||
const value = node.getAttribute(
|
let value = node.getAttribute(
|
||||||
realName.toLowerCase() + boundAttributeSuffix
|
realName.toLowerCase() + boundAttributeSuffix
|
||||||
)
|
)
|
||||||
const statics = value.split(marker)
|
let statics = value.split(marker)
|
||||||
const m = /([.?@])?(.*)/.exec(realName)
|
let m = /([:@])?(.*)/.exec(realName)
|
||||||
|
|
||||||
parts.push({
|
parts.push({
|
||||||
type: ATTRIBUTE_PART,
|
type: ATTRIBUTE_PART,
|
||||||
index: nodeIndex,
|
index: nodeIndex,
|
||||||
name: m[2],
|
name: m[2],
|
||||||
strings: statics,
|
strings: statics,
|
||||||
ctor:
|
ctor:
|
||||||
m[1] === '.'
|
m[1] === ':'
|
||||||
? PropertyPart
|
? PropertyPart
|
||||||
: m[1] === '?'
|
|
||||||
? BooleanAttributePart
|
|
||||||
: m[1] === '@'
|
: m[1] === '@'
|
||||||
? EventPart
|
? EventPart
|
||||||
: AttributePart
|
: AttributePart
|
||||||
|
@ -212,13 +188,13 @@ class Template {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const name of attrsToRemove) {
|
for (let name of attrsToRemove) {
|
||||||
node.removeAttribute(name)
|
node.removeAttribute(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rawTextElement.test(node.tagName)) {
|
if (rawTextElement.test(node.tagName)) {
|
||||||
const strings2 = node.textContent.split(marker)
|
let strings2 = node.textContent.split(marker)
|
||||||
const lastIndex = strings2.length - 1
|
let lastIndex = strings2.length - 1
|
||||||
if (lastIndex > 0) {
|
if (lastIndex > 0) {
|
||||||
node.textContent = ''
|
node.textContent = ''
|
||||||
for (let i = 0; i < lastIndex; i++) {
|
for (let i = 0; i < lastIndex; i++) {
|
||||||
|
@ -230,7 +206,7 @@ class Template {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (node.nodeType === 8) {
|
} else if (node.nodeType === 8) {
|
||||||
const data = node.data
|
let data = node.data
|
||||||
if (data === markerMatch) {
|
if (data === markerMatch) {
|
||||||
parts.push({ type: CHILD_PART, index: nodeIndex })
|
parts.push({ type: CHILD_PART, index: nodeIndex })
|
||||||
} else {
|
} else {
|
||||||
|
@ -259,7 +235,7 @@ function resolveDirective(part, value, parent = part, attributeIndex) {
|
||||||
? parent.__directives?.[attributeIndex]
|
? parent.__directives?.[attributeIndex]
|
||||||
: parent.__directive
|
: parent.__directive
|
||||||
|
|
||||||
const nextDirectiveConstructor = isPrimitive(value)
|
let nextDirectiveConstructor = isPrimitive(value)
|
||||||
? void 0
|
? void 0
|
||||||
: value['_$litDirective$']
|
: value['_$litDirective$']
|
||||||
|
|
||||||
|
@ -294,6 +270,7 @@ function resolveDirective(part, value, parent = part, attributeIndex) {
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
class TemplateInstance {
|
class TemplateInstance {
|
||||||
constructor(template, parent) {
|
constructor(template, parent) {
|
||||||
this._parts = []
|
this._parts = []
|
||||||
|
@ -356,7 +333,7 @@ class TemplateInstance {
|
||||||
}
|
}
|
||||||
_update(values) {
|
_update(values) {
|
||||||
let i = 0
|
let i = 0
|
||||||
for (const part of this._parts) {
|
for (let part of this._parts) {
|
||||||
if (part !== void 0) {
|
if (part !== void 0) {
|
||||||
if (part.strings !== void 0) {
|
if (part.strings !== void 0) {
|
||||||
part._$setValue(values, part, i)
|
part._$setValue(values, part, i)
|
||||||
|
@ -369,6 +346,7 @@ class TemplateInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChildPart {
|
class ChildPart {
|
||||||
constructor(startNode, endNode, parent, options) {
|
constructor(startNode, endNode, parent, options) {
|
||||||
this.type = CHILD_PART
|
this.type = CHILD_PART
|
||||||
|
@ -379,16 +357,13 @@ class ChildPart {
|
||||||
this._$parent = parent
|
this._$parent = parent
|
||||||
this.options = options
|
this.options = options
|
||||||
this.__isConnected = options?.isConnected || true
|
this.__isConnected = options?.isConnected || true
|
||||||
if (ENABLE_EXTRA_SECURITY_HOOKS) {
|
|
||||||
this._textSanitizer = void 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
get _$isConnected() {
|
get _$isConnected() {
|
||||||
return this._$parent?._$isConnected || this.__isConnected
|
return this._$parent?._$isConnected || this.__isConnected
|
||||||
}
|
}
|
||||||
get parentNode() {
|
get parentNode() {
|
||||||
let parentNode = this._$startNode.parentNode
|
let parentNode = this._$startNode.parentNode
|
||||||
const parent = this._$parent
|
let parent = this._$parent
|
||||||
if (parent !== void 0 && parentNode.nodeType === 11) {
|
if (parent !== void 0 && parentNode.nodeType === 11) {
|
||||||
parentNode = parent.parentNode
|
parentNode = parent.parentNode
|
||||||
}
|
}
|
||||||
|
@ -405,7 +380,7 @@ class ChildPart {
|
||||||
if (isPrimitive(value)) {
|
if (isPrimitive(value)) {
|
||||||
if (value === NOTHING || value == null || value === '') {
|
if (value === NOTHING || value == null || value === '') {
|
||||||
if (this._$committedValue !== NOTHING) {
|
if (this._$committedValue !== NOTHING) {
|
||||||
this._$clear()
|
this.#clear()
|
||||||
}
|
}
|
||||||
this._$committedValue = NOTHING
|
this._$committedValue = NOTHING
|
||||||
} else if (value !== this._$committedValue && value !== NO_CHANGE) {
|
} else if (value !== this._$committedValue && value !== NO_CHANGE) {
|
||||||
|
@ -426,17 +401,7 @@ class ChildPart {
|
||||||
}
|
}
|
||||||
_commitNode(value) {
|
_commitNode(value) {
|
||||||
if (this._$committedValue !== value) {
|
if (this._$committedValue !== value) {
|
||||||
this._$clear()
|
this.#clear()
|
||||||
if (
|
|
||||||
ENABLE_EXTRA_SECURITY_HOOKS &&
|
|
||||||
sanitizerFactoryInternal !== noopSanitizer
|
|
||||||
) {
|
|
||||||
const parentNodeName = this._$startNode.parentNode?.nodeName
|
|
||||||
|
|
||||||
if (parentNodeName === 'STYLE' || parentNodeName === 'SCRIPT') {
|
|
||||||
throw new Error('Forbidden')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._$committedValue = this._insert(value)
|
this._$committedValue = this._insert(value)
|
||||||
}
|
}
|
||||||
|
@ -446,34 +411,17 @@ class ChildPart {
|
||||||
this._$committedValue !== NOTHING &&
|
this._$committedValue !== NOTHING &&
|
||||||
isPrimitive(this._$committedValue)
|
isPrimitive(this._$committedValue)
|
||||||
) {
|
) {
|
||||||
const node = this._$startNode.nextSibling
|
let node = this._$startNode.nextSibling
|
||||||
if (ENABLE_EXTRA_SECURITY_HOOKS) {
|
|
||||||
if (this._textSanitizer === void 0) {
|
|
||||||
this._textSanitizer = createSanitizer(node, 'data', 'property')
|
|
||||||
}
|
|
||||||
value = this._textSanitizer(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
node.data = value
|
node.data = value
|
||||||
} else {
|
} else {
|
||||||
if (ENABLE_EXTRA_SECURITY_HOOKS) {
|
this._commitNode(document.createTextNode(value))
|
||||||
const textNode = document.createTextNode('')
|
|
||||||
this._commitNode(textNode)
|
|
||||||
if (this._textSanitizer === void 0) {
|
|
||||||
this._textSanitizer = createSanitizer(textNode, 'data', 'property')
|
|
||||||
}
|
|
||||||
value = this._textSanitizer(value)
|
|
||||||
|
|
||||||
textNode.data = value
|
|
||||||
} else {
|
|
||||||
this._commitNode(document.createTextNode(value))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this._$committedValue = value
|
this._$committedValue = value
|
||||||
}
|
}
|
||||||
_commitTemplateResult(result) {
|
_commitTemplateResult(result) {
|
||||||
const { values, ['__dom_type__']: type } = result
|
let { values, ['__dom_type__']: type } = result
|
||||||
const template =
|
let template =
|
||||||
typeof type === 'number'
|
typeof type === 'number'
|
||||||
? this._$getTemplate(result)
|
? this._$getTemplate(result)
|
||||||
: (type.el === void 0 &&
|
: (type.el === void 0 &&
|
||||||
|
@ -483,8 +431,8 @@ class ChildPart {
|
||||||
if (this._$committedValue?._$template === template) {
|
if (this._$committedValue?._$template === template) {
|
||||||
this._$committedValue._update(values)
|
this._$committedValue._update(values)
|
||||||
} else {
|
} else {
|
||||||
const instance = new TemplateInstance(template, this)
|
let instance = new TemplateInstance(template, this)
|
||||||
const fragment = instance._clone(this.options)
|
let fragment = instance._clone(this.options)
|
||||||
|
|
||||||
instance._update(values)
|
instance._update(values)
|
||||||
|
|
||||||
|
@ -502,12 +450,12 @@ class ChildPart {
|
||||||
_commitIterable(value) {
|
_commitIterable(value) {
|
||||||
if (!isArray(this._$committedValue)) {
|
if (!isArray(this._$committedValue)) {
|
||||||
this._$committedValue = []
|
this._$committedValue = []
|
||||||
this._$clear()
|
this.#clear()
|
||||||
}
|
}
|
||||||
const itemParts = this._$committedValue
|
let itemParts = this._$committedValue
|
||||||
let partIndex = 0
|
let partIndex = 0
|
||||||
let itemPart
|
let itemPart
|
||||||
for (const item of value) {
|
for (let item of value) {
|
||||||
if (partIndex === itemParts.length) {
|
if (partIndex === itemParts.length) {
|
||||||
itemParts.push(
|
itemParts.push(
|
||||||
(itemPart = new ChildPart(
|
(itemPart = new ChildPart(
|
||||||
|
@ -524,11 +472,12 @@ class ChildPart {
|
||||||
partIndex++
|
partIndex++
|
||||||
}
|
}
|
||||||
if (partIndex < itemParts.length) {
|
if (partIndex < itemParts.length) {
|
||||||
this._$clear(itemPart && itemPart._$endNode.nextSibling, partIndex)
|
this.#clear(itemPart && itemPart._$endNode.nextSibling, partIndex)
|
||||||
itemParts.length = partIndex
|
itemParts.length = partIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_$clear(start = this._$startNode.nextSibling, from) {
|
|
||||||
|
#clear(start = this._$startNode.nextSibling, from) {
|
||||||
this._$notifyConnectionChanged?.call(this, false, true, from)
|
this._$notifyConnectionChanged?.call(this, false, true, from)
|
||||||
|
|
||||||
while (start && start !== this._$endNode) {
|
while (start && start !== this._$endNode) {
|
||||||
|
@ -544,6 +493,7 @@ class ChildPart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 常规属性
|
||||||
class AttributePart {
|
class AttributePart {
|
||||||
constructor(element, name, strings, parent, options) {
|
constructor(element, name, strings, parent, options) {
|
||||||
this.type = ATTRIBUTE_PART
|
this.type = ATTRIBUTE_PART
|
||||||
|
@ -559,9 +509,6 @@ class AttributePart {
|
||||||
} else {
|
} else {
|
||||||
this._$committedValue = NOTHING
|
this._$committedValue = NOTHING
|
||||||
}
|
}
|
||||||
if (ENABLE_EXTRA_SECURITY_HOOKS) {
|
|
||||||
this._sanitizer = void 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
get tagName() {
|
get tagName() {
|
||||||
return this.element.tagName
|
return this.element.tagName
|
||||||
|
@ -569,8 +516,9 @@ class AttributePart {
|
||||||
get _$isConnected() {
|
get _$isConnected() {
|
||||||
return this._$parent._$isConnected
|
return this._$parent._$isConnected
|
||||||
}
|
}
|
||||||
|
|
||||||
_$setValue(value, directiveParent = this, valueIndex, noCommit) {
|
_$setValue(value, directiveParent = this, valueIndex, noCommit) {
|
||||||
const strings = this.strings
|
let strings = this.strings
|
||||||
let change = false
|
let change = false
|
||||||
if (strings === void 0) {
|
if (strings === void 0) {
|
||||||
value = resolveDirective(this, value, directiveParent, 0)
|
value = resolveDirective(this, value, directiveParent, 0)
|
||||||
|
@ -581,7 +529,7 @@ class AttributePart {
|
||||||
this._$committedValue = value
|
this._$committedValue = value
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const values = value
|
let values = value
|
||||||
value = strings[0]
|
value = strings[0]
|
||||||
|
|
||||||
for (let i = 0; i < strings.length - 1; i++) {
|
for (let i = 0; i < strings.length - 1; i++) {
|
||||||
|
@ -604,70 +552,45 @@ class AttributePart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (change && !noCommit) {
|
if (change && !noCommit) {
|
||||||
this._commitValue(value)
|
this.#commitValue(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_commitValue(value) {
|
|
||||||
if (value === NOTHING) {
|
|
||||||
this.element.removeAttribute(this.name)
|
|
||||||
} else {
|
|
||||||
if (ENABLE_EXTRA_SECURITY_HOOKS) {
|
|
||||||
if (this._sanitizer === void 0) {
|
|
||||||
this._sanitizer = sanitizerFactoryInternal(
|
|
||||||
this.element,
|
|
||||||
this.name,
|
|
||||||
'attribute'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
value = this._sanitizer(value !== null && value !== void 0 ? value : '')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.element.setAttribute(
|
#commitValue(value) {
|
||||||
this.name,
|
let isBoolAttr = boolMap[this.name]
|
||||||
value !== null && value !== void 0 ? value : ''
|
|
||||||
)
|
if (isBoolAttr) {
|
||||||
|
this.element[isBoolAttr] = !(value === false || value === null)
|
||||||
|
|
||||||
|
if (this.element[isBoolAttr]) {
|
||||||
|
this.element.setAttribute(this.name, '')
|
||||||
|
} else {
|
||||||
|
this.element.removeAttribute(this.name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value === null || value === void 0) {
|
||||||
|
this.element.removeAttribute(this.name)
|
||||||
|
} else {
|
||||||
|
this.element.setAttribute(this.name, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 赋值属性
|
||||||
class PropertyPart extends AttributePart {
|
class PropertyPart extends AttributePart {
|
||||||
constructor() {
|
constructor(...args) {
|
||||||
super(...arguments)
|
super(...args)
|
||||||
this.type = PROPERTY_PART
|
|
||||||
}
|
}
|
||||||
_commitValue(value) {
|
|
||||||
if (ENABLE_EXTRA_SECURITY_HOOKS) {
|
|
||||||
if (this._sanitizer === void 0) {
|
|
||||||
this._sanitizer = sanitizerFactoryInternal(
|
|
||||||
this.element,
|
|
||||||
this.name,
|
|
||||||
'property'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
value = this._sanitizer(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.element[this.name] = value === NOTHING ? void 0 : value
|
#commitValue(value) {
|
||||||
}
|
this.element[this.name] = value
|
||||||
}
|
|
||||||
|
|
||||||
class BooleanAttributePart extends AttributePart {
|
|
||||||
constructor() {
|
|
||||||
super(...arguments)
|
|
||||||
this.type = BOOLEAN_ATTRIBUTE_PART
|
|
||||||
}
|
|
||||||
_commitValue(value) {
|
|
||||||
if (value && value !== NOTHING) {
|
|
||||||
// 布尔属性,值固定为空
|
|
||||||
this.element.setAttribute(this.name, '')
|
|
||||||
} else {
|
|
||||||
this.element.removeAttribute(this.name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 事件属性
|
||||||
class EventPart extends AttributePart {
|
class EventPart extends AttributePart {
|
||||||
constructor(element, name, strings, parent, options) {
|
constructor(...args) {
|
||||||
super(element, name, strings, parent, options)
|
super(...args)
|
||||||
this.type = EVENT_PART
|
this.type = EVENT_PART
|
||||||
}
|
}
|
||||||
_$setValue(newListener, directiveParent = this) {
|
_$setValue(newListener, directiveParent = this) {
|
||||||
|
@ -677,13 +600,13 @@ class EventPart extends AttributePart {
|
||||||
if (newListener === NO_CHANGE) {
|
if (newListener === NO_CHANGE) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const oldListener = this._$committedValue
|
let oldListener = this._$committedValue
|
||||||
const shouldRemoveListener =
|
let shouldRemoveListener =
|
||||||
(newListener === NOTHING && oldListener !== NOTHING) ||
|
(newListener === NOTHING && oldListener !== NOTHING) ||
|
||||||
newListener.capture !== oldListener.capture ||
|
newListener.capture !== oldListener.capture ||
|
||||||
newListener.once !== oldListener.once ||
|
newListener.once !== oldListener.once ||
|
||||||
newListener.passive !== oldListener.passive
|
newListener.passive !== oldListener.passive
|
||||||
const shouldAddListener =
|
let shouldAddListener =
|
||||||
newListener !== NOTHING &&
|
newListener !== NOTHING &&
|
||||||
(oldListener === NOTHING || shouldRemoveListener)
|
(oldListener === NOTHING || shouldRemoveListener)
|
||||||
|
|
||||||
|
@ -703,6 +626,7 @@ class EventPart extends AttributePart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ElementPart {
|
class ElementPart {
|
||||||
constructor(element, parent, options) {
|
constructor(element, parent, options) {
|
||||||
this.element = element
|
this.element = element
|
||||||
|
@ -749,8 +673,3 @@ export const svg = (strings, ...values) => {
|
||||||
values
|
values
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ENABLE_EXTRA_SECURITY_HOOKS) {
|
|
||||||
render.setSanitizer = setSanitizer
|
|
||||||
render.createSanitizer = createSanitizer
|
|
||||||
}
|
|
||||||
|
|
|
@ -235,12 +235,12 @@ export class Component extends HTMLElement {
|
||||||
unmounted() {}
|
unmounted() {}
|
||||||
updated() {}
|
updated() {}
|
||||||
|
|
||||||
$on(type, callback) {
|
$on(type, callback, options) {
|
||||||
return bind(this, type, callback)
|
return bind(this, type, callback, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
$off(type, callback) {
|
$off(type, callback, options) {
|
||||||
unbind(this, type, callback)
|
unbind(this, type, callback, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
$emit(type, data = {}) {
|
$emit(type, data = {}) {
|
||||||
|
|
|
@ -13,9 +13,9 @@ export function $(selector, container) {
|
||||||
|
|
||||||
export function $$(selector, container) {
|
export function $$(selector, container) {
|
||||||
if (container) {
|
if (container) {
|
||||||
return container.querySelectorsAll(selector)
|
return container.querySelectorAll(selector)
|
||||||
}
|
}
|
||||||
return document.body.querySelectorsAll(selector)
|
return document.body.querySelectorAll(selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const nextTick = (function () {
|
export const nextTick = (function () {
|
||||||
|
|
Loading…
Reference in New Issue