@dooboostore/dom-render
Version:
html view template engine
766 lines • 90 kB
JavaScript
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