UNPKG

@dooboostore/dom-render

Version:
985 lines 63.9 kB
import { RandomUtils } from "@dooboostore/core"; import { StringUtils } from "@dooboostore/core"; import { EventManager } from "../events/EventManager.js"; import { Range } from "@dooboostore/core"; import { ElementUtils } from "@dooboostore/core-web"; import { DrPre } from "../operators/DrPre.js"; import { Dr } from "../operators/Dr.js"; import { DrIf } from "../operators/DrIf.js"; import { ExecuteState } from "../operators/OperatorExecuter.js"; import { DrThis } from "../operators/DrThis.js"; import { DrForm } from "../operators/DrForm.js"; import { DrInnerText } from "../operators/DrInnerText.js"; import { DrInnerHTML } from "../operators/DrInnerHTML.js"; import { DrFor } from "../operators/DrFor.js"; import { DrForOf } from "../operators/DrForOf.js"; import { DrAppender } from "../operators/DrAppender.js"; import { DrRepeat } from "../operators/DrRepeat.js"; import { DrTargetElement } from "../operators/DrTargetElement.js"; import { DrTargetAttr } from "../operators/DrTargetAttr.js"; import { DrStripElement } from "../operators/DrStripElement.js"; import { DestroyOptionType } from "./DestroyOptionType.js"; import { RawSetType } from "./RawSetType.js"; import { DrThisProperty } from "../operators/DrThisProperty.js"; import { RawSetOperatorType } from "./RawSetOperatorType.js"; import { CssParser, isStyleRule, isAtRule } from "@dooboostore/core"; import { isOnCreateRenderData } from "../lifecycle/OnCreateRenderData.js"; import { isOnCreateRender } from "../lifecycle/OnCreateRender.js"; import { isOnChangeAttrRender } from "../lifecycle/OnChangeAttrRender.js"; import { isOnInitRender } from "../lifecycle/OnInitRender.js"; import { isOnCreatedThisChild } from "../lifecycle/OnCreatedThisChild.js"; import { isOnDestroyRender } from "../lifecycle/OnDestroyRender.js"; import { DrTargetElementIsElement } from "../operators/DrTargetElementIsElement.js"; import { ObjectUtils } from "@dooboostore/core"; import { NodeUtils } from "@dooboostore/core-web"; import { ConvertUtils } from "@dooboostore/core"; import { DomRenderComponentMetaKey } from "./index.js"; const _RawSet = class _RawSet { constructor(uuid, type, point, dataSet, detect) { this.uuid = uuid; this.type = type; this.point = point; this.dataSet = dataSet; this.detect = detect; this.findNearThis = (obj, rawSet = this) => { const path = this.findNearThisPath(rawSet); if (path) { const optionalPath = ObjectUtils.Path.toOptionalChainPath(path); return ObjectUtils.Script.evaluateReturn(optionalPath, obj); } }; this.findParentThis = (obj, rawSet = this) => { const path = this.findParentThisPath(rawSet); if (path) { const optionalPath = ObjectUtils.Path.toOptionalChainPath(path); return ObjectUtils.Script.evaluateReturn(optionalPath, obj); } }; this.findNearThisPath = (rawSet = this) => { const paths = this.findThisPaths(rawSet); return paths[paths.length - 1]; }; this.findParentThisPath = (rawSet = this) => { const paths = this.findThisPaths(rawSet); return paths[paths.length - 2]; }; this.findThisPaths = (rawSet = this) => { const paths = []; const findPath = (rawSet2) => { if (rawSet2 && rawSet2.point) { if (rawSet2.point?.start && "getAttribute" in rawSet2.point.start && rawSet2.point.start.getAttribute("this-path")) { paths.push(rawSet2.point.start.getAttribute("this-path")); } if (rawSet2.point.parentRawSet) findPath(rawSet2.point.parentRawSet); } }; findPath(rawSet); paths.push("this"); return paths.reverse(); }; } get isConnected() { return this.point && this.point.start && this.point.end && this.point.start.isConnected && this.point.end.isConnected; } // 중요 getUsingTriggerVariables(config) { const usingTriggerVariables = /* @__PURE__ */ new Set(); this.dataSet.fragment.childNodes.forEach((cNode, key) => { let script = ""; if (cNode.nodeType === Node.TEXT_NODE) { script = `\`${cNode.textContent ?? ""}\``; const expressionGroups = _RawSet.expressionGroups(script); if (expressionGroups[0].length > 1) { script = expressionGroups[0][1]; } } else if (cNode.nodeType === Node.ELEMENT_NODE) { const element = cNode; const targetAttrNames = (config?.targetAttrs?.map((it) => it.name) ?? []).concat(_RawSet.DR_ATTRIBUTES, _RawSet.DR_DETECT_FILTER_OPTIONNAME, _RawSet.DR_DETECT_IF_OPTIONNAME, _RawSet.DR_DETECT_ATTR_OPTIONNAME); const targetScripts = targetAttrNames.map((it) => element.getAttribute(it)).filter((it) => it).map((it) => `(${it})`); const targetAttrMap = element.getAttribute(EventManager.normalAttrMapAttrName); if (targetAttrMap) { new Map(JSON.parse(targetAttrMap)).forEach((v, k) => { const variablePaths = v.variablePaths; variablePaths.forEach((it) => targetScripts.push(`(${it.inner})`)); }); } script = targetScripts.join(";"); } if (script) { script = script.replace(/#[^#]*#/g, "({})"); EventManager.VARNAMES.forEach((it) => { script = script.replace(RegExp(it.replace("$", "\\$"), "g"), `this.___${it}`); }); Array.from(ObjectUtils.Path.detectPathFromScript(script, { excludeThis: true })).filter((it) => !it.startsWith(`___${EventManager.SCRIPTS_VARNAME}`)).forEach((it) => usingTriggerVariables.add(it)); } }); return usingTriggerVariables; } async render(obj, config) { if (this.dataSet.fragment.childNodes.length === 1 && this.dataSet.fragment.childNodes[0].nodeType === Node.TEXT_NODE) { const textContent = this.dataSet.fragment.childNodes[0].textContent; if (textContent) { const runText = _RawSet.expressionGroups(textContent)[0][1]; const __render = { rawSet: this, scripts: EventManager.setBindProperty(config?.scripts, obj), router: config?.router, range: Range.range, element: this.dataSet.fragment.childNodes[0], attribute: {}, rootObject: obj, scriptUtils: ObjectUtils.Script, nearThis: this.findNearThis(obj), parentThis: this.findParentThis(obj), bindScript: ` /** render **/ const ${EventManager.SCRIPTS_VARNAME} = this.__render.scripts; const ${EventManager.RAWSET_VARNAME} = this.__render.rawSet; const ${EventManager.ELEMENT_VARNAME} = this.__render.element; const ${EventManager.ATTRIBUTE_VARNAME} = this.__render.attribute; const ${EventManager.RANGE_VARNAME} = this.__render.range; const ${EventManager.ROUTER_VARNAME} = this.__render.router; const ${EventManager.NEAR_THIS_VARNAME} = this.__render.nearThis; const ${EventManager.PARENT_THIS_VARNAME} = this.__render.parentThis; const ${EventManager.SCRIPT_UTILS_VARNAME} = this.__render.scriptUtils; const ${EventManager.ROOT_OBJECT_VARNAME} = this.__render.rootObject; ` }; try { const newValue = ObjectUtils.Script.evaluateReturn( { bodyScript: __render.bindScript, returnScript: runText }, Object.assign(obj, { __render }) ); const newValueStr = String(newValue); if (this.lastRenderedValue === newValueStr) { return { raws: [], executedOperators: [] }; } this.lastRenderedValue = newValueStr; } catch (e) { } } } const genNode = config.window.document.importNode(this.dataSet.fragment, true); const raws = []; const onAttrInitCallBacks = []; const onElementInitCallBacks = []; const onThisComponentSetCallBacks = []; const drAttrs = []; const executedOperators = []; for (const cNode of Array.from(genNode.childNodes.values())) { let attribute = {}; if (cNode.nodeType === Node.ELEMENT_NODE) { attribute = ElementUtils.getAttributeToObject(cNode); } const __render = Object.freeze({ rawSet: this, scripts: EventManager.setBindProperty(config?.scripts, obj), router: config?.router, range: Range.range, element: cNode, attribute, rootObject: obj, scriptUtils: ObjectUtils.Script, nearThis: this.findNearThis(obj), parentThis: this.findParentThis(obj), bindScript: ` /** render **/ const ${EventManager.SCRIPTS_VARNAME} = this.__render.scripts; const ${EventManager.RAWSET_VARNAME} = this.__render.rawSet; const ${EventManager.ELEMENT_VARNAME} = this.__render.element; const ${EventManager.ATTRIBUTE_VARNAME} = this.__render.attribute; const ${EventManager.RANGE_VARNAME} = this.__render.range; const ${EventManager.ROUTER_VARNAME} = this.__render.router; const ${EventManager.NEAR_THIS_VARNAME} = this.__render.nearThis; const ${EventManager.PARENT_THIS_VARNAME} = this.__render.parentThis; const ${EventManager.SCRIPT_UTILS_VARNAME} = this.__render.scriptUtils; const ${EventManager.ROOT_OBJECT_VARNAME} = this.__render.rootObject; ` }); const fag = config.window.document.createDocumentFragment(); if (cNode.nodeType === Node.TEXT_NODE && cNode.textContent) { const textContent = cNode.textContent; const runText = _RawSet.expressionGroups(textContent)[0][1]; let newNode; if (textContent?.startsWith("#")) { const r = ObjectUtils.Script.evaluateReturn({ bodyScript: __render.bindScript, returnScript: runText }, Object.assign(obj, { __render })); const template = config.window.document.createElement("template"); template.innerHTML = r; newNode = template.content; } else { const r = ObjectUtils.Script.evaluateReturn({ bodyScript: __render.bindScript, returnScript: runText }, Object.assign(obj, { __render })); newNode = config.window.document.createTextNode(r); } cNode.parentNode?.replaceChild(newNode, cNode); if (this.type === RawSetType.STYLE_TEXT && this.point.parent) { this.point.parent.removeAttribute("completed"); } } else if (cNode.nodeType === Node.ELEMENT_NODE) { const element = cNode; const drAttr = { dr: this.getAttributeAndDelete(element, _RawSet.DR_NAME), drIf: this.getAttributeAndDelete(element, _RawSet.DR_IF_NAME), drFor: this.getAttributeAndDelete(element, _RawSet.DR_FOR_NAME), drForOf: this.getAttributeAndDelete(element, _RawSet.DR_FOR_OF_NAME), drThisProperty: this.getAttributeAndDelete(element, _RawSet.DR_THIS_PROPERTY_NAME), drAppender: this.getAttributeAndDelete(element, _RawSet.DR_APPENDER_NAME), drRepeat: this.getAttributeAndDelete(element, _RawSet.DR_REPEAT_NAME), drThis: this.getAttributeAndDelete(element, _RawSet.DR_THIS_NAME), drForm: this.getAttributeAndDelete(element, _RawSet.DR_FORM_NAME), drPre: this.getAttributeAndDelete(element, _RawSet.DR_PRE_NAME), drInnerHTML: this.getAttributeAndDelete(element, _RawSet.DR_INNERHTML_NAME), drInnerText: this.getAttributeAndDelete(element, _RawSet.DR_INNERTEXT_NAME), drStripElement: this.getAttributeAndDelete(element, _RawSet.DR_STRIP_NAME), drReplaceTargetElementIs: this.getAttributeAndDelete(element, _RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME), drItOption: this.getAttributeAndDelete(element, _RawSet.DR_IT_OPTIONNAME), drIfOption: this.getAttributeAndDelete(element, _RawSet.DR_IF_OPTIONNAME), drVarOption: this.getAttributeAndDelete(element, _RawSet.DR_VAR_OPTIONNAME), drNextOption: this.getAttributeAndDelete(element, _RawSet.DR_NEXT_OPTIONNAME), drAfterOption: this.getAttributeAndDelete(element, _RawSet.DR_AFTER_OPTIONNAME), drBeforeOption: this.getAttributeAndDelete(element, _RawSet.DR_BEFORE_OPTIONNAME), drCompleteOption: this.getAttributeAndDelete(element, _RawSet.DR_COMPLETE_OPTIONNAME), drStripOption: this.getAttributeAndDelete(element, _RawSet.DR_STRIP_OPTIONNAME), drDestroyOption: this.getAttributeAndDelete(element, _RawSet.DR_DESTROY_OPTIONNAME), drKeyOption: this.getAttributeAndDelete(element, _RawSet.DR_KEY_OPTIONNAME), drDetectIfOption: this.getAttribute(element, _RawSet.DR_DETECT_IF_OPTIONNAME), drHasKeysOption: this.getAttribute(element, _RawSet.DR_HAS_KEYS_OPTIONNAME), drItemIndexOffsetOption: this.getAttributeAndDelete(element, _RawSet.DR_ITEM_INDEX_OFFSET_OPTIONNAME), drVariableNameOption: this.getAttributeAndDelete(element, _RawSet.DR_VARIABLE_NAME_OPTIONNAME), drItemVariableNameOption: this.getAttributeAndDelete(element, _RawSet.DR_ITEM_VARIABLE_NAME_OPTIONNAME), drItemIndexVariableNameOption: this.getAttributeAndDelete(element, _RawSet.DR_ITEM_INDEX_VARIABLE_NAME_OPTIONNAME), drItemOffsetIndexVariableNameOption: this.getAttributeAndDelete(element, _RawSet.DR_ITEM_OFFSET_INDEX_VARIABLE_NAME_OPTIONNAME) }; drAttrs.push(drAttr); const operators = [ new DrPre(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_PRE_NAME, attr: drAttr.drPre, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drPre }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new Dr(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_NAME, attr: drAttr.dr, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.dr }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), // new Dr(this, __render, {raws, fag}, {element, attrName: EventManager.onRenderedInitAttrName, attr: drAttr.dr, attrs: drAttr}, {config, obj, operatorAround: config.operatorAround?.dr}, {onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks}), new DrIf(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_IF_NAME, attr: drAttr.drIf, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drIf }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrStripElement(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_STRIP_NAME, attr: drAttr.drStripElement, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drThis }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrThis(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_THIS_NAME, attr: drAttr.drThis, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drThis }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrForm(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_FOR_NAME, attr: drAttr.drForm, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drForm }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrInnerText(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_INNERTEXT_NAME, attr: drAttr.drInnerText, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drInnerText }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrInnerHTML(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_INNERHTML_NAME, attr: drAttr.drInnerHTML, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drInnerHTML }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrFor(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_FOR_NAME, attr: drAttr.drFor, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drFor }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrForOf(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_FOR_OF_NAME, attr: drAttr.drForOf, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drForOf }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrThisProperty(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_THIS_PROPERTY_NAME, attr: drAttr.drThisProperty, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drThisProperty }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrAppender(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_APPENDER_NAME, attr: drAttr.drAppender, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drAppender }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrRepeat(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_REPEAT_NAME, attr: drAttr.drRepeat, attrs: drAttr }, { config, obj, operatorAround: config.operatorAround?.drRepeat }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrTargetElementIsElement(this, __render, { raws, fag }, { element, attrName: _RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME, attr: drAttr.drReplaceTargetElementIs, attrs: drAttr }, { config, obj }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrTargetElement(this, __render, { raws, fag }, { element, attrs: drAttr }, { config, obj }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrTargetAttr(this, __render, { raws, fag }, { element, attrs: drAttr }, { config, obj }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }) ]; for (const operator of operators) { const state = await operator.start(); if (state === ExecuteState.EXECUTE) { executedOperators.push(operator); break; } else if (state === ExecuteState.STOP) { return { raws, executedOperators }; } } } } this.point.childrenRawSets = raws; raws.forEach((it) => { it.point.parentRawSet = this; }); const childrenNodes = Array.from(genNode.childNodes); this.applyEvent(obj, genNode, config); this.replaceBody(genNode); this.onRenderedEvent(obj, childrenNodes, config); drAttrs.forEach((it) => { if (it.drCompleteOption) { const render = Object.freeze({ rawSet: this, fag: genNode, scripts: EventManager.setBindProperty(config?.scripts, obj) }); ObjectUtils.Script.evaluate( ` const ${EventManager.FAG_VARNAME} = this.__render.fag; const ${EventManager.SCRIPTS_VARNAME} = this.__render.scripts; const ${EventManager.RAWSET_VARNAME} = this.__render.rawSet; ${it.drCompleteOption}`, Object.assign(obj, { __render: render }) ); } }); for (const it of onThisComponentSetCallBacks) { if (isOnInitRender(it.obj)) { await it.obj?.onInitRender?.({}, this); } } for (const it of onElementInitCallBacks) { if (isOnInitRender(this.dataSet.render?.currentThis)) { await this.dataSet.render.currentThis.onInitRender({}, this); } config?.onElementInit?.(it.name, obj, this, it.targetElement); } for (const it of onAttrInitCallBacks) { config?.onAttrInit?.(it.attrName, it.attrValue, obj, this); } if (obj[DomRenderComponentMetaKey.DOMRENDER_COMPONENTS_KEY]) { Object.entries(obj[DomRenderComponentMetaKey.DOMRENDER_COMPONENTS_KEY]).forEach(([key, value]) => { const rawSet = value.__rawSet; const drAttrs2 = rawSet?.dataSet.render?.attribute; if (rawSet && !rawSet.isConnected) { const destroyOptions = drAttrs2?.drDestroyOption?.split(",") ?? []; _RawSet.destroy(obj[DomRenderComponentMetaKey.DOMRENDER_COMPONENTS_KEY][key], { rawSet }, config, destroyOptions); delete obj[DomRenderComponentMetaKey.DOMRENDER_COMPONENTS_KEY][key]; } }); } console.groupEnd(); return { raws, executedOperators }; } // 중요 스타일 적용 부분 static generateRuleSelector(start, end, sit) { const selectorText = `:is(${start} ~ *:not(${start} ~ ${end} ~ *))`; if (sit.startsWith("## ")) { return sit.replace(/^## /, ""); } else if (sit.startsWith(".")) { return `${selectorText}${sit}, ${selectorText} ${sit}`; } else if (sit.includes("::")) { const reg = sit.match(/(.*)::(.*)$/); const first = reg?.[1]; const extracted = reg?.[2]; const divText = `${start} ~ ${first}:not(${start} ~ ${end} ~ *)`; return `${selectorText} ${first}, ${divText}::${extracted}`; } else { const divText = `${start} ~ ${sit}:not(${start} ~ ${end} ~ *)`; return `${selectorText} ${sit}, ${divText}`; } } static generateStyleTransform(styleBody, componentKey, styleTagWrap = true) { if (Array.isArray(styleBody)) { styleBody = styleBody.join("\n"); } styleBody = styleBody.replaceAll("#uuid#", componentKey); const { cleanedCss, importRules } = _RawSet.extractCssImports(styleBody); styleBody = cleanedCss; const start = `#${componentKey}-start`; const end = `#${componentKey}-end`; const cssParser = new CssParser(styleBody); const processRule = (rule) => { if (isStyleRule(rule)) { const isRoot = rule.selector.includes(":root"); if (!isRoot) { const selectors = rule.selector.split(",").map((s) => s.trim()); const transformedSelectors = selectors.map((selector) => this.generateRuleSelector(start, end, selector)); rule.selector = transformedSelectors.join(", "); } } else if (isAtRule(rule)) { if (rule.name === "media") { const hasRoot = rule.children.some((childRule) => isStyleRule(childRule) && childRule.selector.includes(":root")); if (!hasRoot) { rule.children.forEach((childRule) => { if (isStyleRule(childRule)) { const selectors = childRule.selector.split(",").map((s) => s.trim()); const transformedSelectors = selectors.map((selector) => this.generateRuleSelector(start, end, selector)); childRule.selector = transformedSelectors.join(", "); } }); } } } }; cssParser.rules.forEach(processRule); let after = cssParser.stringify(); after = after.replaceAll("/*$", "${"); after = after.replaceAll("$*/", "}$"); if (importRules.length) { after = `${importRules.join("\n")} ${after}`; } if (styleTagWrap) { styleBody = `<style id='${componentKey}-style' domstyle>${after}</style>`; } return styleBody; } static extractCssImports(styleBody) { const importRules = []; let result = ""; let i = 0; while (i < styleBody.length) { const importIndex = styleBody.indexOf("@import", i); if (importIndex === -1) { result += styleBody.slice(i); break; } result += styleBody.slice(i, importIndex); let j = importIndex + "@import".length; let inSingleQuote = false; let inDoubleQuote = false; let parenDepth = 0; while (j < styleBody.length) { const ch = styleBody[j]; if (ch === "\\") { j += 2; continue; } if (!inDoubleQuote && ch === "'") { inSingleQuote = !inSingleQuote; } else if (!inSingleQuote && ch === '"') { inDoubleQuote = !inDoubleQuote; } else if (!inSingleQuote && !inDoubleQuote) { if (ch === "(") { parenDepth += 1; } else if (ch === ")" && parenDepth > 0) { parenDepth -= 1; } else if (ch === ";" && parenDepth === 0) { j += 1; break; } } j += 1; } const importRule = styleBody.slice(importIndex, j).trim(); if (importRule) { importRules.push(importRule); } i = j; } return { cleanedCss: result, importRules }; } applyEvent(obj, fragment = this.dataSet.fragment, config) { this.dataSet.config.eventManager.applyEvent(obj, this.dataSet.config.eventManager.findAttrElements(fragment, config), config); } onRenderedEvent(obj, nodes, config) { this.dataSet.config.eventManager.onRenderedEvent(obj, nodes, config); } getAttribute(element, attr) { const data = element.getAttribute(attr); return data; } getAttributeAndDelete(element, attr) { const data = element.getAttribute(attr); element.removeAttribute(attr); return data; } getDrAppendAttributeAndDelete(element, obj) { let data = element.getAttribute(_RawSet.DR_APPENDER_NAME); if (data && !/\[.+\]/g.test(data)) { const currentIndex = ObjectUtils.Script.evaluateReturn(`${ObjectUtils.Path.toOptionalChainPath(data)}?.length -1`, obj); data = `${data}[${currentIndex}]`; element.setAttribute(_RawSet.DR_APPENDER_NAME, data); } element.removeAttribute(_RawSet.DR_APPENDER_NAME); return data; } replaceBody(genNode) { this.childAllRemove(); this.point.start.parentNode?.insertBefore(genNode, this.point.start.nextSibling); } // 중요 important static checkPointCreates(element, obj, config) { const NodeFilter2 = config.window.NodeFilter; const Node2 = config.window.Node; const processedNodes = /* @__PURE__ */ new Set(); const findNodes = NodeUtils.findNodes(element, (node) => { if (node.nodeType === Node2.TEXT_NODE) { const between = _RawSet.expressionGroups(StringUtils.deleteEnter(node.data ?? "")); const r2 = between?.length > 0 ? NodeUtils.FindNodesFilterResult.MATCH_AND_SKIP_CHILDREN : NodeUtils.FindNodesFilterResult.NO_MATCH_AND_SKIP_CHILDREN; return r2; } else if (node.nodeType === Node2.ELEMENT_NODE) { const element2 = node; if (element2.hasAttribute(_RawSet.DR_PRE_NAME)) { let r3 = NodeUtils.FindNodesFilterResult.NO_MATCH_AND_SKIP_CHILDREN; return r3; } if (element2.hasAttribute(EventManager.attrAttrName)) { const script = element2.getAttribute(EventManager.attrAttrName) ?? ""; const keyValuePairs = Array.from(script.matchAll(/['"]?([\w-_]+)['"]?:\s*([^,}]+)/g)).map((match) => ({ key: match[1], value: match[2] })); (keyValuePairs ?? []).forEach((it) => { element2.setAttribute(it.key, "${" + it.value + "}$"); }); } const targetElementIs = element2.getAttribute(_RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME); const targetElementNames = config.targetElements?.map((it) => it.name.toLowerCase()) ?? []; targetElementNames.push(..._RawSet.DR_ELEMENTS); const isElement = targetElementNames.includes(element2.tagName.toLowerCase()) || targetElementNames.includes(targetElementIs?.toLowerCase()); const targetAttrNames = (config.targetAttrs?.map((it) => it.name) ?? []).concat([..._RawSet.DR_ATTRIBUTES]); const normalAttrs = /* @__PURE__ */ new Map(); const linkVariables = /* @__PURE__ */ new Map(); const linkNames = EventManager.linkAttrs.map((it) => it.name); const isAttr = element2.getAttributeNames().filter((it) => !EventManager.noDetectAttr.includes(it)).filter((it) => { const value = element2.getAttribute(it)?.trim(); if (value && linkNames.includes(it)) { linkVariables.set(it, value); } else if (value && _RawSet.isExpression(value)) { const variablePaths = _RawSet.expressionGroups(value).map((it2) => ({ origin: it2[0].trim(), inner: it2[1].trim() })); const isStringTemplate = variablePaths.length > 1 || variablePaths[0] && variablePaths[0].origin !== value; let targetScript = value; variablePaths.forEach((it2) => { let r3 = it2.inner.replace(/#[^#]*#/g, "({})"); r3 = ObjectUtils.Path.toOptionalChainPath(r3); targetScript = targetScript.replaceAll(it2.origin, `\${${r3}}`); }); const cval = ObjectUtils.Script.evaluateReturn("`" + targetScript + "`", Object.assign(obj)); if (cval === null) { element2.removeAttribute(it); } else { element2.setAttribute(it, cval); } normalAttrs.set(it, { originalAttrValue: value, variablePaths, isStringTemplate }); } const isTargetAttr = targetAttrNames.includes(it.toLowerCase()); return isTargetAttr; }).length > 0; if (linkVariables.size) { element2.setAttribute(EventManager.linkTargetMapAttrName, JSON.stringify(Array.from(linkVariables.entries()))); } if (normalAttrs.size) { element2.setAttribute(EventManager.normalAttrMapAttrName, JSON.stringify(Array.from(normalAttrs.entries()))); } const r2 = isAttr || isElement ? NodeUtils.FindNodesFilterResult.MATCH_AND_SKIP_CHILDREN : NodeUtils.FindNodesFilterResult.NO_MATCH_AND_CONTINUE; return r2; } const r = NodeUtils.FindNodesFilterResult.NO_MATCH_AND_CONTINUE; return r; }); const pars = []; let currentNode; const name = RandomUtils.uuid(); for (const currentNode2 of findNodes) { processedNodes.add(currentNode2); if (currentNode2.nodeType === Node2.TEXT_NODE) { const text = currentNode2.textContent ?? ""; const template = config.window.document?.createElement("template"); if (!template) break; const groups = _RawSet.expressionGroups(text); const map = groups.map((it) => ({ uuid: `${RandomUtils.alphabet(40)}_${obj?.constructor?.name}`, content: it[0], regexArr: it })); let lasterIndex = 0; for (let i = 0; i < map.length; i++) { const it = map[i]; const regexArr = it.regexArr; const preparedText = regexArr.input.substring(lasterIndex, regexArr.index); let type; if (currentNode2.parentNode && currentNode2.parentNode.nodeName.toUpperCase() === "STYLE") { type = RawSetType.STYLE_TEXT; } else { type = RawSetType.TEXT; } const node = config.window.document.createTextNode(preparedText); const startEndPoint = _RawSet.createStartEndPoint({ id: it.uuid, type }, config); template.content.append(node); template.content.append(startEndPoint.start); template.content.append(startEndPoint.end); const fragment = config.window.document.createDocumentFragment(); fragment.append(config.window.document.createTextNode(it.content)); pars.push( new _RawSet( it.uuid, type, { start: startEndPoint.start, node: currentNode2, end: startEndPoint.end, parent: currentNode2.parentNode // thisVariableName: thisVariableName }, { fragment, config } ) ); lasterIndex = regexArr.index + it.content.length; } template.content.append(config.window.document.createTextNode(text.substring(lasterIndex, text.length))); const p = currentNode2?.parentNode; p?.replaceChild(template.content, currentNode2); } else if (currentNode2.nodeType === Node2.ELEMENT_NODE) { const uuid = `${RandomUtils.alphabet(40)}`; const element2 = currentNode2; const fragment = config.window.document.createDocumentFragment(); const elementType = RawSetType.TARGET_ELEMENT; const startEndPoint = _RawSet.createStartEndPoint({ node: element2, id: uuid, type: elementType }, config); const targetElementIs = element2.getAttribute(_RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME); const targetElementNames = config.targetElements?.map((it) => it.name.toLowerCase()) ?? []; targetElementNames.push(..._RawSet.DR_ELEMENTS); const isElement = targetElementNames.includes(element2.tagName.toLowerCase()) || targetElementNames.includes(targetElementIs?.toLowerCase()); const targetAttrNames = (config.targetAttrs?.map((it) => it.name) ?? []).concat(_RawSet.DR_ATTRIBUTES); const isAttr = element2.getAttributeNames().filter((it) => targetAttrNames.includes(it.toLowerCase())).length > 0; currentNode2?.parentNode?.insertBefore(startEndPoint.start, currentNode2); currentNode2?.parentNode?.insertBefore(startEndPoint.end, currentNode2.nextSibling); fragment.append(currentNode2); const rawSet = new _RawSet( uuid, isElement ? elementType : isAttr ? RawSetType.TARGET_ATTR : RawSetType.UNKOWN, { start: startEndPoint.start, node: currentNode2, end: startEndPoint.end, parent: currentNode2.parentNode // thisVariableName: thisVariableName }, { config, fragment } ); pars.push(rawSet); } } const util = ElementUtils; return pars; } static createStartEndPoint(data, config) { if (data.type === RawSetType.TARGET_ELEMENT && data.node) { const element = data.node; const start = config.window.document.createElement("meta"); const end = config.window.document.createElement("meta"); start.setAttribute("id", `${data.id}-start`); start.setAttribute("dr-start-point", ""); const keys = element.getAttribute(_RawSet.DR_KEY_OPTIONNAME); const thisPropertyType = element.getAttribute(_RawSet.DR_THIS_PROPERTY_NAME); if (thisPropertyType) { start.setAttribute("type", RawSetOperatorType.DR_THIS_PROPERTY); } if (keys) { element.removeAttribute(_RawSet.DR_KEY_OPTIONNAME); start.setAttribute(_RawSet.DR_KEY_OPTIONNAME, keys); } end.setAttribute("id", `${data.id}-end`); end.setAttribute("dr-end-point", ""); return { start, end }; } else if (data.type === RawSetType.STYLE_TEXT) { return { start: config.window.document.createTextNode(`/*start text ${data.id}*/`), end: config.window.document.createTextNode(`/*end text ${data.id}*/`) }; } else { return { start: config.window.document.createComment(`start text ${data.id}`), end: config.window.document.createComment(`end text ${data.id}`) }; } } remove() { this.childAllRemove(); this.point.end.remove(); this.point.start.remove(); } childAllRemove() { let next = this.point.start.nextSibling; while (next) { if (next === this.point.end) { break; } next.remove(); next = this.point.start.nextSibling; } } childs(stopNext) { const childs = []; let next = this.point.start.nextSibling; while (next && next !== this.point.end) { if (stopNext?.(next)) { return; } childs.push(next); next = next.nextSibling; } return childs; } getHasRawSet(key) { let rawSet; this.childs((node) => { const drKey = node.getAttribute?.(_RawSet.DR_KEY_OPTIONNAME); if (drKey && drKey === key) { rawSet = node.rawSet; return true; } return false; }); return rawSet; } static drItOtherEncoding(element, postFix) { const random = RandomUtils.uuid() + postFix; const regex = /#it#/g; element.querySelectorAll(`[${_RawSet.DR_IT_OPTIONNAME}], [${_RawSet.DR_FOR_OF_NAME}], [${_RawSet.DR_REPEAT_NAME}], [${_RawSet.DR_APPENDER_NAME}]`).forEach((it) => { it.innerHTML = it.innerHTML.replace(regex, random); }); return random; } static drItOtherDecoding(element, random) { element.querySelectorAll(`[${_RawSet.DR_IT_OPTIONNAME}], [${_RawSet.DR_FOR_OF_NAME}], [${_RawSet.DR_REPEAT_NAME}], [${_RawSet.DR_APPENDER_NAME}]`).forEach((it) => { it.innerHTML = it.innerHTML.replace(RegExp(random, "g"), "#it#"); }); } static drVarDecoding(element, vars) { element.querySelectorAll(`[${_RawSet.DR_THIS_NAME}]`).forEach((it) => { vars.filter((vit) => vit.value && vit.name).forEach((vit) => { it.innerHTML = it.innerHTML.replace(RegExp(vit.random, "g"), vit.value); }); }); } static replaceInnerHTML(element, config) { const innerHTML = element.innerHTML; const tobe = config.toBe = config.toBe ?? RandomUtils.uuid(); if (config.asIs instanceof RegExp) { element.innerHTML = innerHTML.replace(config.asIs, config.toBe); } else { element.innerHTML = innerHTML.replaceAll(config.asIs, config.toBe); } return tobe; } static drThisEncoding(element, drThis, config) { const thisRandom = config.toBe = config?.toBe ?? RandomUtils.uuid(); element.querySelectorAll(`[${_RawSet.DR_PRE_NAME}]`).forEach((it) => { it.innerHTML = it.innerHTML.replace(config.asIs, thisRandom); }); element.querySelectorAll(`[${_RawSet.DR_THIS_NAME}]`).forEach((it) => { let message2 = it.innerHTML; StringUtils.regexExec(config.asIs, message2).reverse().forEach((it2) => { message2 = message2.substr(0, it2.index) + message2.substr(it2.index).replace(it2[0], `${it2[1] ?? ""}${drThis}`); }); it.innerHTML = message2; }); let message = element.innerHTML; StringUtils.regexExec(config.asIs, message).reverse().forEach((it) => { message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ""}${drThis}`); }); element.innerHTML = message; return thisRandom; } static drThisBindEncoding(element, variable, config) { element.querySelectorAll(`[${_RawSet.DR_THIS_NAME}]`).forEach((eIt) => { let message = eIt.innerHTML; StringUtils.regexExec(variable, message).reverse().forEach((it) => { message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ""}${eIt.getAttribute(_RawSet.DR_THIS_NAME)}`); }); eIt.innerHTML = message; }); const targetElements = config.config.targetElements ?? []; const targetElementNames = targetElements.map((it) => it.name.replaceAll(".", "\\.").replaceAll(":", "\\:")).join(","); const thisRandom = RandomUtils.uuid(); element.querySelectorAll(targetElementNames).forEach((it) => { it.innerHTML = it.innerHTML.replace(variable, thisRandom); }); element.querySelectorAll(`[${_RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME}]`).forEach((it) => { it.innerHTML = it.innerHTML.replace(variable, thisRandom); }); if (config.otherReplaceVariablePath) { let message = element.innerHTML; StringUtils.regexExec(variable, message).reverse().forEach((it) => { message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ""}${config.otherReplaceVariablePath}`); }); element.innerHTML = message; } return thisRandom; } static drThisBindDecoding(element, config) { const targetElements = config.config.targetElements ?? []; const targetElementNames = targetElements.map((it) => it.name.replaceAll(".", "\\.").replaceAll(":", "\\:")).join(","); element.querySelectorAll(targetElementNames).forEach((it) => { it.innerHTML = it.innerHTML.replace(RegExp(config.asIs, "g"), config.toBe); }); element.querySelectorAll(`[${_RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME}]`).forEach((it) => { it.innerHTML = it.innerHTML.replace(RegExp(config.asIs, "g"), config.toBe); }); } static drThisDecoding(element, config) { element.querySelectorAll(`[${_RawSet.DR_PRE_NAME}]`).forEach((it) => { it.innerHTML = it.innerHTML.replace(RegExp(config.asIs, "g"), config.toBe); }); element.querySelectorAll(`[${_RawSet.DR_THIS_NAME}]`).forEach((it) => { it.innerHTML = it.innerHTML.replace(RegExp(config.asIs, "g"), config.toBe); }); } static drFormOtherMoveAttr(element, as, to, config) { element.querySelectorAll(`[${_RawSet.DR_FORM_NAME}]`).forEach((subElement) => { const nodeIterator = config.window.document?.createNodeIterator(subElement, NodeFilter.SHOW_ELEMENT, { acceptNode(node2) { if (node2.nodeType === Node.ELEMENT_NODE) { const element2 = node2; return element2.hasAttribute(as) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; } else { return NodeFilter.FILTER_REJECT; } } }); let node; while (node = nodeIterator?.nextNode()) { const element2 = node; element2.setAttribute(to, element2.getAttribute(as) ?? ""); element2.removeAttribute(as); } }); } static drVarEncoding(element, drVarOption) { const vars = (drVarOption?.split(",") ?? []).map((it) => { const s = it.trim().split("="); const name = s[0]?.trim(); const value = s[1]?.trim(); return { name, value, // regex: RegExp('(?<!(dr-|\\.))var\\.' + s[0] + '(?=.?)', 'g'), regex: RegExp("\\$var\\." + name + "(?=.?)", "g"), random: RandomUtils.uuid() }; }); element.querySelectorAll(`[${_RawSet.DR_VAR_OPTIONNAME}]`).forEach((it) => { vars.filter((vit) => vit.value && vit.name).forEach((vit) => { it.innerHTML = it.innerHTML.replace(vit.regex, vit.random); }); }); vars.filter((vit) => vit.value && vit.name).forEach((vit) => { element.innerHTML = element.innerHTML.replace(vit.regex, vit.value); }); return vars; } static async drThisCreate(rawSet, element, drThis, drVarOption, drStripOption, obj, config, set) { var _a; const fag = config.window.document?.createDocumentFragment(); if (!fag) { return; } const targetElement = element.cloneNode(true); let targetObj = obj; if (set) { targetObj = set.obj; const templateStringSet = await _RawSet.fetchTemplateStyle(set, targetObj); set.setTemplateStyle(templateStringSet); const style = _RawSet.generateStyleTransform(templateStringSet.styles ?? [], rawSet.uuid, true); targetElement.innerHTML = style + (templateStringSet.template ?? ""); } else { targetObj = ObjectUtils.Script.evaluateReturn(ObjectUtils.Path.toOptionalChainPath(drThis), obj); } const componentKey = rawSet.uuid; const renderScript = ` /*drThisCreate*/ // console.log('-----', this.__render); var ${EventManager.RENDER_VARNAME} = this.__render; var ${EventManager.RAWSET_VARNAME} = this.__render.rawSet; var ${EventManager.COMPONENT_VARNAME} = this.__render.component; var ${EventManager.ELEMENT_VARNAME} = this.__render.element; var ${EventManager.ROUTER_VARNAME} = this.__render.router; var ${EventManager.INNER_HTML_VARNAME} = this.__render.innerHTML; var ${EventManager.ATTRIBUTE_VARNAME} = this.__render.attribute; var ${EventManager.PARENT_THIS_PATH_VARNAME} = this.__render.parentThisPath; var ${EventManager.CURRENT_THIS_VARNAME} = this.__render.currentThis; var ${EventManager.CURRENT_THIS_PATH_VARNAME} = this.__render.currentThisPath; var ${EventManager.PARENT_THIS_VARNAME} = this.__render.parentThis; var ${EventManager.NEAR_THIS_PATH_VARNAME} = this.__render.nearThisPath; var ${EventManager.NEAR_THIS_VARNAME} = this.__render.nearThis; var ${EventManager.CREATOR_META_DATA_VARNAME} = this.__render.creatorMetaData; `; const parentThisPath = rawSet.findParentThisPath(); const parentThis = rawSet.findParentThis(obj); const nearThisPath = rawSet.findNearThisPath(); const nearThis = rawSet.findNearThis(obj); let render = { renderScript, element, getElement: () => config.window.document.querySelector(`[class*="${rawSet.uuid}"]`), innerHTML: element.innerHTML, // attribute: ObjectUtils.toDeleteKey(attribute, [...Object.values(RawSet.drAttrsOriginName), ...Object.values(EventManager.VARNAMES)]), rawSet, router: config.router, componentKey, currentThis: targetObj, currentThisPath: drThis, parentThisPath, parentThis, nearThisPath, nearThis, scripts: EventManager.setBindProperty(config.scripts ?? {}, obj) }; render.attribute = _RawSet.getAttributeObject(element, { script: renderScript, obj, renderData: render }); render = Object.freeze(render); const onCreateDataScript = `{rootParent: this, render: this.__render}`; const onCreateDataParam = ObjectUtils.Script.evaluateReturn(onCreateDataScript, Object.assign(obj, { __render: render })); if (isOnCreateRenderData(targetObj)) { targetObj?.onCreateRenderData(onCreateDataParam); } if (onCreateDataParam?.render?.parentThis && isOnCreatedThisChild(onCreateDataParam?.render?.parentThis)) { onCreateDataParam.render.parentThis.onCreatedThisChild(targetObj, onCreateDataParam); } const onCreate = element.getAttribute(_RawSet.DR_ON_CREATE_ARGUMENTS_OPTIONNAME); let createParam = []; if (onCreate) { createParam = ObjectUtils.Script.evaluateReturn({ bodyScript: renderScript, returnScript: ObjectUtils.Path.toOptionalChainPath(onCreate) }, obj); if (!Array.isArray(createParam)) { createParam = [createParam]; } } if (isOnCreateRender(targetObj)) { targetObj.onCreateRender(...createParam); } const targetAttrObject = _RawSet.getAttributeObject(element, { script: renderScript, obj, renderData: render }); if (targetAttrObject) { (_a = rawSet.dataSet).render ?? (_a.render = {}); rawSet.dataSet.render.attribute = targetAttrObject; Object.entries(targetAttrObject).forEach(([key, cval], index) => { if (isOnChangeAttrRender(targetObj)) { targetObj.onChangeAttrRender(key, cval, { rawSet }); } }); } const oninit = element.getAttribute(_RawSet.DR_ON_CREATED_CALLBACK_OPTIONNAME); if (oninit) { const script = `${renderScript} ${oninit} `; ObjectUtils.Script.evaluate(script, Object.assign(obj, { __render: render })); } targetElement.querySelectorAll(EventManager.attrNames.map((it) => `[${it}]`).join(",")).forEach((it) => { it.setAttribute(EventManager.ownerVariablePathAttrName, "this"); }); rawSet.point.innerHTML = element.innerHTML; const innerText = element.textContent?.trim() ?? ""; const escapedInnerHTML = ConvertUtils.escapeHTML(element.innerHTML); const innerHTMLName = targetElement.getAttribute(_RawSet.DR_INNER_HTML_NAME_OPTIONNAME) ?? "innerHTML"; const innerTEXTName = targetElement.getAttribute(_RawSet.DR_INNER_TEXT_NAME_OPTIONNAME) ?? "innerTEXT"; const innerHTMLEscapedName = targetElement.getAttribute(_RawSet.DR_INNER_HTML_ESCAPED_NAME_OPTIONNAME) ?? "innerHTMLEscaped"; const templateReplacements = []; if (innerHTMLName) { templateReplacements.push({ regex: new RegExp(`#${innerHTMLName}#`, "g"), callback: () => element.innerHTML }); } if (innerTEXTName) { templateReplacements.push({ regex: new RegExp(`#${innerTEXTName}#`, "g"), callback: () => innerText }); } if (innerHTMLEscapedName) { templateReplacements.push({ regex: new RegExp(`#${innerHTMLEscapedName}#`, "g"), callback: () => escapedInnerHTML }); } if (templateReplacements.length > 0) { targetElement.innerHTML = StringUtils.replaceSequentially(targetElement.innerHTML, templateReplacements); } const componentName = targetElement.getAttribute(_RawSet.DR_VARIABLE_NAME_OPTIONNAME) ?? "component"; const optionThisName = targetElement.getAttribute(_RawSet.DR_THIS_NAME_OPTIONNAME); targetElement.getAttributeNames().forEach((it) => targetElement.setAttribute(it, targetElement.getAttribute(it).replace(/#this#/g, drThis))); const thisRandom = this.drThisEncoding(targetElement, drThis, { asIs: /@this@/g }); targetElement.innerHTML = targetElement.innerHTML.replaceAll(`#${componentName}#`, drThis); if (optionThisName) { targetElement.innerHTML = targetElement.innerHTML.replaceAll(`@${optionThisName}@`, drThis); } const nearThisRandom = this.drThisBindEncoding(targetElement, /@nearThis@/g, { config, otherReplaceVariablePath: rawSet.findNearThisPath() }); const parentThisRandom = this.drThisBindEncoding(targetElement, /@parentThis@/g, { config, otherReplaceVariablePath: rawSet.findParentThisPath() }); const vars = this.drVarEncoding(targetElement, drVarOption); this.drVarDecoding(targetElement, vars); this.drThisDecoding(targetElement, { asIs: thisRandom, toBe: "@this@" }); this.drThisBindDecoding(targetElement, { config, asIs: nearThisRandom, toBe: "@nearThis@" }); this.drThisBindDecoding(targetElement, { config, asIs: parentThisRandom, toBe: "@parentThis@" }); if (drStripOption && (drStripOption === true || drStripOption === "true")) { Array.from(targetElement.childNodes).forEach((it) => fag.append(it)); } els