代码优化精简

master 1.11.3
yutent 2023-12-14 12:36:06 +08:00
parent ea6010c782
commit db7098c4f8
3 changed files with 68 additions and 68 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "wkit", "name": "wkit",
"version": "1.11.2", "version": "1.11.3",
"type": "module", "type": "module",
"description": "A library for building fast, lightweight web components.", "description": "A library for building fast, lightweight web components.",
"main": "dist/index.js", "main": "dist/index.js",

View File

@ -6,31 +6,28 @@
import { boolMap, WC_PART, NOTHING } from './constants.js' import { boolMap, WC_PART, NOTHING } from './constants.js'
import { animate, MODES } from './anim.js' import { animate, MODES } from './anim.js'
import { nextTick } from './utils.js' import { nextTick, noop } from './utils.js'
const BIND_ATTR_SUFFIX = '{{$wkit$}}'
const MARKER = `{{^wkit${String(Math.random()).slice(-8)}^}}`
const MARKER_MATCH = '?' + MARKER
const NODE_MARKER = `<${MARKER_MATCH}>`
const boundAttributeSuffix = '$wc$'
const marker = `wc$${String(Math.random()).slice(9)}$`
const markerMatch = '?' + marker
const nodeMarker = `<${markerMatch}>`
const createMarker = (v = '') => document.createComment(v)
const isPrimitive = value => const isPrimitive = value =>
value === null || (typeof value != 'object' && typeof value != 'function') value === null || (typeof value != 'object' && typeof value != 'function')
const isArray = Array.isArray const isArray = Array.isArray
const isIterable = value => const isIterable = value =>
isArray(value) || value ? isArray(value) || typeof value[Symbol.iterator] === 'function' : false
typeof (value === null || value === void 0
? false
: value[Symbol.iterator]) === 'function'
const SPACE_CHAR = `[ \n\f\r]` const SPACE_CHAR = `[ \n\f\r]`
const ATTR_VALUE_CHAR = `[^ \n\f\r"'\`<>=]` const ATTR_VALUE_CHAR = `[^ \n\f\r"'\`<>=]`
const NAME_CHAR = `[^\\s"'>=/]` const NAME_CHAR = `[^\\s"'>=/]`
const textEndRegex = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g const TEXT_END_REGEX = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g
const COMMENT_START = 1 const COMMENT_START = 1
const TAG_NAME = 2 const TAG_NAME = 2
const DYNAMIC_TAG_NAME = 3 const DYNAMIC_TAG_NAME = 3
const commentEndRegex = /-->/g const COMMENT_END_REGEXP = /-->/g
const comment2EndRegex = />/g const COMMENT_END_REGEXP_2 = />/g
const tagEndRegex = new RegExp( const TAG_END_REGEXP = 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'
) )
@ -38,9 +35,9 @@ const ENTIRE_MATCH = 0
const ATTRIBUTE_NAME = 1 const ATTRIBUTE_NAME = 1
const SPACES_AND_EQUALS = 2 const SPACES_AND_EQUALS = 2
const QUOTE_CHAR = 3 const QUOTE_CHAR = 3
const singleQuoteAttrEndRegex = /'/g const SINGLE_QUOTE_REGEXP = /'/g
const doubleQuoteAttrEndRegex = /"/g const DOUBLE_QUOTE_REGEXP = /"/g
const rawTextElement = /^(?:script|style|textarea|title)$/i const RAW_TEXT_ELEM_REGEXP = /^(?:script|style|textarea|title)$/i
const HTML_RESULT = 1 const HTML_RESULT = 1
const SVG_RESULT = 2 const SVG_RESULT = 2
const ATTRIBUTE_PART = 1 const ATTRIBUTE_PART = 1
@ -52,14 +49,12 @@ const COMMENT_PART = 7
const TEMPLATE_CACHE = new Map() const TEMPLATE_CACHE = new Map()
const walker = document.createTreeWalker(document, 129, null, false) const walker = document.createTreeWalker(document, 129, null, false)
function noop() {}
function getTemplateHtml(strings, type) { function getTemplateHtml(strings, type) {
let len = strings.length - 1 let len = strings.length - 1
let attrNames = [] let attrNames = []
let html2 = type === SVG_RESULT ? '<svg>' : '' let html2 = type === SVG_RESULT ? '<svg>' : ''
let rawTextEndRegex let rawTextEndRegex
let regex = textEndRegex let regex = TEXT_END_REGEX
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
let s = strings[i] let s = strings[i]
let attrNameEndIndex = -1 let attrNameEndIndex = -1
@ -73,25 +68,26 @@ function getTemplateHtml(strings, type) {
break break
} }
lastIndex = regex.lastIndex lastIndex = regex.lastIndex
if (regex === textEndRegex) {
if (regex === TEXT_END_REGEX) {
if (match[COMMENT_START] === '!--') { if (match[COMMENT_START] === '!--') {
regex = commentEndRegex regex = COMMENT_END_REGEXP
} else if (match[COMMENT_START] !== void 0) { } else if (match[COMMENT_START] !== void 0) {
regex = comment2EndRegex regex = COMMENT_END_REGEXP_2
} else if (match[TAG_NAME] !== void 0) { } else if (match[TAG_NAME] !== void 0) {
if (rawTextElement.test(match[TAG_NAME])) { if (RAW_TEXT_ELEM_REGEXP.test(match[TAG_NAME])) {
rawTextEndRegex = new RegExp(`</${match[TAG_NAME]}`, 'g') rawTextEndRegex = new RegExp(`</${match[TAG_NAME]}`, 'g')
} }
regex = tagEndRegex regex = TAG_END_REGEXP
} else if (match[DYNAMIC_TAG_NAME] !== void 0) { } else if (match[DYNAMIC_TAG_NAME] !== void 0) {
regex = tagEndRegex regex = TAG_END_REGEXP
} }
} else if (regex === tagEndRegex) { } else if (regex === TAG_END_REGEXP) {
if (match[ENTIRE_MATCH] === '>') { if (match[ENTIRE_MATCH] === '>') {
regex = regex =
rawTextEndRegex !== null && rawTextEndRegex !== void 0 rawTextEndRegex !== null && rawTextEndRegex !== void 0
? rawTextEndRegex ? rawTextEndRegex
: textEndRegex : TEXT_END_REGEX
attrNameEndIndex = -1 attrNameEndIndex = -1
} else if (match[ATTRIBUTE_NAME] === void 0) { } else if (match[ATTRIBUTE_NAME] === void 0) {
attrNameEndIndex = -2 attrNameEndIndex = -2
@ -100,52 +96,65 @@ function getTemplateHtml(strings, type) {
attrName = match[ATTRIBUTE_NAME] attrName = match[ATTRIBUTE_NAME]
regex = regex =
match[QUOTE_CHAR] === void 0 match[QUOTE_CHAR] === void 0
? tagEndRegex ? TAG_END_REGEXP
: match[QUOTE_CHAR] === '"' : match[QUOTE_CHAR] === '"'
? doubleQuoteAttrEndRegex ? DOUBLE_QUOTE_REGEXP
: singleQuoteAttrEndRegex : SINGLE_QUOTE_REGEXP
} }
} else if ( } else if (
regex === doubleQuoteAttrEndRegex || regex === DOUBLE_QUOTE_REGEXP ||
regex === singleQuoteAttrEndRegex regex === SINGLE_QUOTE_REGEXP
) { ) {
regex = tagEndRegex regex = TAG_END_REGEXP
} else if (regex === commentEndRegex || regex === comment2EndRegex) { } else if (
regex = textEndRegex regex === COMMENT_END_REGEXP ||
regex === COMMENT_END_REGEXP_2
) {
regex = TEXT_END_REGEX
} else { } else {
regex = tagEndRegex regex = TAG_END_REGEXP
rawTextEndRegex = void 0 rawTextEndRegex = void 0
} }
} }
let end = let end =
regex === tagEndRegex && strings[i + 1].startsWith('/>') ? ' ' : '' regex === TAG_END_REGEXP && strings[i + 1].startsWith('/>') ? ' ' : ''
html2 += html2 +=
regex === textEndRegex regex === TEXT_END_REGEX
? s + nodeMarker ? s + NODE_MARKER
: attrNameEndIndex >= 0 : attrNameEndIndex >= 0
? (attrNames.push(attrName), ? (attrNames.push(attrName),
s.slice(0, attrNameEndIndex) + s.slice(0, attrNameEndIndex) +
boundAttributeSuffix + BIND_ATTR_SUFFIX +
s.slice(attrNameEndIndex)) + s.slice(attrNameEndIndex)) +
marker + MARKER +
end end
: s + : s +
marker + MARKER +
(attrNameEndIndex === -2 ? (attrNames.push(void 0), i) : end) (attrNameEndIndex === -2 ? (attrNames.push(void 0), i) : end)
} }
let 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 (!isArray(strings) || !strings.hasOwnProperty('raw')) {
throw new Error('invalid html ast') throw new Error('invalid html ast')
} }
return [htmlResult, attrNames] return [htmlResult, attrNames]
} }
function createElement(v = '') {
let el = document.createElement('template')
el.innerHTML = v
return el
}
function createMarker(v = '') {
return document.createComment(v)
}
class Template { class Template {
parts = [] parts = []
constructor({ strings, ['__dom_type__']: type }, options) { constructor({ strings, values, __dom_type__: type }, options) {
let node let node
let nodeIndex = 0 let nodeIndex = 0
let attrNameIndex = 0 let attrNameIndex = 0
@ -153,7 +162,7 @@ class Template {
let parts = this.parts let parts = this.parts
let [html2, attrNames] = getTemplateHtml(strings, type) let [html2, attrNames] = getTemplateHtml(strings, type)
this.el = Template.createElement(html2) this.el = createElement(html2)
walker.currentNode = this.el.content walker.currentNode = this.el.content
@ -170,17 +179,14 @@ class Template {
let attrsToRemove = [] let attrsToRemove = []
for (let name of node.getAttributeNames()) { for (let name of node.getAttributeNames()) {
if ( if (name.endsWith(BIND_ATTR_SUFFIX) || name.startsWith(MARKER)) {
name.endsWith(boundAttributeSuffix) ||
name.startsWith(marker)
) {
let realName = attrNames[attrNameIndex++] let realName = attrNames[attrNameIndex++]
attrsToRemove.push(name) attrsToRemove.push(name)
if (realName !== void 0) { if (realName !== void 0) {
let value = node.getAttribute( let value = node.getAttribute(
realName.toLowerCase() + boundAttributeSuffix realName.toLowerCase() + BIND_ATTR_SUFFIX
) )
let statics = value.split(marker) let statics = value.split(MARKER)
let m = /([#:@])?(.*)/.exec(realName) let m = /([#:@])?(.*)/.exec(realName)
let decorates = [] let decorates = []
@ -216,8 +222,8 @@ class Template {
node.removeAttribute(name) node.removeAttribute(name)
} }
} }
if (rawTextElement.test(node.tagName)) { if (RAW_TEXT_ELEM_REGEXP.test(node.tagName)) {
let strings2 = node.textContent.split(marker) let strings2 = node.textContent.split(MARKER)
let lastIndex = strings2.length - 1 let lastIndex = strings2.length - 1
if (lastIndex > 0) { if (lastIndex > 0) {
node.textContent = '' node.textContent = ''
@ -231,24 +237,19 @@ class Template {
} }
} else if (node.nodeType === 8) { } else if (node.nodeType === 8) {
let data = node.data let data = node.data
if (data === markerMatch) { if (data === MARKER_MATCH) {
parts.push({ type: CHILD_PART, index: nodeIndex }) parts.push({ type: CHILD_PART, index: nodeIndex })
} else { } else {
let i = -1 let i = -1
while ((i = node.data.indexOf(marker, i + 1)) !== -1) { while ((i = node.data.indexOf(MARKER, i + 1)) !== -1) {
parts.push({ type: COMMENT_PART, index: nodeIndex }) parts.push({ type: COMMENT_PART, index: nodeIndex })
i += marker.length - 1 i += MARKER.length - 1
} }
} }
} }
nodeIndex++ nodeIndex++
} }
} }
static createElement(html2) {
let el = document.createElement('template')
el.innerHTML = html2
return el
}
} }
class TemplateInstance { class TemplateInstance {
@ -378,7 +379,7 @@ class ChildPart {
} else if (value !== this.#value) { } else if (value !== this.#value) {
this.#commitText(value) this.#commitText(value)
} }
} else if (value['__dom_type__'] !== void 0) { } else if (value.__dom_type__ !== void 0) {
this.#commitTemplateResult(value) this.#commitTemplateResult(value)
} else if (value.nodeType !== void 0) { } else if (value.nodeType !== void 0) {
this.#commitNode(value) this.#commitNode(value)
@ -415,12 +416,11 @@ class ChildPart {
} }
#commitTemplateResult(result) { #commitTemplateResult(result) {
let { values, ['__dom_type__']: type } = result let { values, __dom_type__: type } = result
let template = let template =
typeof type === 'number' typeof type === 'number'
? this.#getTemplate(result) ? this.#getTemplate(result)
: (type.el === void 0 && (type.el = Template.createElement(type.h)), : (type.el === void 0 && (type.el = createElement(type.h)), type)
type)
if (this.#value?.$template === template) { if (this.#value?.$template === template) {
this.#value.update(values) this.#value.update(values)

View File

@ -4,7 +4,7 @@
* @date 2023/03/07 22:11:30 * @date 2023/03/07 22:11:30
*/ */
function noop() {} export function noop() {}
export function $(selector, container, multi) { export function $(selector, container, multi) {
let fn = multi ? 'querySelectorAll' : 'querySelector' let fn = multi ? 'querySelectorAll' : 'querySelector'