UNPKG

@dooboostore/dom-render

Version:
766 lines 90 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { RandomUtils } from '@dooboostore/core/random/RandomUtils'; import { StringUtils } from '@dooboostore/core/string/StringUtils'; import { ScriptUtils } from '@dooboostore/core-web/script/ScriptUtils'; import { EventManager, eventManager } from '../events/EventManager'; import { Range } from '../iterators/Range'; import { DomUtils } from '@dooboostore/core-web/dom/DomUtils'; import { DrPre } from '../operators/DrPre'; import { Dr } from '../operators/Dr'; import { DrIf } from '../operators/DrIf'; import { ExecuteState } from '../operators/OperatorExecuter'; import { DrThis } from '../operators/DrThis'; import { DrForm } from '../operators/DrForm'; import { DrInnerText } from '../operators/DrInnerText'; import { DrInnerHTML } from '../operators/DrInnerHTML'; import { DrFor } from '../operators/DrFor'; import { DrForOf } from '../operators/DrForOf'; import { DrAppender } from '../operators/DrAppender'; import { DrRepeat } from '../operators/DrRepeat'; import { DrTargetElement } from '../operators/DrTargetElement'; import { DrTargetAttr } from '../operators/DrTargetAttr'; import { DrStripElement } from '../operators/DrStripElement'; import { DestroyOptionType } from './DestroyOptionType'; import { RawSetType } from './RawSetType'; import { DrThisProperty } from '../operators/DrThisProperty'; import { RawSetOperatorType } from './RawSetOperatorType'; import cssParse from '../css/parse'; import cssStringify from '../css/stringify'; import { isOnCreateRenderData } from '../lifecycle/OnCreateRenderData'; import { isOnCreateRender } from '../lifecycle/OnCreateRender'; import { isOnChangeAttrRender } from '../lifecycle/OnChangeAttrRender'; import { isOnInitRender } from '../lifecycle/OnInitRender'; import { isOnCreatedThisChild } from '../lifecycle/OnCreatedThisChild'; import { isOnDestroyRender } from '../lifecycle/OnDestroyRender'; import { DrTargetElementIsElement } from '../operators/DrTargetElementIsElement'; export 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) return ScriptUtils.evalReturn(path, obj); }; this.findParentThis = (obj, rawSet = this) => { const path = this.findParentThisPath(rawSet); if (path) return ScriptUtils.evalReturn(path, 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 = (rawSet) => { if (rawSet && rawSet.point) { // jsDom에서 instranceof HTMLMetaElement가 안먹히는것같아? 간혈적으로? if ('getAttribute' in rawSet.point.start && rawSet.point.start.getAttribute('this-path')) { paths.push(rawSet.point.start.getAttribute('this-path')); } if (rawSet.point.parentRawSet) findPath(rawSet.point.parentRawSet); } }; findPath(rawSet); paths.push('this'); return paths.reverse(); }; // point.start.rawSet = this; // console.log('rawset constructor->', (this.point.node as Element).getAttributeNames()); } get isConnected() { // console.log('isConnect???', this, this.point.start.isConnected, this.point.end.isConnected); return this.point.start.isConnected && this.point.end.isConnected; } // 중요 getUsingTriggerVariables(config) { const usingTriggerVariables = new Set(); // console.log('------data', this.dataSet) this.dataSet.fragment.childNodes.forEach((cNode, key) => { var _a, _b, _c; // console.log('-----aaaa-data', cNode, key) let script = ''; if (cNode.nodeType === Node.TEXT_NODE) { script = `\`${(_a = cNode.textContent) !== null && _a !== void 0 ? _a : ''}\``; const expressionGroups = RawSet.expressionGroups(script); // console.log('???????', script, expressionGroups) if (expressionGroups[0].length > 1) { script = expressionGroups[0][1]; } // console.log('--', expressionGroups, script) } else if (cNode.nodeType === Node.ELEMENT_NODE) { const element = cNode; const targetAttrNames = ((_c = (_b = config === null || config === void 0 ? void 0 : config.targetAttrs) === null || _b === void 0 ? void 0 : _b.map(it => it.name)) !== null && _c !== void 0 ? _c : []) .concat(RawSet.DR_ATTRIBUTES, RawSet.DR_DETECT_FILTER_OPTIONNAME, RawSet.DR_DETECT_IF_OPTIONNAME, RawSet.DR_DETECT_ATTR_OPTIONNAME); // .concat(EventManager.normalAttrMapAttrName); const targetScripts = targetAttrNames.map(it => element.getAttribute(it)).filter(it => it).map(it => `(${it})`); const targetAttrMap = element.getAttribute(EventManager.normalAttrMapAttrName); // console.log('targetAttrMap-->', targetAttrMap) if (targetAttrMap) { new Map(JSON.parse(targetAttrMap)).forEach((v, k) => { targetScripts.push(`(${v})`); }); } script = targetScripts.join(';'); // script = targetScripts.map(it=>`try{${it}}catch(e){}`).join(';'); // attribute쪽 체크하는거 추가 // console.log('----!!!!!-->', targetAttrNames) // const otherAttrs = element.getAttributeNames() // .filter(it => !targetAttrNames.includes(it.toLowerCase()) && RawSet.isExporesion(element.getAttribute(it))) // .map(it => { // return `\`${element.getAttribute(it) ?? ''}\``; // }).join(';'); // script += ';' + otherAttrs } if (script) { script = script.replace(/#[^#]*#/g, '({})'); // script = script.replace('}$','}'); // script = script.replace('@this@','this'); // console.log('----------->', script) EventManager.VARNAMES.forEach(it => { // script = script.replace(RegExp(it.replace('$', '\\$'), 'g'), `this?.___${it}`); // script = script.replace(RegExp(it.replace('$', '\\$'), 'g'), `this.___${it}`); script = script.replace(RegExp(it.replace('$', '\\$'), 'g'), `this.___${it}`); // console.log('scripts-->', script) }); // console.log('--------1--', script); // script = script.replaceAll('#{','${').replaceAll('}#', '}') // console.log('--------2--', script); Array.from(ScriptUtils.getVariablePaths(script)).filter(it => !it.startsWith(`___${EventManager.SCRIPTS_VARNAME}`)).forEach(it => usingTriggerVariables.add(it)); } }); // console.log('usingTriggerVariable----------->', usingTriggerVariables) return usingTriggerVariables; } // 중요 render 처리 부분 render(obj, config) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; // console.log('render!!!!!!!!!!!!!!') const genNode = config.window.document.importNode(this.dataSet.fragment, true); const raws = []; const onAttrInitCallBacks = []; const onElementInitCallBacks = []; const onThisComponentSetCallBacks = []; const drAttrs = []; // console.log('rawSet render!!', obj, config, this, Array.from(genNode.childNodes.values())); for (const cNode of Array.from(genNode.childNodes.values())) { // console.log('cNodecNodecNode', cNode); let attribute = {}; if (cNode.nodeType === Node.ELEMENT_NODE) { attribute = DomUtils.getAttributeToObject(cNode); } const __render = Object.freeze({ rawSet: this, scripts: EventManager.setBindProperty(config === null || config === void 0 ? void 0 : config.scripts, obj), router: config === null || config === void 0 ? void 0 : config.router, range: Range.range, element: cNode, attribute: attribute, rootObject: obj, scriptUtils: ScriptUtils, nearThis: this.findNearThis(obj), parentThis: this.findParentThis(obj), bindScript: ` 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 normalAttribute = attribute[EventManager.normalAttrMapAttrName]; // if (normalAttribute) { // new Map<string, string>(JSON.parse(normalAttribute)).forEach((v, k) => { // const cval = ScriptUtils.evalReturn({ bodyScript: __render.bindScript, returnScript: v }, Object.assign(obj, { __render: __render })); // console.log('-----------',v,k, cval); // attribute[v] = cval; // }); // } const fag = config.window.document.createDocumentFragment(); if (cNode.nodeType === Node.TEXT_NODE && cNode.textContent) { // console.log('text-->', this, obj, config, cNode.textContent); // console.log('text-->', Array.from(this.fragment.childNodes)) const textContent = cNode.textContent; const runText = RawSet.expressionGroups(textContent)[0][1]; // console.log('--->', RawSet.exporesionGrouops(textContent), textContent,runText, runText[0][1]) let newNode; if (textContent === null || textContent === void 0 ? void 0 : textContent.startsWith('#')) { const r = ScriptUtils.eval(`${__render.bindScript} return ${runText}`, Object.assign(obj, { __render })); const template = config.window.document.createElement('template'); template.innerHTML = r; newNode = template.content; } else { const r = ScriptUtils.eval(`${__render.bindScript} return ${runText}`, Object.assign(obj, { __render })); newNode = config.window.document.createTextNode(r); } (_a = cNode.parentNode) === null || _a === void 0 ? void 0 : _a.replaceChild(newNode, cNode); // console.log('-------', this.point.start.parentNode.nodeName) // 중요 style value change 됐을때 다시 처리해야되기떄문에: 마지막에 completed 없는 attr 가지고 판단 하니깐 if (this.type === RawSetType.STYLE_TEXT && this.point.parent) { this.point.parent.removeAttribute('completed'); } } else if (cNode.nodeType === Node.ELEMENT_NODE) { const element = cNode; // console.log('target-->', element) 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), 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) }; 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: (_b = config.operatorAround) === null || _b === void 0 ? void 0 : _b.drPre }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new Dr(this, __render, { raws, fag }, { element, attrName: RawSet.DR_NAME, attr: drAttr.dr, attrs: drAttr }, { config, obj, operatorAround: (_c = config.operatorAround) === null || _c === void 0 ? void 0 : _c.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: (_d = config.operatorAround) === null || _d === void 0 ? void 0 : _d.drIf }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrStripElement(this, __render, { raws, fag }, { element, attrName: RawSet.DR_STRIP_NAME, attr: drAttr.drStripElement, attrs: drAttr }, { config, obj, operatorAround: (_e = config.operatorAround) === null || _e === void 0 ? void 0 : _e.drThis }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrThis(this, __render, { raws, fag }, { element, attrName: RawSet.DR_THIS_NAME, attr: drAttr.drThis, attrs: drAttr }, { config, obj, operatorAround: (_f = config.operatorAround) === null || _f === void 0 ? void 0 : _f.drThis }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrForm(this, __render, { raws, fag }, { element, attrName: RawSet.DR_FOR_NAME, attr: drAttr.drForm, attrs: drAttr }, { config, obj, operatorAround: (_g = config.operatorAround) === null || _g === void 0 ? void 0 : _g.drForm }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrInnerText(this, __render, { raws, fag }, { element, attrName: RawSet.DR_INNERTEXT_NAME, attr: drAttr.drInnerText, attrs: drAttr }, { config, obj, operatorAround: (_h = config.operatorAround) === null || _h === void 0 ? void 0 : _h.drInnerText }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrInnerHTML(this, __render, { raws, fag }, { element, attrName: RawSet.DR_INNERHTML_NAME, attr: drAttr.drInnerHTML, attrs: drAttr }, { config, obj, operatorAround: (_j = config.operatorAround) === null || _j === void 0 ? void 0 : _j.drInnerHTML }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrFor(this, __render, { raws, fag }, { element, attrName: RawSet.DR_FOR_NAME, attr: drAttr.drFor, attrs: drAttr }, { config, obj, operatorAround: (_k = config.operatorAround) === null || _k === void 0 ? void 0 : _k.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: (_l = config.operatorAround) === null || _l === void 0 ? void 0 : _l.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: (_m = config.operatorAround) === null || _m === void 0 ? void 0 : _m.drThisProperty }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrAppender(this, __render, { raws, fag }, { element, attrName: RawSet.DR_APPENDER_NAME, attr: drAttr.drAppender, attrs: drAttr }, { config, obj, operatorAround: (_o = config.operatorAround) === null || _o === void 0 ? void 0 : _o.drAppender }, { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }), new DrRepeat(this, __render, { raws, fag }, { element, attrName: RawSet.DR_REPEAT_NAME, attr: drAttr.drRepeat, attrs: drAttr }, { config, obj, operatorAround: (_p = config.operatorAround) === null || _p === void 0 ? void 0 : _p.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 = yield operator.start(); if (state === ExecuteState.EXECUTE) { break; } else if (state === ExecuteState.STOP) { return raws; } } } } this.point.childrenRawSets = raws; raws.forEach(it => { it.point.parentRawSet = this; }); // console.log('pppppppppppppp', this); // replaceBody와 applyEvent 순서를 바꿨다 20250511 const childrenNodes = Array.from(genNode.childNodes); this.applyEvent(obj, genNode, config); this.replaceBody(genNode); // 중요 여기서 마지막에 연션된 값을 그려준다. // console.log('rawSEt!!!!!!!', obj,childrenNodes,config) this.onRenderedEvent(obj, childrenNodes, config); drAttrs.forEach(it => { if (it.drCompleteOption) { // genNode.childNodes const render = Object.freeze({ rawSet: this, fag: genNode, scripts: EventManager.setBindProperty(config === null || config === void 0 ? void 0 : config.scripts, obj) }); ScriptUtils.eval(` 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 })); } }); // 중요 style isolation 나중에 :scope로 대체 가능할듯. // 2023.9.4일 없앰 style 처음들어올때 처리하는걸로 바꿈 // RawSet.generateStyleSheetsLocal(config); for (const it of onThisComponentSetCallBacks) { if (isOnInitRender(it.obj)) { (_r = (_q = it.obj) === null || _q === void 0 ? void 0 : _q.onInitRender) === null || _r === void 0 ? void 0 : _r.call(_q, {}, this); } } for (const it of onElementInitCallBacks) { if (isOnInitRender(this.dataSet.render.currentThis)) { // TODO: 나중에 파라미터 들어가야될듯. 지금은 리팩토링하느라 빠짐 // console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', it, this.dataSet); // dr-on-init:arguments // if (isOnInitRender()) { // it.targetElement.__render.component.onInitRender?.(...param); // } // if (it.targetElement?.__render?.element && it.targetElement?.__render?.component) { // const oninit = it.targetElement.__render.element.getAttribute(RawSet.DR_ON_INIT_ARGUMENTS_OPTIONNAME); // dr-on-component-init // let param = []; // if (oninit) { // const script = `${it.targetElement.__render.renderScript} return ${oninit} `; // param = ScriptUtils.eval(script, Object.assign(obj, { // __render: it.targetElement.__render // })); // if (!Array.isArray(param)) { // param = [param]; // } // } // // if (isOnInitRender(it.targetElement.__render.component)) { // it.targetElement.__render.component.onInitRender?.(...param); // } // } this.dataSet.render.currentThis.onInitRender({}, this); } (_s = config === null || config === void 0 ? void 0 : config.onElementInit) === null || _s === void 0 ? void 0 : _s.call(config, it.name, obj, this, it.targetElement); } // TODO: 이부분도 위에 targetElement 처럼 해야될까? for (const it of onAttrInitCallBacks) { (_t = config === null || config === void 0 ? void 0 : config.onAttrInit) === null || _t === void 0 ? void 0 : _t.call(config, it.attrName, it.attrValue, obj, this); } // component destroy if (obj.__domrender_components) { Object.entries(obj.__domrender_components).forEach(([key, value]) => { var _a, _b; const rawSet = value.__rawSet; const drAttrs = rawSet === null || rawSet === void 0 ? void 0 : rawSet.dataSet.render.attribute; if (rawSet && !rawSet.isConnected) { const destroyOptions = (_b = (_a = drAttrs === null || drAttrs === void 0 ? void 0 : drAttrs.drDestroyOption) === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : []; RawSet.destroy(obj.__domrender_components[key], { rawSet: rawSet }, config, destroyOptions); delete obj.__domrender_components[key]; } }); } // console.log('-------raws',raws) return raws; }); } // 중요 스타일 적용 부분 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 === null || reg === void 0 ? void 0 : reg[1]; const extracted = reg === null || reg === void 0 ? void 0 : 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) { var _a; // console.log('style!!!!!!!!!!!!!!!!1', styleBody, componentKey, styleTagWrap); if (Array.isArray(styleBody)) { styleBody = styleBody.join('\n'); } styleBody = styleBody.replaceAll('#uuid#', componentKey); const start = `#${componentKey}-start`; const end = `#${componentKey}-end`; // 이거뭐하는지 까먹었네 뭐였지??.. // 동적으로 처리하는것같은데.. css 에서는 동적으로 처리하는걸 지향 해야될것같은데 이기능 deprecated 할지 고민중 const before = StringUtils.regexExecArrayReplace(styleBody, /(\$\{.*?\}\$)/g, (data) => { // console.log('동적?', `var(--domrender-${data[0]})`) return `var(--domrender-${data[0]})`; }); // const before = styleBody; // console.log('before@@@@@@@@@@@', before) const cssobject = cssParse(before); (_a = cssobject.stylesheet) === null || _a === void 0 ? void 0 : _a.rules.forEach((rule) => { var _a, _b, _c; // console.log('--------cssParse', rule) const isRoot = (_a = rule.selectors) === null || _a === void 0 ? void 0 : _a.find(it => it.startsWith(':root')); if (rule.type === 'rule' && !isRoot) { // && !!isRoot rule.selectors = (_b = rule.selectors) === null || _b === void 0 ? void 0 : _b.map(sit => { return this.generateRuleSelector(start, end, sit); }); } else if (rule.type === 'media' && !isRoot) { (_c = rule.rules) === null || _c === void 0 ? void 0 : _c.forEach((mediaRule) => { var _a; mediaRule.selectors = (_a = mediaRule.selectors) === null || _a === void 0 ? void 0 : _a.map(sit => { return this.generateRuleSelector(start, end, sit); }); // console.log('--------', mediaRule, mediaRule.selectors) }); } }); const stringify = cssStringify(cssobject); // let after = StringUtils.regexExecArrayReplace(stringify as string, /(var\(--domrender-(\$\{.*?\}\$)?\))/g, (data) => { // return data[2]; // }); let after = stringify; // console.log('after@@@@@@@@@@@', after) // 여기서 선언 selector 자체에도 처리가능하도록 한다 20250518 after = after.replaceAll('/*$', '${'); after = after.replaceAll('$*/', '}$'); if (styleTagWrap) { styleBody = `<style id='${componentKey}-style' domstyle>${after}</style>`; } // console.log('style!!!!!!!!!!!!!!2', styleBody); return styleBody; } applyEvent(obj, fragment = this.dataSet.fragment, config) { eventManager.applyEvent(obj, eventManager.findAttrElements(fragment, config), config); } onRenderedEvent(obj, nodes, config) { eventManager.onRenderedEvent(obj, nodes, config); } getAttribute(element, attr) { const data = element.getAttribute(attr); return data; } getAttributeAndDelete(element, attr) { const data = element.getAttribute(attr); // if (data) // element.setAttribute(`origin-${attr}`, data); element.removeAttribute(attr); return data; } getDrAppendAttributeAndDelete(element, obj) { let data = element.getAttribute(RawSet.DR_APPENDER_NAME); // if (data && !/\[[0-9]+\]/g.test(data)) { if (data && !/\[.+\]/g.test(data)) { const currentIndex = ScriptUtils.evalReturn(`${data}?.length -1`, obj); // console.log('------?', currentIndex) // if (currentIndex === undefined || isNaN(currentIndex)) { // return undefined; // } // const currentIndex = ScriptUtils.evalReturn(`${data}.length`, obj); data = `${data}[${currentIndex}]`; element.setAttribute(RawSet.DR_APPENDER_NAME, data); // element.setAttribute(RawSet.DR_IF_NAME, data); // element.setAttribute('dr-id', data); // console.log('-->', element) } // if (data && !/\.childs\[[0-9]+\]/g.test(data)) { // const currentIndex = ScriptUtils.evalReturn(`${data}.currentIndex`, obj); // data = `${data}.childs[${currentIndex}]`; // element.setAttribute(RawSet.DR_APPENDER_NAME, data) // } element.removeAttribute(RawSet.DR_APPENDER_NAME); return data; } replaceBody(genNode) { var _a; this.childAllRemove(); (_a = this.point.start.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(genNode, this.point.start.nextSibling); // 중요 start checkpoint 다음인 end checkpoint 앞에 넣는다. 즉 중간 껴넣기 (나중에 meta tag로 변경을 해도될듯하긴한데..) } // 중요 important static checkPointCreates(element, obj, config) { var _a, _b, _c, _d, _e, _f, _g, _h, _j; // console.log('!@@@@@@@@@@@@@@@@', obj); // const NodeFilter = (config.window as any).NodeFilter; // const thisVariableName = (element as any).__domrender_this_variable_name; // console.log('thisVariableName---', thisVariableName); const nodeIterator = config.window.document.createNodeIterator(element, NodeFilter.SHOW_ALL, { acceptNode(node) { var _a, _b, _c, _d, _e, _f; // console.log('nodeType', node.nodeType, (node as any).tagName, (node as any).data); if (node.nodeType === Node.TEXT_NODE) { // console.log('text--->', node.textContent) // console.log('????????', node.parentElement, node.parentElement?.getAttribute('dr-pre')); // console.log('???????/',node.textContent, node.parentElement?.getAttribute('dr-pre')) // TODO: 나중에 // const between = StringUtils.betweenRegexpStr('[$#]\\{', '\\}', StringUtils.deleteEnter((node as Text).data ?? '')) const between = RawSet.expressionGroups(StringUtils.deleteEnter((_a = node.data) !== null && _a !== void 0 ? _a : '')); // console.log('bbbb', between) return (between === null || between === void 0 ? void 0 : between.length) > 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; // return /\$\{.*?\}/g.test(StringUtils.deleteEnter((node as Text).data ?? '')) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; // return /[$#]\{.*?\}/g.test(StringUtils.deleteEnter((node as Text).data ?? '')) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; } else if (node.nodeType === Node.ELEMENT_NODE) { const element = node; if (element.hasAttribute(RawSet.DR_PRE_NAME)) { return NodeFilter.FILTER_REJECT; } if (element.hasAttribute(EventManager.attrAttrName)) { const script = (_b = element.getAttribute(EventManager.attrAttrName)) !== null && _b !== void 0 ? _b : ''; // console.log('scriptscriptscriptscriptscriptscript,', script) const keyValuePairs = Array.from(script.matchAll(/(\w+):\s*([^,}]+)/g)).map(match => ({ key: match[1], value: match[2] })); (keyValuePairs !== null && keyValuePairs !== void 0 ? keyValuePairs : []).forEach(it => { element.setAttribute(it.key, '${' + it.value + '}$'); }); // console.log('-------k', keyValuePairs) // const drAttr = ScriptUtils.evalReturn(script, obj) // Object.entries(drAttr).forEach(([key, value]) => { // const keyValuePairs = Array.from(a.matchAll(/(\w+):\s*([^,}]+)/g)).map(match => ({ key: match[1], value: match[2] })); // console.log(keyValuePairs); // // 출력: [{ key: 'value', value: 'this.child.obj.name' }, { key: 'wow', value: 'this.ww' }, { key: 'zz', value: '22' }, { key: 'v', value: '"ee"' }] // // console.log('-----------------', key,value) // element.setAttribute(key, '${'+(value)+'}$'); // }) // EventManager.attrNames.filter(it => it in drAttr).forEach(it => { // if (drAttr[it] === null) { // element.removeAttribute(it); // } else { // element.setAttribute(it, drAttr[it]); // } // }) // console.log('-------->', Array.from(element.attributes), element.getAttribute('dr-attr'), obj) } // element.setAttribute('dr-event-click', 'console.log(11)'); const targetElementIs = element.getAttribute(RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME); const targetElementNames = (_d = (_c = config.targetElements) === null || _c === void 0 ? void 0 : _c.map(it => it.name.toLowerCase())) !== null && _d !== void 0 ? _d : []; const isElement = targetElementNames.includes(element.tagName.toLowerCase()) || targetElementNames.includes(targetElementIs === null || targetElementIs === void 0 ? void 0 : targetElementIs.toLowerCase()); // if (isElement) { // (element as HTMLElement).style.display = 'none'; // (element as HTMLElement).style.width = '100px'; // (element as HTMLElement).style.height = '100px'; // console.log((element as HTMLElement).outerHTML) // } // console.log('------targetElementIstargetElementIs>', targetElementNames, '---', isElement, targetElementIs); // const targetAttrNames = (config.targetAttrs?.map(it => it.name) ?? []).concat([...RawSet.DR_ATTRIBUTES,...EventManager.RAWSET_CHECK_ATTRIBUTE]); const targetAttrNames = ((_f = (_e = config.targetAttrs) === null || _e === void 0 ? void 0 : _e.map(it => it.name)) !== null && _f !== void 0 ? _f : []).concat([...RawSet.DR_ATTRIBUTES]); const normalAttrs = new Map(); const linkVariables = new Map(); const linkNames = EventManager.linkAttrs.map(it => it.name); const isAttr = element.getAttributeNames().filter(it => { const value = element.getAttribute(it); // link일때 if (linkNames.includes(it)) { linkVariables.set(it, value); } else if (value && RawSet.isExpression(value)) { // 표현식있을떄 let variablePath = RawSet.expressionGroups(value)[0][1]; // normal Attribute 초반에 셋팅해주기. variablePath = variablePath.replace(/#[^#]*#/g, '({})'); const cval = ScriptUtils.evalReturn(variablePath, Object.assign(obj)); if (cval === null) { element.removeAttribute(it); } else { element.setAttribute(it, cval); } normalAttrs.set(it, variablePath); // console.log('normalAttribute', it, variablePath); } // console.log(element.getAttribute(it), attrExpresion); const isTargetAttr = targetAttrNames.includes(it.toLowerCase()); return isTargetAttr; }).length > 0; if (linkVariables.size) { element.setAttribute(EventManager.linkTargetMapAttrName, JSON.stringify(Array.from(linkVariables.entries()))); } // 기본 attribute를 처리하기위해 if (normalAttrs.size) { element.setAttribute(EventManager.normalAttrMapAttrName, JSON.stringify(Array.from(normalAttrs.entries()))); } // if (isElement) { // element.setAttribute('www', '@this@'); // } const r = (isAttr || isElement) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; return r; } return NodeFilter.FILTER_REJECT; } }); const pars = []; let currentNode; // eslint-disable-next-line no-cond-assign while (currentNode = nodeIterator.nextNode()) { if (currentNode.nodeType === Node.TEXT_NODE) { const text = (_a = currentNode.textContent) !== null && _a !== void 0 ? _a : ''; const template = config.window.document.createElement('template'); // const a = StringUtils.regexExec(/\$\{.*?\}/g, text); // const a = StringUtils.regexExec(/[$#]\{.*?\}/g, text); // const a = StringUtils.betweenRegexpStr('[$#]\\{', '\\}', text); // <--TODO: 나중에.. const groups = RawSet.expressionGroups(text); const map = groups.map(it => { var _a; return ({ uuid: `${RandomUtils.alphabet(40)}_${(_a = obj === null || obj === void 0 ? void 0 : obj.constructor) === null || _a === void 0 ? void 0 : _a.name}`, content: it[0], regexArr: it }); }); let lasterIndex = 0; for (let i = 0; i < map.length; i++) { const it = map[i]; // console.log('itttttttttttt', it); const regexArr = it.regexArr; // 중요: text경우 asdasd ${this.name}$ 이렇게 있다면 앞부분 asdasd <-- 이부분은 살려야되니깐 아래처럼 짜름 const preparedText = regexArr.input.substring(lasterIndex, regexArr.index); // const preparedText = regexArr[1]; // const start = config.window.document.createElement('meta'); // start.setAttribute('id', `${it.uuid}-start`); // const end = config.window.document.createElement('meta'); // end.setAttribute('id', `${it.uuid}-end`); let type; if (currentNode.parentNode && currentNode.parentNode.nodeName.toUpperCase() === 'STYLE') { type = RawSetType.STYLE_TEXT; } else { type = RawSetType.TEXT; } const node = document.createTextNode(preparedText); const startEndPoint = RawSet.createStartEndPoint({ id: it.uuid, type }, config); // layout setting // console.log('createTextNode', node); template.content.append(node); // expression 앞 부분 넣어줘야 앞부분 일반 text 안짤린다. template.content.append(startEndPoint.start); // add start checkpoint template.content.append(startEndPoint.end); // add end checkpoint // content 안쪽 RawSet render 할때 start 와 end 사이에 fragment 연산해서 들어간다. const fragment = config.window.document.createDocumentFragment(); fragment.append(config.window.document.createTextNode(it.content)); // (startEndPoint.start as any).khh = RandomUtils.decimal(0,10) pars.push(new RawSet(it.uuid, type, { start: startEndPoint.start, node: currentNode, end: startEndPoint.end, parent: currentNode.parentNode, // thisVariableName: thisVariableName }, { fragment: fragment, config: config })); lasterIndex = regexArr.index + it.content.length; } template.content.append(config.window.document.createTextNode(text.substring(lasterIndex, text.length))); (_b = currentNode === null || currentNode === void 0 ? void 0 : currentNode.parentNode) === null || _b === void 0 ? void 0 : _b.replaceChild(template.content, currentNode); // <-- 여기서 text를 fragment로 replace했기때문에 추적 변경이 가능하다. } else if (currentNode.nodeType === Node.ELEMENT_NODE) { const uuid = `${RandomUtils.alphabet(40)}___${(_c = obj === null || obj === void 0 ? void 0 : obj.constructor) === null || _c === void 0 ? void 0 : _c.name}`; const element = currentNode; const fragment = config.window.document.createDocumentFragment(); const elementType = RawSetType.TARGET_ELEMENT; const startEndPoint = RawSet.createStartEndPoint({ node: element, id: uuid, type: elementType }, config); // 여기서 등록한 component 추가한다. const targetElementIs = element.getAttribute(RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME); const targetElementNames = (_e = (_d = config.targetElements) === null || _d === void 0 ? void 0 : _d.map(it => it.name.toLowerCase())) !== null && _e !== void 0 ? _e : []; const isElement = targetElementNames.includes(element.tagName.toLowerCase()) || targetElementNames.includes(targetElementIs === null || targetElementIs === void 0 ? void 0 : targetElementIs.toLowerCase()); // if (isElement) { // (element as HTMLElement).style.display = 'none' // } // const isElement = targetElementNames.includes(element.tagName.toLowerCase()); const targetAttrNames = ((_g = (_f = config.targetAttrs) === null || _f === void 0 ? void 0 : _f.map(it => it.name)) !== null && _g !== void 0 ? _g : []).concat(RawSet.DR_ATTRIBUTES); const isAttr = element.getAttributeNames().filter(it => targetAttrNames.includes(it.toLowerCase())).length > 0; (_h = currentNode === null || currentNode === void 0 ? void 0 : currentNode.parentNode) === null || _h === void 0 ? void 0 : _h.insertBefore(startEndPoint.start, currentNode); (_j = currentNode === null || currentNode === void 0 ? void 0 : currentNode.parentNode) === null || _j === void 0 ? void 0 : _j.insertBefore(startEndPoint.end, currentNode.nextSibling); fragment.append(currentNode); // const tempDiv = document.createElement('div'); // tempDiv.appendChild(fragment.cloneNode(true)); // fragment 복사본 추가 // console.log('------',tempDiv.innerHTML); // console.log(); const rawSet = new RawSet(uuid, isElement ? elementType : (isAttr ? RawSetType.TARGET_ATTR : RawSetType.UNKOWN), { start: startEndPoint.start, node: currentNode, end: startEndPoint.end, parent: currentNode.parentNode, // thisVariableName: thisVariableName }, { config: config, fragment: fragment }); pars.push(rawSet); } } // console.log('parsparsparsparsparsparsparsparsparspars', pars); 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 { // text 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 === null || stopNext === void 0 ? void 0 : stopNext(next)) { return; } childs.push(next); next = next.nextSibling; } return childs; } getHasRawSet(key) { let rawSet; this.childs((node) => { var _a, _b; const drKey = (_b = (_a = node).getAttribute) === null || _b === void 0 ? void 0 : _b.call(_a, 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_REP