@dooboostore/dom-render 1.0.108 → 1.0.110

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/README.MD +27 -1451
  2. package/dist/cjs/DomRender.js +41 -26
  3. package/dist/cjs/DomRender.js.map +2 -2
  4. package/dist/cjs/DomRenderProxy.js +134 -62
  5. package/dist/cjs/DomRenderProxy.js.map +2 -2
  6. package/dist/cjs/bundle-entry.js +32 -21
  7. package/dist/cjs/bundle-entry.js.map +2 -2
  8. package/dist/cjs/components/ComponentBase.js +24 -6
  9. package/dist/cjs/components/ComponentBase.js.map +2 -2
  10. package/dist/cjs/components/ComponentRouterBase.js +11 -1
  11. package/dist/cjs/components/ComponentRouterBase.js.map +2 -2
  12. package/dist/cjs/components/appender/Appender.js +0 -3
  13. package/dist/cjs/components/appender/Appender.js.map +2 -2
  14. package/dist/cjs/components/checkbox/CheckBox.js.map +2 -2
  15. package/dist/cjs/components/choose/Choose.js +7 -1
  16. package/dist/cjs/components/choose/Choose.js.map +2 -2
  17. package/dist/cjs/components/details/Details.js +2 -2
  18. package/dist/cjs/components/details/Details.js.map +2 -2
  19. package/dist/cjs/components/forOf/ForOf.js.map +2 -2
  20. package/dist/cjs/components/if/If.js +2 -2
  21. package/dist/cjs/components/if/If.js.map +2 -2
  22. package/dist/cjs/components/input/Input.js +2 -2
  23. package/dist/cjs/components/input/Input.js.map +2 -2
  24. package/dist/cjs/components/promise/PromiseSwitch.js +6 -6
  25. package/dist/cjs/components/promise/PromiseSwitch.js.map +2 -2
  26. package/dist/cjs/components/radio/Radio.js.map +2 -2
  27. package/dist/cjs/components/router/Route.js +2 -2
  28. package/dist/cjs/components/router/Route.js.map +2 -2
  29. package/dist/cjs/components/router/RouterOutlet.js +17 -3
  30. package/dist/cjs/components/router/RouterOutlet.js.map +2 -2
  31. package/dist/cjs/components/select/Select.js +26 -12
  32. package/dist/cjs/components/select/Select.js.map +2 -2
  33. package/dist/cjs/components/this/This.js +2 -2
  34. package/dist/cjs/components/this/This.js.map +2 -2
  35. package/dist/cjs/components/timer/Timer.js +15 -13
  36. package/dist/cjs/components/timer/Timer.js.map +2 -2
  37. package/dist/cjs/decorators/DomRenderNoProxy.js +2 -1
  38. package/dist/cjs/decorators/DomRenderNoProxy.js.map +2 -2
  39. package/dist/cjs/events/EventManager.js +9 -2
  40. package/dist/cjs/events/EventManager.js.map +2 -2
  41. package/dist/cjs/lifecycle/OnInitRender.js.map +1 -1
  42. package/dist/cjs/lifecycle/OnRawSetRendered.js +26 -0
  43. package/dist/cjs/lifecycle/OnRawSetRendered.js.map +7 -0
  44. package/dist/cjs/lifecycle/index.js +1 -0
  45. package/dist/cjs/lifecycle/index.js.map +2 -2
  46. package/dist/cjs/operators/DrForOf.js +24 -11
  47. package/dist/cjs/operators/DrForOf.js.map +2 -2
  48. package/dist/cjs/operators/DrIf.js +1 -2
  49. package/dist/cjs/operators/DrIf.js.map +2 -2
  50. package/dist/cjs/operators/DrInnerText.js +2 -2
  51. package/dist/cjs/operators/DrInnerText.js.map +2 -2
  52. package/dist/cjs/operators/DrTargetElement.js +2 -0
  53. package/dist/cjs/operators/DrTargetElement.js.map +2 -2
  54. package/dist/cjs/operators/OperatorExecuter.js +1 -2
  55. package/dist/cjs/operators/OperatorExecuter.js.map +2 -2
  56. package/dist/cjs/package.json +5 -0
  57. package/dist/cjs/rawsets/RawSet.js +392 -115
  58. package/dist/cjs/rawsets/RawSet.js.map +3 -3
  59. package/dist/cjs/rawsets/Render.js.map +1 -1
  60. package/dist/cjs/routers/PathRouter.js +13 -7
  61. package/dist/cjs/routers/PathRouter.js.map +2 -2
  62. package/dist/cjs/routers/Router.js +76 -36
  63. package/dist/cjs/routers/Router.js.map +3 -3
  64. package/dist/esm/DomRender.js +41 -26
  65. package/dist/esm/DomRender.js.map +2 -2
  66. package/dist/esm/DomRenderProxy.js +134 -62
  67. package/dist/esm/DomRenderProxy.js.map +2 -2
  68. package/dist/esm/bundle-entry.js +22 -21
  69. package/dist/esm/bundle-entry.js.map +2 -2
  70. package/dist/esm/components/ComponentBase.js +24 -6
  71. package/dist/esm/components/ComponentBase.js.map +2 -2
  72. package/dist/esm/components/ComponentRouterBase.js +11 -1
  73. package/dist/esm/components/ComponentRouterBase.js.map +2 -2
  74. package/dist/esm/components/appender/Appender.js +0 -3
  75. package/dist/esm/components/appender/Appender.js.map +2 -2
  76. package/dist/esm/components/checkbox/CheckBox.js.map +2 -2
  77. package/dist/esm/components/choose/Choose.js +7 -1
  78. package/dist/esm/components/choose/Choose.js.map +2 -2
  79. package/dist/esm/components/details/Details.js +2 -2
  80. package/dist/esm/components/details/Details.js.map +2 -2
  81. package/dist/esm/components/forOf/ForOf.js.map +2 -2
  82. package/dist/esm/components/if/If.js +2 -2
  83. package/dist/esm/components/if/If.js.map +2 -2
  84. package/dist/esm/components/input/Input.js +2 -2
  85. package/dist/esm/components/input/Input.js.map +2 -2
  86. package/dist/esm/components/promise/PromiseSwitch.js +6 -6
  87. package/dist/esm/components/promise/PromiseSwitch.js.map +2 -2
  88. package/dist/esm/components/radio/Radio.js.map +2 -2
  89. package/dist/esm/components/router/Route.js +2 -2
  90. package/dist/esm/components/router/Route.js.map +2 -2
  91. package/dist/esm/components/router/RouterOutlet.js +18 -4
  92. package/dist/esm/components/router/RouterOutlet.js.map +2 -2
  93. package/dist/esm/components/select/Select.js +26 -12
  94. package/dist/esm/components/select/Select.js.map +2 -2
  95. package/dist/esm/components/this/This.js +2 -2
  96. package/dist/esm/components/this/This.js.map +2 -2
  97. package/dist/esm/components/timer/Timer.js +15 -13
  98. package/dist/esm/components/timer/Timer.js.map +2 -2
  99. package/dist/esm/decorators/DomRenderNoProxy.js +2 -1
  100. package/dist/esm/decorators/DomRenderNoProxy.js.map +2 -2
  101. package/dist/esm/events/EventManager.js +9 -2
  102. package/dist/esm/events/EventManager.js.map +2 -2
  103. package/dist/esm/lifecycle/OnInitRender.js.map +1 -1
  104. package/dist/esm/lifecycle/OnRawSetRendered.js +7 -0
  105. package/dist/esm/lifecycle/OnRawSetRendered.js.map +7 -0
  106. package/dist/esm/lifecycle/index.js +1 -0
  107. package/dist/esm/lifecycle/index.js.map +2 -2
  108. package/dist/esm/operators/DrForOf.js +24 -11
  109. package/dist/esm/operators/DrForOf.js.map +2 -2
  110. package/dist/esm/operators/DrIf.js +1 -2
  111. package/dist/esm/operators/DrIf.js.map +2 -2
  112. package/dist/esm/operators/DrInnerText.js +2 -2
  113. package/dist/esm/operators/DrInnerText.js.map +2 -2
  114. package/dist/esm/operators/DrTargetElement.js +2 -0
  115. package/dist/esm/operators/DrTargetElement.js.map +2 -2
  116. package/dist/esm/operators/OperatorExecuter.js +1 -2
  117. package/dist/esm/operators/OperatorExecuter.js.map +2 -2
  118. package/dist/esm/rawsets/RawSet.js +392 -115
  119. package/dist/esm/rawsets/RawSet.js.map +3 -3
  120. package/dist/esm/routers/PathRouter.js +13 -7
  121. package/dist/esm/routers/PathRouter.js.map +2 -2
  122. package/dist/esm/routers/Router.js +76 -36
  123. package/dist/esm/routers/Router.js.map +3 -3
  124. package/dist/esm-bundle/dooboostore-dom-render.esm.js +14023 -6402
  125. package/dist/esm-bundle/dooboostore-dom-render.esm.js.map +4 -4
  126. package/dist/types/DomRender.d.ts +11 -5
  127. package/dist/types/DomRender.d.ts.map +1 -1
  128. package/dist/types/DomRenderProxy.d.ts +2 -2
  129. package/dist/types/DomRenderProxy.d.ts.map +1 -1
  130. package/dist/types/bundle-entry.d.ts +5 -2
  131. package/dist/types/bundle-entry.d.ts.map +1 -1
  132. package/dist/types/components/ComponentBase.d.ts +8 -2
  133. package/dist/types/components/ComponentBase.d.ts.map +1 -1
  134. package/dist/types/components/ComponentRouterBase.d.ts +8 -0
  135. package/dist/types/components/ComponentRouterBase.d.ts.map +1 -1
  136. package/dist/types/components/appender/Appender.d.ts +0 -2
  137. package/dist/types/components/appender/Appender.d.ts.map +1 -1
  138. package/dist/types/components/checkbox/CheckBox.d.ts.map +1 -1
  139. package/dist/types/components/choose/Choose.d.ts.map +1 -1
  140. package/dist/types/components/details/Details.d.ts +1 -1
  141. package/dist/types/components/details/Details.d.ts.map +1 -1
  142. package/dist/types/components/forOf/ForOf.d.ts.map +1 -1
  143. package/dist/types/components/if/If.d.ts +1 -1
  144. package/dist/types/components/if/If.d.ts.map +1 -1
  145. package/dist/types/components/index.d.ts +2 -1
  146. package/dist/types/components/index.d.ts.map +1 -1
  147. package/dist/types/components/input/Input.d.ts +1 -1
  148. package/dist/types/components/input/Input.d.ts.map +1 -1
  149. package/dist/types/components/promise/PromiseSwitch.d.ts +1 -1
  150. package/dist/types/components/promise/PromiseSwitch.d.ts.map +1 -1
  151. package/dist/types/components/radio/Radio.d.ts.map +1 -1
  152. package/dist/types/components/router/Route.d.ts +1 -1
  153. package/dist/types/components/router/Route.d.ts.map +1 -1
  154. package/dist/types/components/router/RouterOutlet.d.ts +6 -2
  155. package/dist/types/components/router/RouterOutlet.d.ts.map +1 -1
  156. package/dist/types/components/select/Select.d.ts +5 -5
  157. package/dist/types/components/select/Select.d.ts.map +1 -1
  158. package/dist/types/components/this/This.d.ts +1 -1
  159. package/dist/types/components/this/This.d.ts.map +1 -1
  160. package/dist/types/components/timer/Timer.d.ts +6 -4
  161. package/dist/types/components/timer/Timer.d.ts.map +1 -1
  162. package/dist/types/decorators/DomRenderNoProxy.d.ts.map +1 -1
  163. package/dist/types/events/EventManager.d.ts +8 -0
  164. package/dist/types/events/EventManager.d.ts.map +1 -1
  165. package/dist/types/index.d.ts +0 -100
  166. package/dist/types/lifecycle/OnInitRender.d.ts +1 -1
  167. package/dist/types/lifecycle/OnInitRender.d.ts.map +1 -1
  168. package/dist/types/lifecycle/OnRawSetRendered.d.ts +10 -0
  169. package/dist/types/lifecycle/OnRawSetRendered.d.ts.map +1 -0
  170. package/dist/types/lifecycle/index.d.ts +1 -0
  171. package/dist/types/lifecycle/index.d.ts.map +1 -1
  172. package/dist/types/operators/DrForOf.d.ts.map +1 -1
  173. package/dist/types/operators/DrInnerText.d.ts.map +1 -1
  174. package/dist/types/operators/DrTargetElement.d.ts.map +1 -1
  175. package/dist/types/operators/OperatorExecuter.d.ts.map +1 -1
  176. package/dist/types/rawsets/RawSet.d.ts +17 -9
  177. package/dist/types/rawsets/RawSet.d.ts.map +1 -1
  178. package/dist/types/rawsets/Render.d.ts +1 -0
  179. package/dist/types/rawsets/Render.d.ts.map +1 -1
  180. package/dist/types/routers/PathRouter.d.ts.map +1 -1
  181. package/dist/types/routers/Router.d.ts +11 -14
  182. package/dist/types/routers/Router.d.ts.map +1 -1
  183. package/dist/umd-bundle/dooboostore-dom-render.umd.js +14104 -6502
  184. package/dist/umd-bundle/dooboostore-dom-render.umd.js.map +4 -4
  185. package/package.json +9 -8
  186. package/src/DomRender.ts +62 -34
  187. package/src/DomRenderProxy.ts +275 -142
  188. package/src/bundle-entry.ts +5 -3
  189. package/src/components/ComponentBase.ts +33 -11
  190. package/src/components/ComponentRouterBase.ts +17 -2
  191. package/src/components/appender/Appender.ts +0 -5
  192. package/src/components/checkbox/CheckBox.ts +22 -25
  193. package/src/components/choose/Choose.ts +19 -18
  194. package/src/components/details/Details.ts +40 -43
  195. package/src/components/forOf/ForOf.ts +6 -9
  196. package/src/components/if/If.ts +9 -11
  197. package/src/components/input/Input.ts +16 -22
  198. package/src/components/promise/PromiseSwitch.ts +67 -66
  199. package/src/components/radio/Radio.ts +23 -28
  200. package/src/components/router/Route.ts +10 -13
  201. package/src/components/router/RouterOutlet.ts +29 -8
  202. package/src/components/select/Select.ts +47 -33
  203. package/src/components/this/This.ts +13 -12
  204. package/src/components/timer/Timer.ts +29 -65
  205. package/src/decorators/DomRenderNoProxy.ts +3 -1
  206. package/src/events/EventManager.ts +15 -4
  207. package/src/lifecycle/OnInitRender.ts +1 -1
  208. package/src/lifecycle/OnRawSetRendered.ts +15 -0
  209. package/src/lifecycle/index.ts +1 -0
  210. package/src/node_modules/.bin/acorn +17 -0
  211. package/src/node_modules/.bin/browserslist +17 -0
  212. package/src/node_modules/.bin/eslint +17 -0
  213. package/src/node_modules/.bin/sbf +17 -0
  214. package/src/node_modules/.bin/ts-node +17 -0
  215. package/src/node_modules/.bin/ts-node-cwd +17 -0
  216. package/src/node_modules/.bin/ts-node-dev +17 -0
  217. package/src/node_modules/.bin/ts-node-esm +17 -0
  218. package/src/node_modules/.bin/ts-node-script +17 -0
  219. package/src/node_modules/.bin/ts-node-transpile-only +17 -0
  220. package/src/node_modules/.bin/ts-script +17 -0
  221. package/src/node_modules/.bin/tsc +17 -0
  222. package/src/node_modules/.bin/tsnd +17 -0
  223. package/src/node_modules/.bin/tsserver +17 -0
  224. package/src/node_modules/.bin/webpack +17 -0
  225. package/src/node_modules/.bin/webpack-cli +17 -0
  226. package/src/node_modules/.bin/webpack-dev-server +17 -0
  227. package/src/operators/DrForOf.ts +25 -10
  228. package/src/operators/DrIf.ts +1 -1
  229. package/src/operators/DrInnerText.ts +2 -1
  230. package/src/operators/DrTargetElement.ts +14 -0
  231. package/src/operators/OperatorExecuter.ts +1 -2
  232. package/src/rawsets/RawSet.ts +709 -295
  233. package/src/rawsets/Render.ts +1 -0
  234. package/src/routers/PathRouter.ts +14 -7
  235. package/src/routers/Router.ts +107 -61
  236. package/types.d.ts +0 -2825
@@ -1,7 +1,6 @@
1
1
  import { RandomUtils } from '@dooboostore/core/random/RandomUtils';
2
2
  import { StringUtils } from '@dooboostore/core/string/StringUtils';
3
- import { ScriptUtils } from '@dooboostore/core-web/script/ScriptUtils';
4
- import { EventManager } from '../events/EventManager';
3
+ import { EventManager, NormalAttrDataType } from '../events/EventManager';
5
4
  import type { DomRenderConfig } from '../configs/DomRenderConfig';
6
5
  import { Range } from '../iterators/Range';
7
6
  import { ElementUtils } from '@dooboostore/core-web/element/ElementUtils';
@@ -9,7 +8,7 @@ import { ComponentSet } from '../components/ComponentSet';
9
8
  import { DrPre } from '../operators/DrPre';
10
9
  import { Dr } from '../operators/Dr';
11
10
  import { DrIf } from '../operators/DrIf';
12
- import { ExecuteState } from '../operators/OperatorExecuter';
11
+ import { ExecuteState, OperatorExecuter } from '../operators/OperatorExecuter';
13
12
  import { DrThis } from '../operators/DrThis';
14
13
  import { DrForm } from '../operators/DrForm';
15
14
  import { DrInnerText } from '../operators/DrInnerText';
@@ -40,7 +39,10 @@ import { isOnCreatedThisChild } from '../lifecycle/OnCreatedThisChild';
40
39
  import { isOnDestroyRender, OnDestroyRenderParams } from '../lifecycle/OnDestroyRender';
41
40
  import { DrTargetElementIsElement } from '../operators/DrTargetElementIsElement';
42
41
  import { ObjectUtils } from '@dooboostore/core/object/ObjectUtils';
42
+ import { NodeUtils } from '@dooboostore/core-web/node/NodeUtils';
43
+ import { ConvertUtils } from '@dooboostore/core/convert/ConvertUtils';
43
44
 
45
+ export type RenderResult = { raws: RawSet[]; executedOperators: OperatorExecuter[] };
44
46
 
45
47
  export class RawSet {
46
48
  public static readonly DR_NAME = 'dr';
@@ -64,7 +66,6 @@ export class RawSet {
64
66
  public static readonly DR_DETECT_FILTER_OPTIONNAME = 'dr-detect-option-filter';
65
67
  public static readonly DR_DETECT_ATTR_OPTIONNAME = 'dr-detect-option-attr';
66
68
 
67
-
68
69
  /**
69
70
  * @deprecated
70
71
  */
@@ -81,11 +82,14 @@ export class RawSet {
81
82
  public static readonly DR_DESTROY_OPTIONNAME = 'dr-option-destroy';
82
83
 
83
84
  public static readonly DR_THIS_NAME_OPTIONNAME = 'dr-option-this-name';
84
- /**
85
- * @deprecated
86
- */
87
- public static readonly DR_COMPONENT_NAME_OPTIONNAME = 'dr-option-component-name';
88
- public static readonly DR_COMPONENT_INNER_HTML_NAME_OPTIONNAME = 'dr-option-component-inner-html-name';
85
+
86
+ public static readonly DR_VARIABLE_NAME_OPTIONNAME = 'dr-option-variable-name';
87
+ public static readonly DR_ITEM_VARIABLE_NAME_OPTIONNAME = 'dr-option-item-variable-name';
88
+ public static readonly DR_ITEM_INDEX_VARIABLE_NAME_OPTIONNAME = 'dr-option-item-index-variable-name';
89
+ public static readonly DR_INNER_HTML_NAME_OPTIONNAME = 'dr-option-inner-html-name';
90
+ public static readonly DR_INNER_TEXT_NAME_OPTIONNAME = 'dr-option-inner-text-name';
91
+ public static readonly DR_INNER_HTML_ESCAPED_NAME_OPTIONNAME = 'dr-option-inner-html-escaped-name';
92
+
89
93
  public static readonly DR_KEY_OPTIONNAME = 'dr-option-key';
90
94
  public static readonly DR_HAS_KEYS_OPTIONNAME = 'dr-option-has-keys';
91
95
 
@@ -146,27 +150,28 @@ export class RawSet {
146
150
  RawSet.DR_INNERTEXT_NAME,
147
151
  RawSet.DR_REPEAT_NAME,
148
152
  RawSet.DR_DETECT_NAME,
149
- RawSet.DR_STRIP_NAME,
153
+ RawSet.DR_STRIP_NAME
150
154
  ] as const;
151
155
 
152
156
  constructor(
153
157
  public uuid: string,
154
158
  public type: RawSetType,
155
159
  public point: {
156
- start: (Comment | Text | HTMLMetaElement),
157
- node: Node,
158
- end: Comment | Text | HTMLMetaElement,
160
+ start: Comment | Text | HTMLMetaElement;
161
+ node: Node;
162
+ end: Comment | Text | HTMLMetaElement;
163
+ innerHTML?: string;
159
164
  // thisVariableName?: string | null,
160
- parent?: Node | null,
161
- parentRawSet?: RawSet,
162
- childrenRawSets?: RawSet[]
165
+ parent?: Node | null;
166
+ parentRawSet?: RawSet;
167
+ childrenRawSets?: RawSet[];
163
168
  },
164
169
  public dataSet: {
165
170
  config: DomRenderConfig;
166
- fragment: DocumentFragment,
171
+ fragment: DocumentFragment;
167
172
  render?: Render;
168
173
  },
169
- public detect?: { action: Function },
174
+ public detect?: { action: Function }
170
175
  ) {
171
176
  // point.start.rawSet = this;
172
177
  // console.log('rawset constructor->', (this.point.node as Element).getAttributeNames());
@@ -174,7 +179,9 @@ export class RawSet {
174
179
 
175
180
  get isConnected() {
176
181
  // console.log('isConnect???', this, this.point.start.isConnected, this.point.end.isConnected);
177
- return this.point.start.isConnected && this.point.end.isConnected;
182
+ return (
183
+ this.point && this.point.start && this.point.end && this.point.start.isConnected && this.point.end.isConnected
184
+ );
178
185
  }
179
186
 
180
187
  // 중요
@@ -186,22 +193,38 @@ export class RawSet {
186
193
  let script = '';
187
194
  if (cNode.nodeType === Node.TEXT_NODE) {
188
195
  script = `\`${(cNode as Text).textContent ?? ''}\``;
189
- const expressionGroups = RawSet.expressionGroups(script)
196
+ const expressionGroups = RawSet.expressionGroups(script);
190
197
  // console.log('???????', script, expressionGroups)
191
- if (expressionGroups[0].length >1) {
198
+ if (expressionGroups[0].length > 1) {
192
199
  script = expressionGroups[0][1] as string;
193
200
  }
194
201
  // console.log('--', expressionGroups, script)
195
202
  } else if (cNode.nodeType === Node.ELEMENT_NODE) {
196
203
  const element = cNode as Element;
197
- const targetAttrNames = (config?.targetAttrs?.map(it => it.name) ?? [])
198
- .concat(RawSet.DR_ATTRIBUTES, RawSet.DR_DETECT_FILTER_OPTIONNAME, RawSet.DR_DETECT_IF_OPTIONNAME, RawSet.DR_DETECT_ATTR_OPTIONNAME); // .concat(EventManager.normalAttrMapAttrName);
199
- const targetScripts = targetAttrNames.map(it => element.getAttribute(it)).filter(it => it).map(it=>`(${it})`);
204
+ const targetAttrNames = (config?.targetAttrs?.map(it => it.name) ?? []).concat(
205
+ RawSet.DR_ATTRIBUTES,
206
+ RawSet.DR_DETECT_FILTER_OPTIONNAME,
207
+ RawSet.DR_DETECT_IF_OPTIONNAME,
208
+ RawSet.DR_DETECT_ATTR_OPTIONNAME
209
+ ); // .concat(EventManager.normalAttrMapAttrName);
210
+ const targetScripts = targetAttrNames
211
+ .map(it => element.getAttribute(it))
212
+ .filter(it => it)
213
+ .map(it => `(${it})`);
200
214
  const targetAttrMap = element.getAttribute(EventManager.normalAttrMapAttrName);
201
215
  // console.log('targetAttrMap-->', targetAttrMap)
202
216
  if (targetAttrMap) {
203
- new Map<string, string>(JSON.parse(targetAttrMap)).forEach((v, k) => {
204
- targetScripts.push(`(${v})`);
217
+ new Map<string, NormalAttrDataType>(JSON.parse(targetAttrMap)).forEach((v, k) => {
218
+ const variablePaths = v.variablePaths;
219
+ // let targetScript = v.originalAttrValue;
220
+ // variablePaths.forEach(it => {
221
+ // let r = ObjectUtils.Path.toOptionalChainPath(it.inner);
222
+ // targetScript = targetScript.replaceAll(it.origin,`\${${r}}`);
223
+ // })
224
+ // targetScripts.push(`(${targetScript})`);
225
+ // 변수 체크만 하는거니깐 이렇게
226
+ variablePaths.forEach(it => targetScripts.push(`(${it.inner})`));
227
+ // console.log('targetScripts', targetScripts);
205
228
  });
206
229
  }
207
230
  // console.log('targetScriptstargetScripts', targetScripts)
@@ -218,7 +241,6 @@ export class RawSet {
218
241
  // script += ';' + otherAttrs
219
242
  }
220
243
  if (script) {
221
-
222
244
  // console.log('------1-',script)
223
245
  script = script.replace(/#[^#]*#/g, '({})');
224
246
  // console.log('------2-',script)
@@ -237,7 +259,9 @@ export class RawSet {
237
259
  // script = script.replaceAll('#{','${').replaceAll('}#', '}')
238
260
  // console.log('--------2--', script);
239
261
  // TODO: 훔.. 꼭필요한가..? 트리거될때 스크립트변수 까지 감지해야될까?
240
- Array.from(ObjectUtils.Path.detectPathFromScript(script,{excludeThis: true})).filter(it => !it.startsWith(`___${EventManager.SCRIPTS_VARNAME}`)).forEach(it => usingTriggerVariables.add(it));
262
+ Array.from(ObjectUtils.Path.detectPathFromScript(script, { excludeThis: true }))
263
+ .filter(it => !it.startsWith(`___${EventManager.SCRIPTS_VARNAME}`))
264
+ .forEach(it => usingTriggerVariables.add(it));
241
265
  }
242
266
  });
243
267
  // console.log('usingTriggerVariable----------->', usingTriggerVariables)
@@ -245,7 +269,9 @@ export class RawSet {
245
269
  }
246
270
 
247
271
  // 중요 render 처리 부분
248
- public async render(obj: any, config: DomRenderConfig): Promise<RawSet[]> {
272
+ // public async render(obj: any, config: DomRenderConfig): Promise<RawSet[]> {
273
+ // }
274
+ public async render(obj: any, config: DomRenderConfig): Promise<RenderResult> {
249
275
  // console.log('render!!!!!!!!!!!!!!')
250
276
  const genNode = config.window.document.importNode(this.dataSet.fragment, true);
251
277
  const raws: RawSet[] = [];
@@ -254,6 +280,7 @@ export class RawSet {
254
280
  const onThisComponentSetCallBacks: ComponentSet[] = [];
255
281
  const drAttrs: Attrs[] = [];
256
282
  // console.log('rawSet render!!', obj, config, this, Array.from(genNode.childNodes.values()));
283
+ const executedOperators: OperatorExecuter[] = [];
257
284
  for (const cNode of Array.from(genNode.childNodes.values())) {
258
285
  // console.log('cNodecNodecNode', cNode);
259
286
  let attribute = {};
@@ -269,7 +296,7 @@ export class RawSet {
269
296
  element: cNode,
270
297
  attribute: attribute,
271
298
  rootObject: obj,
272
- scriptUtils: ScriptUtils,
299
+ scriptUtils: ObjectUtils.Script,
273
300
  nearThis: this.findNearThis(obj),
274
301
  parentThis: this.findParentThis(obj),
275
302
  bindScript: ` /** render **/
@@ -286,7 +313,6 @@ export class RawSet {
286
313
  `
287
314
  }) as unknown as Render;
288
315
 
289
-
290
316
  // const normalAttribute = attribute[EventManager.normalAttrMapAttrName];
291
317
  // if (normalAttribute) {
292
318
  // new Map<string, string>(JSON.parse(normalAttribute)).forEach((v, k) => {
@@ -296,7 +322,6 @@ export class RawSet {
296
322
  // });
297
323
  // }
298
324
 
299
-
300
325
  const fag = config.window.document.createDocumentFragment();
301
326
  if (cNode.nodeType === Node.TEXT_NODE && cNode.textContent) {
302
327
  // console.log('text-->', this, obj, config, cNode.textContent);
@@ -306,12 +331,18 @@ export class RawSet {
306
331
  // console.log('--->', RawSet.exporesionGrouops(textContent), textContent,runText, runText[0][1])
307
332
  let newNode: Node;
308
333
  if (textContent?.startsWith('#')) {
309
- const r = ScriptUtils.evaluate(`${__render.bindScript} return ${runText}`, Object.assign(obj, {__render}));
334
+ const r = ObjectUtils.Script.evaluate(
335
+ `${__render.bindScript} return ${runText}`,
336
+ Object.assign(obj, { __render })
337
+ );
310
338
  const template = config.window.document.createElement('template') as HTMLTemplateElement;
311
339
  template.innerHTML = r;
312
340
  newNode = template.content;
313
341
  } else {
314
- const r = ScriptUtils.evaluate(`${__render.bindScript} return ${runText}`, Object.assign(obj, {__render}));
342
+ const r = ObjectUtils.Script.evaluate(
343
+ `${__render.bindScript} return ${runText}`,
344
+ Object.assign(obj, { __render })
345
+ );
315
346
  newNode = config.window.document.createTextNode(r);
316
347
  }
317
348
  cNode.parentNode?.replaceChild(newNode, cNode);
@@ -323,7 +354,7 @@ export class RawSet {
323
354
  } else if (cNode.nodeType === Node.ELEMENT_NODE) {
324
355
  const element = cNode as Element;
325
356
  // console.log('target-->', element)
326
- const drAttr:Attrs = {
357
+ const drAttr: Attrs = {
327
358
  dr: this.getAttributeAndDelete(element, RawSet.DR_NAME),
328
359
  drIf: this.getAttributeAndDelete(element, RawSet.DR_IF_NAME),
329
360
  drFor: this.getAttributeAndDelete(element, RawSet.DR_FOR_NAME),
@@ -349,36 +380,154 @@ export class RawSet {
349
380
  drDestroyOption: this.getAttributeAndDelete(element, RawSet.DR_DESTROY_OPTIONNAME),
350
381
  drKeyOption: this.getAttributeAndDelete(element, RawSet.DR_KEY_OPTIONNAME),
351
382
  drDetectIfOption: this.getAttribute(element, RawSet.DR_DETECT_IF_OPTIONNAME),
352
- drHasKeysOption: this.getAttribute(element, RawSet.DR_HAS_KEYS_OPTIONNAME),
383
+ drHasKeysOption: this.getAttribute(element, RawSet.DR_HAS_KEYS_OPTIONNAME)
353
384
  };
354
385
  drAttrs.push(drAttr);
355
386
  // 아래 순서 중요
356
387
  const operators = [
357
- 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}),
358
- 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}),
388
+ new DrPre(
389
+ this,
390
+ __render,
391
+ { raws, fag },
392
+ { element, attrName: RawSet.DR_PRE_NAME, attr: drAttr.drPre, attrs: drAttr },
393
+ { config, obj, operatorAround: config.operatorAround?.drPre },
394
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
395
+ ),
396
+ new Dr(
397
+ this,
398
+ __render,
399
+ { raws, fag },
400
+ { element, attrName: RawSet.DR_NAME, attr: drAttr.dr, attrs: drAttr },
401
+ { config, obj, operatorAround: config.operatorAround?.dr },
402
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
403
+ ),
359
404
  // new Dr(this, __render, {raws, fag}, {element, attrName: EventManager.onRenderedInitAttrName, attr: drAttr.dr, attrs: drAttr}, {config, obj, operatorAround: config.operatorAround?.dr}, {onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks}),
360
- 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}),
361
- 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}),
362
- 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}),
363
- 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}),
364
- 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}),
365
- 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}),
366
- 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}),
367
- 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}),
368
- 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}),
369
- 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}),
370
- 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}),
371
- 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}),
372
- new DrTargetElement(this, __render, {raws, fag}, {element, attrs: drAttr}, {config, obj}, {onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks}),
373
- new DrTargetAttr(this, __render, {raws, fag}, {element, attrs: drAttr}, {config, obj}, {onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks}),
405
+ new DrIf(
406
+ this,
407
+ __render,
408
+ { raws, fag },
409
+ { element, attrName: RawSet.DR_IF_NAME, attr: drAttr.drIf, attrs: drAttr },
410
+ { config, obj, operatorAround: config.operatorAround?.drIf },
411
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
412
+ ),
413
+ new DrStripElement(
414
+ this,
415
+ __render,
416
+ { raws, fag },
417
+ { element, attrName: RawSet.DR_STRIP_NAME, attr: drAttr.drStripElement, attrs: drAttr },
418
+ { config, obj, operatorAround: config.operatorAround?.drThis },
419
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
420
+ ),
421
+ new DrThis(
422
+ this,
423
+ __render,
424
+ { raws, fag },
425
+ { element, attrName: RawSet.DR_THIS_NAME, attr: drAttr.drThis, attrs: drAttr },
426
+ { config, obj, operatorAround: config.operatorAround?.drThis },
427
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
428
+ ),
429
+ new DrForm(
430
+ this,
431
+ __render,
432
+ { raws, fag },
433
+ { element, attrName: RawSet.DR_FOR_NAME, attr: drAttr.drForm, attrs: drAttr },
434
+ { config, obj, operatorAround: config.operatorAround?.drForm },
435
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
436
+ ),
437
+ new DrInnerText(
438
+ this,
439
+ __render,
440
+ { raws, fag },
441
+ { element, attrName: RawSet.DR_INNERTEXT_NAME, attr: drAttr.drInnerText, attrs: drAttr },
442
+ { config, obj, operatorAround: config.operatorAround?.drInnerText },
443
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
444
+ ),
445
+ new DrInnerHTML(
446
+ this,
447
+ __render,
448
+ { raws, fag },
449
+ { element, attrName: RawSet.DR_INNERHTML_NAME, attr: drAttr.drInnerHTML, attrs: drAttr },
450
+ { config, obj, operatorAround: config.operatorAround?.drInnerHTML },
451
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
452
+ ),
453
+ new DrFor(
454
+ this,
455
+ __render,
456
+ { raws, fag },
457
+ { element, attrName: RawSet.DR_FOR_NAME, attr: drAttr.drFor, attrs: drAttr },
458
+ { config, obj, operatorAround: config.operatorAround?.drFor },
459
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
460
+ ),
461
+ new DrForOf(
462
+ this,
463
+ __render,
464
+ { raws, fag },
465
+ { element, attrName: RawSet.DR_FOR_OF_NAME, attr: drAttr.drForOf, attrs: drAttr },
466
+ { config, obj, operatorAround: config.operatorAround?.drForOf },
467
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
468
+ ),
469
+ new DrThisProperty(
470
+ this,
471
+ __render,
472
+ { raws, fag },
473
+ { element, attrName: RawSet.DR_THIS_PROPERTY_NAME, attr: drAttr.drThisProperty, attrs: drAttr },
474
+ { config, obj, operatorAround: config.operatorAround?.drThisProperty },
475
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
476
+ ),
477
+ new DrAppender(
478
+ this,
479
+ __render,
480
+ { raws, fag },
481
+ { element, attrName: RawSet.DR_APPENDER_NAME, attr: drAttr.drAppender, attrs: drAttr },
482
+ { config, obj, operatorAround: config.operatorAround?.drAppender },
483
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
484
+ ),
485
+ new DrRepeat(
486
+ this,
487
+ __render,
488
+ { raws, fag },
489
+ { element, attrName: RawSet.DR_REPEAT_NAME, attr: drAttr.drRepeat, attrs: drAttr },
490
+ { config, obj, operatorAround: config.operatorAround?.drRepeat },
491
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
492
+ ),
493
+ new DrTargetElementIsElement(
494
+ this,
495
+ __render,
496
+ { raws, fag },
497
+ {
498
+ element,
499
+ attrName: RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME,
500
+ attr: drAttr.drReplaceTargetElementIs,
501
+ attrs: drAttr
502
+ },
503
+ { config, obj },
504
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
505
+ ),
506
+ new DrTargetElement(
507
+ this,
508
+ __render,
509
+ { raws, fag },
510
+ { element, attrs: drAttr },
511
+ { config, obj },
512
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
513
+ ),
514
+ new DrTargetAttr(
515
+ this,
516
+ __render,
517
+ { raws, fag },
518
+ { element, attrs: drAttr },
519
+ { config, obj },
520
+ { onAttrInitCallBacks, onElementInitCallBacks, onThisComponentSetCallBacks }
521
+ )
374
522
  ];
375
523
 
376
524
  for (const operator of operators) {
377
525
  const state = await operator.start();
378
526
  if (state === ExecuteState.EXECUTE) {
527
+ executedOperators.push(operator);
379
528
  break;
380
529
  } else if (state === ExecuteState.STOP) {
381
- return raws;
530
+ return { raws, executedOperators };
382
531
  }
383
532
  }
384
533
  }
@@ -391,12 +540,11 @@ export class RawSet {
391
540
 
392
541
  // console.log('pppppppppppppp', this);
393
542
 
394
-
395
543
  // replaceBody와 applyEvent 순서를 바꿨다 20250511
396
544
  const childrenNodes = Array.from(genNode.childNodes);
397
545
  this.applyEvent(obj, genNode, config);
398
546
  this.replaceBody(genNode); // 중요 여기서 마지막에 연션된 값을 그려준다.
399
- // console.log('rawSEt!!!!!!!', obj,childrenNodes,config)
547
+ // console.log('rawSEt!!!!!!!', obj, this.near)
400
548
  // console.log('rawSEt!!!!!!!', obj, this.findNearThis(obj),childrenNodes,config)
401
549
  // console.log('rawSEt!!!!!!!', obj, drAttrs)
402
550
  this.onRenderedEvent(obj, childrenNodes, config);
@@ -409,21 +557,23 @@ export class RawSet {
409
557
  fag: genNode,
410
558
  scripts: EventManager.setBindProperty(config?.scripts, obj)
411
559
  } as Render);
412
- ScriptUtils.evaluate(`
560
+ ObjectUtils.Script.evaluate(
561
+ `
413
562
  const ${EventManager.FAG_VARNAME} = this.__render.fag;
414
563
  const ${EventManager.SCRIPTS_VARNAME} = this.__render.scripts;
415
564
  const ${EventManager.RAWSET_VARNAME} = this.__render.rawSet;
416
- ${it.drCompleteOption}`, Object.assign(obj, {__render: render}));
565
+ ${it.drCompleteOption}`,
566
+ Object.assign(obj, { __render: render })
567
+ );
417
568
  }
418
569
  });
419
570
 
420
-
421
571
  // 중요 style isolation 나중에 :scope로 대체 가능할듯.
422
572
  // 2023.9.4일 없앰 style 처음들어올때 처리하는걸로 바꿈
423
573
  // RawSet.generateStyleSheetsLocal(config);
424
574
  for (const it of onThisComponentSetCallBacks) {
425
575
  if (isOnInitRender(it.obj)) {
426
- it.obj?.onInitRender?.({}, this);
576
+ await it.obj?.onInitRender?.({}, this);
427
577
  }
428
578
  }
429
579
  for (const it of onElementInitCallBacks) {
@@ -452,10 +602,9 @@ export class RawSet {
452
602
  // it.targetElement.__render.component.onInitRender?.(...param);
453
603
  // }
454
604
  // }
455
- this.dataSet.render.currentThis.onInitRender({}, this);
605
+ await this.dataSet.render.currentThis.onInitRender({}, this);
456
606
  }
457
607
 
458
-
459
608
  config?.onElementInit?.(it.name, obj, this, it.targetElement);
460
609
  }
461
610
 
@@ -471,16 +620,15 @@ export class RawSet {
471
620
  const drAttrs: Attrs | undefined = rawSet?.dataSet.render?.attribute;
472
621
  if (rawSet && !rawSet.isConnected) {
473
622
  const destroyOptions = drAttrs?.drDestroyOption?.split(',') ?? [];
474
- RawSet.destroy(obj.__domrender_components[key], {rawSet: rawSet}, config, destroyOptions);
623
+ RawSet.destroy(obj.__domrender_components[key], { rawSet: rawSet }, config, destroyOptions);
475
624
  delete obj.__domrender_components[key];
476
625
  }
477
626
  });
478
627
  }
479
628
  // console.log('-------raws',raws)
480
- return raws;
629
+ return { raws: raws, executedOperators: executedOperators };
481
630
  }
482
631
 
483
-
484
632
  // 중요 스타일 적용 부분
485
633
  private static generateRuleSelector(start: string, end: string, sit: string) {
486
634
  const selectorText = `:is(${start} ~ *:not(${start} ~ ${end} ~ *))`;
@@ -517,30 +665,26 @@ export class RawSet {
517
665
  // const before = styleBody;
518
666
  // console.log('before@@@@@@@@@@@', before)
519
667
  const cssParser = new CssParser(styleBody);
520
-
668
+
521
669
  const processRule = (rule: CssRule) => {
522
670
  if (isStyleRule(rule)) {
523
671
  const isRoot = rule.selector.includes(':root');
524
672
  if (!isRoot) {
525
673
  // Handle comma-separated selectors
526
674
  const selectors = rule.selector.split(',').map(s => s.trim());
527
- const transformedSelectors = selectors.map(selector =>
528
- this.generateRuleSelector(start, end, selector)
529
- );
675
+ const transformedSelectors = selectors.map(selector => this.generateRuleSelector(start, end, selector));
530
676
  rule.selector = transformedSelectors.join(', ');
531
677
  }
532
678
  } else if (isAtRule(rule)) {
533
679
  if (rule.name === 'media') {
534
- const hasRoot = rule.children.some(childRule =>
535
- isStyleRule(childRule) && childRule.selector.includes(':root')
680
+ const hasRoot = rule.children.some(
681
+ childRule => isStyleRule(childRule) && childRule.selector.includes(':root')
536
682
  );
537
683
  if (!hasRoot) {
538
684
  rule.children.forEach(childRule => {
539
685
  if (isStyleRule(childRule)) {
540
686
  const selectors = childRule.selector.split(',').map(s => s.trim());
541
- const transformedSelectors = selectors.map(selector =>
542
- this.generateRuleSelector(start, end, selector)
543
- );
687
+ const transformedSelectors = selectors.map(selector => this.generateRuleSelector(start, end, selector));
544
688
  childRule.selector = transformedSelectors.join(', ');
545
689
  }
546
690
  });
@@ -550,7 +694,7 @@ export class RawSet {
550
694
  };
551
695
 
552
696
  cssParser.rules.forEach(processRule);
553
-
697
+
554
698
  let after = cssParser.stringify();
555
699
  // let after = StringUtils.regexExecArrayReplace(stringify as string, /(var\(--domrender-(\$\{.*?\}\$)?\))/g, (data) => {
556
700
  // return data[2];
@@ -558,9 +702,8 @@ export class RawSet {
558
702
  // console.log('after@@@@@@@@@@@', after)
559
703
 
560
704
  // 여기서 선언 selector 자체에도 처리가능하도록 한다 20250518
561
- after = after.replaceAll('/*$', '${')
562
- after = after.replaceAll('$*/', '}$')
563
-
705
+ after = after.replaceAll('/*$', '${');
706
+ after = after.replaceAll('$*/', '}$');
564
707
 
565
708
  if (styleTagWrap) {
566
709
  styleBody = `<style id='${componentKey}-style' domstyle>${after}</style>`;
@@ -571,7 +714,11 @@ export class RawSet {
571
714
  }
572
715
 
573
716
  public applyEvent(obj: any, fragment = this.dataSet.fragment, config?: DomRenderConfig) {
574
- this.dataSet.config.eventManager.applyEvent(obj, this.dataSet.config.eventManager.findAttrElements(fragment, config), config);
717
+ this.dataSet.config.eventManager.applyEvent(
718
+ obj,
719
+ this.dataSet.config.eventManager.findAttrElements(fragment, config),
720
+ config
721
+ );
575
722
  }
576
723
 
577
724
  public onRenderedEvent(obj: any, nodes: Node[], config?: DomRenderConfig) {
@@ -596,7 +743,10 @@ export class RawSet {
596
743
  let data = element.getAttribute(RawSet.DR_APPENDER_NAME);
597
744
  // if (data && !/\[[0-9]+\]/g.test(data)) {
598
745
  if (data && !/\[.+\]/g.test(data)) {
599
- const currentIndex = ScriptUtils.evaluateReturn(`${ObjectUtils.Path.toOptionalChainPath(data)}?.length -1`, obj);
746
+ const currentIndex = ObjectUtils.Script.evaluateReturn(
747
+ `${ObjectUtils.Path.toOptionalChainPath(data)}?.length -1`,
748
+ obj
749
+ );
600
750
  // console.log('------?', currentIndex)
601
751
  // if (currentIndex === undefined || isNaN(currentIndex)) {
602
752
  // return undefined;
@@ -628,93 +778,117 @@ export class RawSet {
628
778
  // console.log('!@@@@@@@@@@@@@@@@', obj);
629
779
  // const NodeFilter = (config.window as any).NodeFilter;
630
780
  // const thisVariableName = (element as any).__domrender_this_variable_name;
631
- // console.log('thisVariableName---', thisVariableName);
632
- const nodeIterator = config.window.document?.createNodeIterator(element, NodeFilter.SHOW_ALL, {
633
- acceptNode(node) {
634
- // console.log('nodeType', node.nodeType, (node as any).tagName, (node as any).data);
635
- if (node.nodeType === Node.TEXT_NODE) {
636
- // console.log('text--->', node.textContent)
637
- // console.log('????????', node.parentElement, node.parentElement?.getAttribute('dr-pre'));
638
- // console.log('???????/',node.textContent, node.parentElement?.getAttribute('dr-pre'))
639
- // TODO: 나중에
640
- // const between = StringUtils.betweenRegexpStr('[$#]\\{', '\\}', StringUtils.deleteEnter((node as Text).data ?? ''))
641
- const between = RawSet.expressionGroups(StringUtils.deleteEnter((node as Text).data ?? ''));
642
- // console.log('bbbb', between)
643
- return between?.length > 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
644
- // return /\$\{.*?\}/g.test(StringUtils.deleteEnter((node as Text).data ?? '')) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
645
- // return /[$#]\{.*?\}/g.test(StringUtils.deleteEnter((node as Text).data ?? '')) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
646
- } else if (node.nodeType === Node.ELEMENT_NODE) {
647
- const element = node as Element;
648
- if (element.hasAttribute(RawSet.DR_PRE_NAME)) {
649
- return NodeFilter.FILTER_REJECT;
650
- }
651
- if (element.hasAttribute(EventManager.attrAttrName)) {
652
- const script = element.getAttribute(EventManager.attrAttrName) ?? '';
653
- // console.log('scriptscriptscriptscriptscriptscript,', script)
654
- const keyValuePairs = Array.from(script.matchAll(/(\w+):\s*([^,}]+)/g)).map(match => ({key: match[1], value: match[2]}));
655
- (keyValuePairs ?? []).forEach(it => {
656
- element.setAttribute(it.key, '${' + it.value + '}$')
657
- })
658
- // console.log('-------k', keyValuePairs)
659
-
660
- // const drAttr = ScriptUtils.evalReturn(script, obj)
661
- // Object.entries(drAttr).forEach(([key, value]) => {
662
- // const keyValuePairs = Array.from(a.matchAll(/(\w+):\s*([^,}]+)/g)).map(match => ({ key: match[1], value: match[2] }));
663
- // console.log(keyValuePairs);
664
- // // 출력: [{ key: 'value', value: 'this.child.obj.name' }, { key: 'wow', value: 'this.ww' }, { key: 'zz', value: '22' }, { key: 'v', value: '"ee"' }]
665
- //
666
- // console.log('-----------------', key,value)
667
- // element.setAttribute(key, '${'+(value)+'}$');
668
- // })
669
- // EventManager.attrNames.filter(it => it in drAttr).forEach(it => {
670
- // if (drAttr[it] === null) {
671
- // element.removeAttribute(it);
672
- // } else {
673
- // element.setAttribute(it, drAttr[it]);
674
- // }
675
- // })
676
- // console.log('-------->', Array.from(element.attributes), element.getAttribute('dr-attr'), obj)
677
- }
678
- // element.setAttribute('dr-event-click', 'console.log(11)');
679
- const targetElementIs = element.getAttribute(RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME);
680
- const targetElementNames = config.targetElements?.map(it => it.name.toLowerCase()) ?? [];
681
- const isElement = targetElementNames.includes(element.tagName.toLowerCase()) || targetElementNames.includes(targetElementIs?.toLowerCase() as any);
682
- // if (isElement) {
683
- // (element as HTMLElement).style.display = 'none';
684
- // (element as HTMLElement).style.width = '100px';
685
- // (element as HTMLElement).style.height = '100px';
686
- // console.log((element as HTMLElement).outerHTML)
687
- // }
688
- // console.log('------targetElementIstargetElementIs>', targetElementNames, '---', isElement, targetElementIs);
689
- // const targetAttrNames = (config.targetAttrs?.map(it => it.name) ?? []).concat([...RawSet.DR_ATTRIBUTES,...EventManager.RAWSET_CHECK_ATTRIBUTE]);
690
- const targetAttrNames = (config.targetAttrs?.map(it => it.name) ?? []).concat([...RawSet.DR_ATTRIBUTES]);
691
- const normalAttrs = new Map<string, string>();
692
- const linkVariables = new Map<string, string>();
693
- const linkNames = EventManager.linkAttrs.map(it => it.name);
694
- const isAttr = element.getAttributeNames().filter(it => {
781
+ // let html = element instanceof DocumentFragment ? ElementUtils.toInnerHTML(element, {document: config.window.document}) : (element as HTMLElement).outerHTML;
782
+ // console.log('==============html-->', element, html);
783
+ const NodeFilter = (config.window as any).NodeFilter;
784
+ const Node = (config.window as any).Node;
785
+ const processedNodes = new Set<Node>();
786
+
787
+ const findNodes = NodeUtils.findNodes(element, node => {
788
+ // console.log('nodeType', node.nodeType, node, (node as any).tagName, (node as any).data);
789
+ // for (const processedNode of processedNodes) {
790
+ // console.log('pre check!!', Array.from(processedNodes),processedNode !== node , processedNode.contains(node));
791
+ // // if(processedNode.contains(node)){
792
+ // console.log('---prechecker--html', (processedNode as HTMLElement).outerHTML,'------', (node as HTMLElement).outerHTML);
793
+ // // }
794
+ // if (processedNode !== node && processedNode.contains(node)) {
795
+ // console.log('acceptNodeReturn contain', NodeFilter.FILTER_REJECT);
796
+ // return NodeFilter.FILTER_REJECT;
797
+ // }
798
+ // }
799
+
800
+ if (node.nodeType === Node.TEXT_NODE) {
801
+ // console.log('nodeText--->', node.textContent)
802
+ // console.log('????????', node.parentElement, node.parentElement?.getAttribute('dr-pre'));
803
+ // console.log('???????/',node.textContent, node.parentElement?.getAttribute('dr-pre'))
804
+ // TODO: 나중에
805
+ // const between = StringUtils.betweenRegexpStr('[$#]\\{', '\\}', StringUtils.deleteEnter((node as Text).data ?? ''))
806
+ const between = RawSet.expressionGroups(StringUtils.deleteEnter((node as Text).data ?? ''));
807
+ // console.log('bbbb', between)
808
+ const r =
809
+ between?.length > 0
810
+ ? NodeUtils.FindNodesFilterResult.MATCH_AND_SKIP_CHILDREN
811
+ : NodeUtils.FindNodesFilterResult.NO_MATCH_AND_SKIP_CHILDREN;
812
+ // console.log('acceptNodeReturn node', r);
813
+ return r;
814
+ // return /\$\{.*?\}/g.test(StringUtils.deleteEnter((node as Text).data ?? '')) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
815
+ // return /[$#]\{.*?\}/g.test(StringUtils.deleteEnter((node as Text).data ?? '')) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
816
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
817
+ const element = node as Element;
818
+ // if (typeof Window === 'undefined' && element.getAttribute('ttt') === 'visual') {
819
+ // return NodeFilter.FILTER_REJECT;
820
+ // }
821
+ // console.log('nodeHTML-->', element.outerHTML);
822
+ if (element.hasAttribute(RawSet.DR_PRE_NAME)) {
823
+ let r = NodeUtils.FindNodesFilterResult.NO_MATCH_AND_SKIP_CHILDREN;
824
+ // console.log('acceptNodeReturn', r);
825
+ return r;
826
+ }
827
+ if (element.hasAttribute(EventManager.attrAttrName)) {
828
+ const script = element.getAttribute(EventManager.attrAttrName) ?? '';
829
+ // console.log('scriptscriptscriptscriptscriptscript,', script)
830
+ const keyValuePairs = Array.from(script.matchAll(/(\w+):\s*([^,}]+)/g)).map(match => ({
831
+ key: match[1],
832
+ value: match[2]
833
+ }));
834
+ (keyValuePairs ?? []).forEach(it => {
835
+ element.setAttribute(it.key, '${' + it.value + '}$');
836
+ });
837
+ }
838
+ // element.setAttribute('dr-event-click', 'console.log(11)');
839
+ const targetElementIs = element.getAttribute(RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME);
840
+ const targetElementNames = config.targetElements?.map(it => it.name.toLowerCase()) ?? [];
841
+ const isElement =
842
+ targetElementNames.includes(element.tagName.toLowerCase()) ||
843
+ targetElementNames.includes(targetElementIs?.toLowerCase() as any);
844
+ // if (isElement) {
845
+ // (element as HTMLElement).style.display = 'none';
846
+ // (element as HTMLElement).style.width = '100px';
847
+ // (element as HTMLElement).style.height = '100px';
848
+ // console.log((element as HTMLElement).outerHTML)
849
+ // }
850
+ // console.log('------targetElementIstargetElementIs>', targetElementNames, '---', isElement, targetElementIs);
851
+ // const targetAttrNames = (config.targetAttrs?.map(it => it.name) ?? []).concat([...RawSet.DR_ATTRIBUTES,...EventManager.RAWSET_CHECK_ATTRIBUTE]);
852
+ const targetAttrNames = (config.targetAttrs?.map(it => it.name) ?? []).concat([...RawSet.DR_ATTRIBUTES]);
853
+ const normalAttrs = new Map<string, NormalAttrDataType>();
854
+ const linkVariables = new Map<string, string>();
855
+ const linkNames = EventManager.linkAttrs.map(it => it.name);
856
+ const isAttr =
857
+ element.getAttributeNames().filter(it=>!EventManager.noDetectAttr.includes(it)).filter(it => {
695
858
  const value = element.getAttribute(it);
696
859
 
697
860
  // link일때
698
861
  if (value && linkNames.includes(it)) {
699
862
  linkVariables.set(it, value);
700
- } else if (value && RawSet.isExpression(value)) { // 표현식있을떄
701
- let variablePath: string = RawSet.expressionGroups(value)[0][1];
702
- // console.log('0-----',variablePath, node);
863
+ } else if (value && RawSet.isExpression(value)) {
864
+ // 표현식있을떄
865
+ const variablePaths: { origin: string; inner: string }[] = RawSet.expressionGroups(value).map(it => ({
866
+ origin: it[0],
867
+ inner: it[1]
868
+ }));
703
869
  // normal Attribute 초반에 셋팅해주기.
704
870
  // TODO: 이거 하긴했는데 사이드 이팩트?
705
- const originVariable = variablePath
706
- variablePath = variablePath.replace(/#[^#]*#/g, '({})');
707
- // console.log('1-----',variablePath, node);
708
- const optionalChainPath = ObjectUtils.Path.toOptionalChainPath(variablePath);
709
- // console.log('2-----',optionalChainPath);
710
- const cval = ScriptUtils.evaluateReturn(optionalChainPath, Object.assign(obj));
711
- // const cval = ScriptUtils.evalReturn(variablePath, Object.assign(obj));
871
+ // let variablePath: string = RawSet.expressionGroups(value)[0][1];
872
+ // const originVariable = variablePath;
873
+ // variablePath = variablePath.replace(/#[^#]*#/g, '({})');
874
+ // const optionalChainPath = ObjectUtils.Path.toOptionalChainPath(variablePath);
875
+ // const cval = ObjectUtils.Script.evaluateReturn(optionalChainPath, Object.assign(obj));
876
+
877
+ let targetScript = value;
878
+ variablePaths.forEach(it => {
879
+ let r = it.inner.replace(/#[^#]*#/g, '({})');
880
+ r = ObjectUtils.Path.toOptionalChainPath(r);
881
+ targetScript = targetScript.replaceAll(it.origin, `\${${r}}`);
882
+ });
883
+ const cval = ObjectUtils.Script.evaluateReturn('`' + targetScript + '`', Object.assign(obj));
884
+
712
885
  if (cval === null) {
713
886
  element.removeAttribute(it);
714
887
  } else {
715
888
  element.setAttribute(it, cval);
716
889
  }
717
- normalAttrs.set(it, originVariable);
890
+ normalAttrs.set(it, { originalAttrValue: value, variablePaths: variablePaths });
891
+ // normalAttrs.set(it, originVariable);
718
892
  // console.log('normalAttribute', it, variablePath);
719
893
  }
720
894
  // console.log(element.getAttribute(it), attrExpresion);
@@ -723,7 +897,10 @@ export class RawSet {
723
897
  }).length > 0;
724
898
 
725
899
  if (linkVariables.size) {
726
- element.setAttribute(EventManager.linkTargetMapAttrName, JSON.stringify(Array.from(linkVariables.entries())));
900
+ element.setAttribute(
901
+ EventManager.linkTargetMapAttrName,
902
+ JSON.stringify(Array.from(linkVariables.entries()))
903
+ );
727
904
  }
728
905
  // 기본 attribute를 처리하기위해
729
906
  if (normalAttrs.size) {
@@ -732,16 +909,27 @@ export class RawSet {
732
909
  // if (isElement) {
733
910
  // element.setAttribute('www', '@this@');
734
911
  // }
735
- const r = (isAttr || isElement) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
912
+ const r = isAttr || isElement ? NodeUtils.FindNodesFilterResult.MATCH_AND_SKIP_CHILDREN : NodeUtils.FindNodesFilterResult.NO_MATCH_AND_CONTINUE;
913
+ // console.log('acceptNodeReturn element', r);
736
914
  return r;
737
915
  }
738
- return NodeFilter.FILTER_REJECT;
916
+ const r = NodeUtils.FindNodesFilterResult.NO_MATCH_AND_CONTINUE;
917
+ // console.log('acceptNodeReturn nothing', r);
918
+ return r;
739
919
  }
740
- });
920
+ )
921
+
741
922
  const pars: RawSet[] = [];
742
923
  let currentNode: Node | null;
924
+ const name = RandomUtils.uuid();
925
+ // console.log('name==', name);
743
926
  // eslint-disable-next-line no-cond-assign
744
- while (currentNode = nodeIterator?.nextNode()) {
927
+ // while ((currentNode = nodeIterator?.nextNode())) {
928
+ // console.log('findNodes~~', findNodes);
929
+ for (const currentNode of findNodes) {
930
+ // 여기에서 부모인거 인지시켜준다 위쪽 에서 다시찾을떄 걸러진다.. JSDOM ..이놈이 즉각적인 처리를 못해줘서 수동 검증 로직 넣었다.
931
+ processedNodes.add(currentNode);
932
+ // console.log('currentNode!!!!', currentNode);
745
933
  if (currentNode.nodeType === Node.TEXT_NODE) {
746
934
  const text = (currentNode as Text).textContent ?? '';
747
935
  const template = config.window.document?.createElement('template');
@@ -750,7 +938,12 @@ export class RawSet {
750
938
  // const a = StringUtils.regexExec(/[$#]\{.*?\}/g, text);
751
939
  // const a = StringUtils.betweenRegexpStr('[$#]\\{', '\\}', text); // <--TODO: 나중에..
752
940
  const groups = RawSet.expressionGroups(text);
753
- const map = groups.map(it => ({uuid: `${RandomUtils.alphabet(40)}_${obj?.constructor?.name}`, content: it[0], regexArr: it}));
941
+ const map = groups.map(it => ({
942
+ uuid: `${RandomUtils.alphabet(40)}_${obj?.constructor?.name}`,
943
+ content: it[0],
944
+ regexArr: it
945
+ }));
946
+ // console.log('create!!',map);
754
947
  let lasterIndex = 0;
755
948
  for (let i = 0; i < map.length; i++) {
756
949
  const it = map[i];
@@ -769,8 +962,8 @@ export class RawSet {
769
962
  } else {
770
963
  type = RawSetType.TEXT;
771
964
  }
772
- const node = document.createTextNode(preparedText);
773
- const startEndPoint = RawSet.createStartEndPoint({id: it.uuid, type}, config);
965
+ const node = config.window.document.createTextNode(preparedText);
966
+ const startEndPoint = RawSet.createStartEndPoint({ id: it.uuid, type }, config);
774
967
  // layout setting
775
968
  // console.log('createTextNode', node);
776
969
  template.content.append(node); // expression 앞 부분 넣어줘야 앞부분 일반 text 안짤린다.
@@ -781,13 +974,20 @@ export class RawSet {
781
974
  const fragment = config.window.document.createDocumentFragment();
782
975
  fragment.append(config.window.document.createTextNode(it.content));
783
976
  // (startEndPoint.start as any).khh = RandomUtils.decimal(0,10)
784
- pars.push(new RawSet(it.uuid, type, {
785
- start: startEndPoint.start,
786
- node: currentNode,
787
- end: startEndPoint.end,
788
- parent: currentNode.parentNode,
789
- // thisVariableName: thisVariableName
790
- }, {fragment: fragment, config: config}));
977
+ pars.push(
978
+ new RawSet(
979
+ it.uuid,
980
+ type,
981
+ {
982
+ start: startEndPoint.start,
983
+ node: currentNode,
984
+ end: startEndPoint.end,
985
+ parent: currentNode.parentNode
986
+ // thisVariableName: thisVariableName
987
+ },
988
+ { fragment: fragment, config: config }
989
+ )
990
+ );
791
991
  lasterIndex = regexArr.index + it.content.length;
792
992
  }
793
993
  template.content.append(config.window.document.createTextNode(text.substring(lasterIndex, text.length)));
@@ -796,13 +996,16 @@ export class RawSet {
796
996
  // const uuid = `${RandomUtils.alphabet(40)}___${obj?.constructor?.name}`;
797
997
  const uuid = `${RandomUtils.alphabet(40)}`;
798
998
  const element = currentNode as Element;
999
+ // console.log('create ElementTarget', uuid, element.outerHTML);
799
1000
  const fragment = config.window.document.createDocumentFragment();
800
1001
  const elementType: RawSetType = RawSetType.TARGET_ELEMENT;
801
- const startEndPoint = RawSet.createStartEndPoint({node: element, id: uuid, type: elementType}, config);
1002
+ const startEndPoint = RawSet.createStartEndPoint({ node: element, id: uuid, type: elementType }, config);
802
1003
  // 여기서 등록한 component 추가한다.
803
1004
  const targetElementIs = element.getAttribute(RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME);
804
1005
  const targetElementNames = config.targetElements?.map(it => it.name.toLowerCase()) ?? [];
805
- const isElement = targetElementNames.includes(element.tagName.toLowerCase()) || targetElementNames.includes(targetElementIs?.toLowerCase() as any);
1006
+ const isElement =
1007
+ targetElementNames.includes(element.tagName.toLowerCase()) ||
1008
+ targetElementNames.includes(targetElementIs?.toLowerCase() as any);
806
1009
  // if (isElement) {
807
1010
  // (element as HTMLElement).style.display = 'none'
808
1011
  // }
@@ -816,21 +1019,49 @@ export class RawSet {
816
1019
  // tempDiv.appendChild(fragment.cloneNode(true)); // fragment 복사본 추가
817
1020
  // console.log('------',tempDiv.innerHTML);
818
1021
  // console.log();
819
- const rawSet = new RawSet(uuid, isElement ? elementType : (isAttr ? RawSetType.TARGET_ATTR : RawSetType.UNKOWN), {
820
- start: startEndPoint.start,
821
- node: currentNode,
822
- end: startEndPoint.end,
823
- parent: currentNode.parentNode,
824
- // thisVariableName: thisVariableName
825
- }, {config: config, fragment: fragment});
1022
+ const rawSet = new RawSet(
1023
+ uuid,
1024
+ isElement ? elementType : isAttr ? RawSetType.TARGET_ATTR : RawSetType.UNKOWN,
1025
+ {
1026
+ start: startEndPoint.start,
1027
+ node: currentNode,
1028
+ end: startEndPoint.end,
1029
+ parent: currentNode.parentNode
1030
+ // thisVariableName: thisVariableName
1031
+ },
1032
+ { config: config, fragment: fragment }
1033
+ );
826
1034
  pars.push(rawSet);
827
1035
  }
828
1036
  }
829
- // console.log('parsparsparsparsparsparsparsparsparspars', pars);
1037
+ // config
1038
+ const util = ElementUtils;
1039
+ // console.log('parsparsparsparsparsparsparsparsparspars', pars, name);
830
1040
  return pars;
1041
+ // const lastpars: RawSet[] = []
1042
+ //
1043
+ // pars.forEach(it => {
1044
+ // // it.uuid
1045
+ // const parents = pars.filter(it => it.dataSet.fragment.getElementById(it.uuid+'-start'))
1046
+ //
1047
+ // console.log('vvvvvvvvv', parents);
1048
+ // if (parents.length>0) {
1049
+ // parents.forEach(sit => {
1050
+ // sit.dataSet.fragment.getElementById(sit.uuid + '-start')?.replaceWith(it.dataSet.fragment);
1051
+ // it.dataSet.fragment.getElementById(sit.uuid + '-end').remove();
1052
+ // console.log('rrr');
1053
+ // // ElementUtils.toInnerHTML(it.dataSet.fragment, {document: config.window.document});
1054
+ // // ElementUtils.toInnerHTML(it.dataSet.fragment
1055
+ // });
1056
+ // } else {
1057
+ // lastpars.push(it)
1058
+ // }
1059
+ // })
1060
+ // console.log('zzzzzz', lastpars);
1061
+ // return lastpars;
831
1062
  }
832
1063
 
833
- public static createStartEndPoint(data: { node?: Node, id: string, type: RawSetType }, config: DomRenderConfig) {
1064
+ public static createStartEndPoint(data: { node?: Node; id: string; type: RawSetType }, config: DomRenderConfig) {
834
1065
  if (data.type === RawSetType.TARGET_ELEMENT && data.node) {
835
1066
  const element = data.node as Element;
836
1067
  const start: HTMLMetaElement = config.window.document.createElement('meta');
@@ -848,13 +1079,14 @@ export class RawSet {
848
1079
  }
849
1080
  end.setAttribute('id', `${data.id}-end`);
850
1081
  end.setAttribute('dr-end-point', '');
851
- return {start, end};
1082
+ return { start, end };
852
1083
  } else if (data.type === RawSetType.STYLE_TEXT) {
853
1084
  return {
854
1085
  start: config.window.document.createTextNode(`/*start text ${data.id}*/`),
855
1086
  end: config.window.document.createTextNode(`/*end text ${data.id}*/`)
856
1087
  };
857
- } else { // text
1088
+ } else {
1089
+ // text
858
1090
  return {
859
1091
  start: config.window.document.createComment(`start text ${data.id}`),
860
1092
  end: config.window.document.createComment(`end text ${data.id}`)
@@ -894,7 +1126,7 @@ export class RawSet {
894
1126
 
895
1127
  public getHasRawSet(key: string) {
896
1128
  let rawSet: RawSet | undefined;
897
- this.childs((node) => {
1129
+ this.childs(node => {
898
1130
  const drKey = (node as Element).getAttribute?.(RawSet.DR_KEY_OPTIONNAME);
899
1131
  if (drKey && drKey === key) {
900
1132
  rawSet = (node as any).rawSet as RawSet;
@@ -906,32 +1138,44 @@ export class RawSet {
906
1138
  }
907
1139
 
908
1140
  public static drItOtherEncoding(element: Element | DocumentFragment, postFix?: string) {
909
-
910
1141
  const random = RandomUtils.uuid() + postFix;
911
1142
  const regex = /#it#/g;
912
- element.querySelectorAll(`[${RawSet.DR_IT_OPTIONNAME}], [${RawSet.DR_FOR_OF_NAME}], [${RawSet.DR_REPEAT_NAME}], [${RawSet.DR_APPENDER_NAME}]`).forEach(it => {
913
- it.innerHTML = it.innerHTML.replace(regex, random);
914
- });
1143
+ element
1144
+ .querySelectorAll(
1145
+ `[${RawSet.DR_IT_OPTIONNAME}], [${RawSet.DR_FOR_OF_NAME}], [${RawSet.DR_REPEAT_NAME}], [${RawSet.DR_APPENDER_NAME}]`
1146
+ )
1147
+ .forEach(it => {
1148
+ it.innerHTML = it.innerHTML.replace(regex, random);
1149
+ });
915
1150
  return random;
916
1151
  }
917
1152
 
918
1153
  public static drItOtherDecoding(element: Element | DocumentFragment, random: string) {
919
- element.querySelectorAll(`[${RawSet.DR_IT_OPTIONNAME}], [${RawSet.DR_FOR_OF_NAME}], [${RawSet.DR_REPEAT_NAME}], [${RawSet.DR_APPENDER_NAME}]`).forEach(it => {
920
- it.innerHTML = it.innerHTML.replace(RegExp(random, 'g'), '#it#');
921
- });
1154
+ element
1155
+ .querySelectorAll(
1156
+ `[${RawSet.DR_IT_OPTIONNAME}], [${RawSet.DR_FOR_OF_NAME}], [${RawSet.DR_REPEAT_NAME}], [${RawSet.DR_APPENDER_NAME}]`
1157
+ )
1158
+ .forEach(it => {
1159
+ it.innerHTML = it.innerHTML.replace(RegExp(random, 'g'), '#it#');
1160
+ });
922
1161
  }
923
1162
 
924
- public static drVarDecoding(element: Element, vars: { name: string, value: string, regex: RegExp, random: string }[]) {
1163
+ public static drVarDecoding(
1164
+ element: Element,
1165
+ vars: { name: string; value: string; regex: RegExp; random: string }[]
1166
+ ) {
925
1167
  element.querySelectorAll(`[${RawSet.DR_THIS_NAME}]`).forEach(it => {
926
- vars.filter(vit => vit.value && vit.name).forEach(vit => {
927
- it.innerHTML = it.innerHTML.replace(RegExp(vit.random, 'g'), vit.value);
928
- });
1168
+ vars
1169
+ .filter(vit => vit.value && vit.name)
1170
+ .forEach(vit => {
1171
+ it.innerHTML = it.innerHTML.replace(RegExp(vit.random, 'g'), vit.value);
1172
+ });
929
1173
  });
930
1174
  }
931
1175
 
932
- public static replaceInnerHTML(element: Element, config: { asIs: string | RegExp, toBe?: string }): string {
1176
+ public static replaceInnerHTML(element: Element, config: { asIs: string | RegExp; toBe?: string }): string {
933
1177
  const innerHTML = element.innerHTML;
934
- const tobe = config.toBe = config.toBe ?? RandomUtils.uuid();
1178
+ const tobe = (config.toBe = config.toBe ?? RandomUtils.uuid());
935
1179
  if (config.asIs instanceof RegExp) {
936
1180
  element.innerHTML = innerHTML.replace(config.asIs, config.toBe);
937
1181
  } else {
@@ -940,8 +1184,9 @@ export class RawSet {
940
1184
  return tobe;
941
1185
  }
942
1186
 
943
- public static drThisEncoding(element: Element, drThis: string, config: { asIs: RegExp, toBe?: string }): string {
944
- const thisRandom = config.toBe = config?.toBe ?? RandomUtils.uuid();
1187
+ public static drThisEncoding(element: Element, drThis: string, config: { asIs: RegExp; toBe?: string }): string {
1188
+ const thisRandom = (config.toBe = config?.toBe ?? RandomUtils.uuid());
1189
+ // console.log('rrrrrrrrrrrrr', thisRandom);
945
1190
  // const thisRegex = /(?<!(dr-|\.))this(?=.?)/g;
946
1191
  // const thisRegex = /[^(dr\-)]this(?=.?)/g;
947
1192
  // const thisRegex = /[^(dr\-)]this\./g;
@@ -956,66 +1201,85 @@ export class RawSet {
956
1201
  // console.log('rrrrrrrrand?', drThis,config);
957
1202
  let message = it.innerHTML;
958
1203
  // StringUtils.regexExec(/([^(dr\-)])?this(?=.?)/g, message).reverse().forEach(it => {
959
- StringUtils.regexExec(config.asIs, message).reverse().forEach(it => {
960
- message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ''}${drThis}`);
961
- });
1204
+ StringUtils.regexExec(config.asIs, message)
1205
+ .reverse()
1206
+ .forEach(it => {
1207
+ message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ''}${drThis}`);
1208
+ });
962
1209
  it.innerHTML = message;
963
1210
  });
964
1211
 
965
1212
  // console.log('changggg', element.innerHTML);
966
1213
  let message = element.innerHTML;
967
- StringUtils.regexExec(config.asIs, message).reverse().forEach(it => {
968
- message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ''}${drThis}`);
969
- });
1214
+ StringUtils.regexExec(config.asIs, message)
1215
+ .reverse()
1216
+ .forEach(it => {
1217
+ message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ''}${drThis}`);
1218
+ });
970
1219
  element.innerHTML = message;
971
1220
  return thisRandom;
972
1221
  }
973
1222
 
974
- public static drThisBindEncoding(element: Element, variable: RegExp, config: { config: DomRenderConfig, otherReplaceVariablePath?: string }) {
1223
+ public static drThisBindEncoding(
1224
+ element: Element,
1225
+ variable: RegExp,
1226
+ config: { config: DomRenderConfig; otherReplaceVariablePath?: string }
1227
+ ) {
975
1228
  element.querySelectorAll(`[${RawSet.DR_THIS_NAME}]`).forEach(eIt => {
976
1229
  let message = eIt.innerHTML;
977
1230
  // StringUtils.regexExec(/([^(dr\-)])?this(?=.?)/g, message).reverse().forEach(it => {
978
- StringUtils.regexExec(variable, message).reverse().forEach(it => {
979
- message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ''}${eIt.getAttribute(RawSet.DR_THIS_NAME)}`);
980
- });
1231
+ StringUtils.regexExec(variable, message)
1232
+ .reverse()
1233
+ .forEach(it => {
1234
+ message =
1235
+ message.substr(0, it.index) +
1236
+ message.substr(it.index).replace(it[0], `${it[1] ?? ''}${eIt.getAttribute(RawSet.DR_THIS_NAME)}`);
1237
+ });
981
1238
  eIt.innerHTML = message;
982
1239
  });
983
1240
 
984
-
985
1241
  const targetElements = config.config.targetElements ?? [];
986
- const targetElementNames = targetElements.map(it => it.name.replaceAll('.', '\\.').replaceAll(':', '\\:')).join(',');
1242
+ const targetElementNames = targetElements
1243
+ .map(it => it.name.replaceAll('.', '\\.').replaceAll(':', '\\:'))
1244
+ .join(',');
987
1245
  const thisRandom = RandomUtils.uuid();
1246
+ // console.log('thisRandom', thisRandom, variable);
988
1247
  element.querySelectorAll(targetElementNames).forEach(it => {
989
1248
  it.innerHTML = it.innerHTML.replace(variable, thisRandom);
990
1249
  });
991
1250
 
992
1251
  element.querySelectorAll(`[${RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME}]`).forEach(it => {
993
1252
  it.innerHTML = it.innerHTML.replace(variable, thisRandom);
994
- })
995
-
1253
+ });
996
1254
 
997
1255
  if (config.otherReplaceVariablePath) {
998
1256
  let message = element.innerHTML;
999
- StringUtils.regexExec(variable, message).reverse().forEach(it => {
1000
- message = message.substr(0, it.index) + message.substr(it.index).replace(it[0], `${it[1] ?? ''}${config.otherReplaceVariablePath}`);
1001
- });
1257
+ StringUtils.regexExec(variable, message)
1258
+ .reverse()
1259
+ .forEach(it => {
1260
+ message =
1261
+ message.substr(0, it.index) +
1262
+ message.substr(it.index).replace(it[0], `${it[1] ?? ''}${config.otherReplaceVariablePath}`);
1263
+ });
1002
1264
  element.innerHTML = message;
1003
1265
  }
1004
1266
  return thisRandom;
1005
1267
  }
1006
1268
 
1007
- public static drThisBindDecoding(element: Element, config: { asIs: string, toBe: string, config: DomRenderConfig }) {
1269
+ public static drThisBindDecoding(element: Element, config: { asIs: string; toBe: string; config: DomRenderConfig }) {
1008
1270
  const targetElements = config.config.targetElements ?? [];
1009
- const targetElementNames = targetElements.map(it => it.name.replaceAll('.', '\\.').replaceAll(':', '\\:')).join(',');
1271
+ const targetElementNames = targetElements
1272
+ .map(it => it.name.replaceAll('.', '\\.').replaceAll(':', '\\:'))
1273
+ .join(',');
1010
1274
  element.querySelectorAll(targetElementNames).forEach(it => {
1011
1275
  it.innerHTML = it.innerHTML.replace(RegExp(config.asIs, 'g'), config.toBe);
1012
1276
  });
1013
1277
  element.querySelectorAll(`[${RawSet.DR_REPLACE_TARGET_ELEMENT_IS_NAME}]`).forEach(it => {
1014
1278
  it.innerHTML = it.innerHTML.replace(RegExp(config.asIs, 'g'), config.toBe);
1015
- })
1279
+ });
1016
1280
  }
1017
1281
 
1018
- public static drThisDecoding(element: Element, config: { asIs: string, toBe: string }) {
1282
+ public static drThisDecoding(element: Element, config: { asIs: string; toBe: string }) {
1019
1283
  element.querySelectorAll(`[${RawSet.DR_PRE_NAME}]`).forEach(it => {
1020
1284
  it.innerHTML = it.innerHTML.replace(RegExp(config.asIs, 'g'), config.toBe);
1021
1285
  });
@@ -1039,7 +1303,7 @@ export class RawSet {
1039
1303
 
1040
1304
  let node;
1041
1305
  // eslint-disable-next-line no-cond-assign
1042
- while (node = nodeIterator?.nextNode()) {
1306
+ while ((node = nodeIterator?.nextNode())) {
1043
1307
  const element = node as Element;
1044
1308
  element.setAttribute(to, element.getAttribute(as) ?? '');
1045
1309
  element.removeAttribute(as);
@@ -1063,21 +1327,34 @@ export class RawSet {
1063
1327
  // console.log('asd', element.innerHTML);
1064
1328
  // element.querySelectorAll(`[${RawSet.DR_THIS_NAME}]`).forEach(it => {
1065
1329
  element.querySelectorAll(`[${RawSet.DR_VAR_OPTIONNAME}]`).forEach(it => {
1066
- vars.filter(vit => vit.value && vit.name).forEach(vit => {
1067
- it.innerHTML = it.innerHTML.replace(vit.regex, vit.random);
1068
- });
1069
- });
1070
- vars.filter(vit => vit.value && vit.name).forEach(vit => {
1071
- element.innerHTML = element.innerHTML.replace(vit.regex, vit.value);
1330
+ vars
1331
+ .filter(vit => vit.value && vit.name)
1332
+ .forEach(vit => {
1333
+ it.innerHTML = it.innerHTML.replace(vit.regex, vit.random);
1334
+ });
1072
1335
  });
1336
+ vars
1337
+ .filter(vit => vit.value && vit.name)
1338
+ .forEach(vit => {
1339
+ element.innerHTML = element.innerHTML.replace(vit.regex, vit.value);
1340
+ });
1073
1341
  return vars;
1074
1342
  }
1075
1343
 
1076
- public static async drThisCreate(rawSet: RawSet, element: Element, drThis: string, drVarOption: string, drStripOption: boolean | string | null, obj: any, config: DomRenderConfig, set?: ComponentSet): Promise<DocumentFragment|undefined> {
1344
+ public static async drThisCreate(
1345
+ rawSet: RawSet,
1346
+ element: Element,
1347
+ drThis: string,
1348
+ drVarOption: string,
1349
+ drStripOption: boolean | string | null,
1350
+ obj: any,
1351
+ config: DomRenderConfig,
1352
+ set?: ComponentSet
1353
+ ): Promise<DocumentFragment | undefined> {
1077
1354
  // console.log('ttttttttttttttttttttt',element.innerHTML, drThis, set, obj);
1078
1355
  const fag = config.window.document?.createDocumentFragment();
1079
- if(!fag) {
1080
- return ;
1356
+ if (!fag) {
1357
+ return;
1081
1358
  }
1082
1359
  const targetElement = element.cloneNode(true) as Element;
1083
1360
  let targetObj = obj;
@@ -1087,7 +1364,7 @@ export class RawSet {
1087
1364
  const style = RawSet.generateStyleTransform(set.styles ?? [], rawSet.uuid, true);
1088
1365
  targetElement.innerHTML = style + (set.template ?? '');
1089
1366
  } else {
1090
- targetObj = ScriptUtils.evaluateReturn(ObjectUtils.Path.toOptionalChainPath(drThis), obj);
1367
+ targetObj = ObjectUtils.Script.evaluateReturn(ObjectUtils.Path.toOptionalChainPath(drThis), obj);
1091
1368
  }
1092
1369
 
1093
1370
  const componentKey = rawSet.uuid;
@@ -1133,12 +1410,15 @@ export class RawSet {
1133
1410
  scripts: EventManager.setBindProperty(config.scripts ?? {}, obj)
1134
1411
  } as Render;
1135
1412
  // const attribute = DomUtils.getAttributeToObject(element);
1136
- render.attribute = RawSet.getAttributeObject(element, {script: renderScript, obj: obj, renderData: render})
1413
+ render.attribute = RawSet.getAttributeObject(element, { script: renderScript, obj: obj, renderData: render });
1137
1414
  render = Object.freeze(render);
1138
1415
 
1139
1416
  // dr-on-create data onCreateRender
1140
1417
  const onCreateDataScript = `return {rootParent: this, render: this.__render}`;
1141
- const onCreateDataParam = ScriptUtils.evaluate<OnCreateRenderDataParams>(onCreateDataScript, Object.assign(obj, {__render: render}));
1418
+ const onCreateDataParam = ObjectUtils.Script.evaluate<OnCreateRenderDataParams>(
1419
+ onCreateDataScript,
1420
+ Object.assign(obj, { __render: render })
1421
+ );
1142
1422
  if (isOnCreateRenderData(targetObj)) {
1143
1423
  targetObj?.onCreateRenderData(onCreateDataParam as OnCreateRenderDataParams);
1144
1424
  }
@@ -1147,12 +1427,14 @@ export class RawSet {
1147
1427
  onCreateDataParam.render.parentThis.onCreatedThisChild(targetObj, onCreateDataParam as OnCreateRenderDataParams);
1148
1428
  }
1149
1429
 
1150
-
1151
1430
  // dr-on-create onCreateRender
1152
1431
  const onCreate = element.getAttribute(RawSet.DR_ON_CREATE_ARGUMENTS_OPTIONNAME);
1153
1432
  let createParam: any[] = [];
1154
1433
  if (onCreate) {
1155
- createParam = ScriptUtils.evaluateReturn<any[]>({bodyScript:renderScript, returnScript:ObjectUtils.Path.toOptionalChainPath(onCreate)}, obj)
1434
+ createParam = ObjectUtils.Script.evaluateReturn<any[]>(
1435
+ { bodyScript: renderScript, returnScript: ObjectUtils.Path.toOptionalChainPath(onCreate) },
1436
+ obj
1437
+ );
1156
1438
  if (!Array.isArray(createParam)) {
1157
1439
  createParam = [createParam];
1158
1440
  }
@@ -1165,7 +1447,7 @@ export class RawSet {
1165
1447
  // console.log('매번타나?');
1166
1448
  // 중요 dr-normal-attr-map
1167
1449
  // const normalAttrMap = element.getAttribute(EventManager.normalAttrMapAttrName);
1168
- const targetAttrObject = RawSet.getAttributeObject(element, {script: renderScript, obj: obj, renderData: render});
1450
+ const targetAttrObject = RawSet.getAttributeObject(element, { script: renderScript, obj: obj, renderData: render });
1169
1451
  if (targetAttrObject) {
1170
1452
  rawSet.dataSet.render ??= {};
1171
1453
  rawSet.dataSet.render.attribute = targetAttrObject;
@@ -1175,19 +1457,18 @@ export class RawSet {
1175
1457
  // const cval = ScriptUtils.eval(script, Object.assign(obj, { __render: render }));
1176
1458
  // // element.setAttribute(key, cval);
1177
1459
  if (isOnChangeAttrRender(targetObj)) {
1178
- targetObj.onChangeAttrRender(key, cval, {rawSet: rawSet});
1460
+ targetObj.onChangeAttrRender(key, cval, { rawSet: rawSet });
1179
1461
  }
1180
1462
  });
1181
1463
  }
1182
1464
 
1183
-
1184
1465
  // dr-on-component-init
1185
1466
  // const oninit = element.getAttribute(`${EventManager.attrPrefix}on-component-init`); // dr-on-component-init
1186
1467
  const oninit = element.getAttribute(RawSet.DR_ON_CREATED_CALLBACK_OPTIONNAME); // dr-on-component-init
1187
1468
  // console.log('--------drThisCreate!!!', oninit)
1188
1469
  if (oninit) {
1189
1470
  const script = `${renderScript} ${oninit} `;
1190
- ScriptUtils.evaluate(script, Object.assign(obj, {__render: render}));
1471
+ ObjectUtils.Script.evaluate(script, Object.assign(obj, { __render: render }));
1191
1472
  }
1192
1473
 
1193
1474
  targetElement.querySelectorAll(EventManager.attrNames.map(it => `[${it}]`).join(',')).forEach(it => {
@@ -1197,7 +1478,7 @@ export class RawSet {
1197
1478
  // console.log('targetElement',targetElement);
1198
1479
  // attribute
1199
1480
  // const componentName = element.getAttribute(RawSet.DR_COMPONENT_NAME_OPTIONNAME) ?? 'component';
1200
- const componentNameReplaceKey = RandomUtils.uuid();
1481
+ // const componentNameReplaceKey = RandomUtils.uuid();
1201
1482
  // if (componentName) {
1202
1483
  // RawSet.replaceInnerHTML(element, {asIs: `#${componentName}#`, toBe: 'this'})
1203
1484
  // }
@@ -1206,18 +1487,46 @@ export class RawSet {
1206
1487
  // if (innerHTMLName) {
1207
1488
  // RawSet.replaceInnerHTML(element, {asIs: `#${innerHTMLName}#`, toBe: innerHTMLNameReplaceKey})
1208
1489
  // }
1490
+
1491
+ rawSet.point.innerHTML = element.innerHTML;
1492
+ const innerText = element.textContent?.trim() ?? '';
1493
+ const escapedInnerHTML = ConvertUtils.escapeHTML(element.innerHTML);
1209
1494
  // 이걸 왜 뺐었지... 다시넣었음 그런데 조금 로직이.. 검증이..
1210
- const innerHTMLName = targetElement.getAttribute(RawSet.DR_COMPONENT_INNER_HTML_NAME_OPTIONNAME) ?? 'innerHTML';
1495
+ const innerHTMLName = targetElement.getAttribute(RawSet.DR_INNER_HTML_NAME_OPTIONNAME) ?? 'innerHTML';
1496
+ const innerTEXTName = targetElement.getAttribute(RawSet.DR_INNER_TEXT_NAME_OPTIONNAME) ?? 'innerTEXT';
1497
+ const innerHTMLEscapedName = targetElement.getAttribute(RawSet.DR_INNER_HTML_ESCAPED_NAME_OPTIONNAME) ?? 'innerHTMLEscaped';
1498
+ const templateReplacements: StringUtils.SequentialReplacement[] = [];
1211
1499
  if (innerHTMLName) {
1212
- RawSet.replaceInnerHTML(targetElement, {asIs: `#${innerHTMLName}#`, toBe: element.innerHTML})
1500
+ templateReplacements.push({
1501
+ regex: new RegExp(`#${innerHTMLName}#`, 'g'),
1502
+ callback: () => element.innerHTML
1503
+ });
1504
+ }
1505
+ if (innerTEXTName) {
1506
+ templateReplacements.push({
1507
+ regex: new RegExp(`#${innerTEXTName}#`, 'g'),
1508
+ callback: () => innerText
1509
+ });
1510
+ }
1511
+ if (innerHTMLEscapedName) {
1512
+ templateReplacements.push({
1513
+ regex: new RegExp(`#${innerHTMLEscapedName}#`, 'g'),
1514
+ callback: () => escapedInnerHTML
1515
+ });
1516
+ }
1517
+
1518
+ if (templateReplacements.length > 0) {
1519
+ targetElement.innerHTML = StringUtils.replaceSequentially(targetElement.innerHTML, templateReplacements);
1213
1520
  }
1214
1521
 
1215
1522
  // console.log('aa-asIs', targetElement.innerHTML);
1216
1523
  const optionThisName = targetElement.getAttribute(RawSet.DR_THIS_NAME_OPTIONNAME);
1217
1524
  // console.log('11111111111111', optionThisName)
1218
- targetElement.getAttributeNames().forEach(it => targetElement.setAttribute(it, targetElement.getAttribute(it)!.replace(/#this#/g, drThis)));
1219
- const thisRandom = this.drThisEncoding(targetElement, drThis, {asIs: /@this@/g});
1220
- // console.log('@@@@@@@@@@@@@0', targetElement.innerHTML);
1525
+ targetElement
1526
+ .getAttributeNames()
1527
+ .forEach(it => targetElement.setAttribute(it, targetElement.getAttribute(it)!.replace(/#this#/g, drThis)));
1528
+ const thisRandom = this.drThisEncoding(targetElement, drThis, { asIs: /@this@/g });
1529
+ // console.log('@@@@@@@@@@@@@0', thisRandom);
1221
1530
  // let thisNameRandom: string | undefined = undefined;
1222
1531
  if (optionThisName) {
1223
1532
  // console.log('-----0', element.innerHTML, '\n', targetElement.innerHTML)
@@ -1225,8 +1534,14 @@ export class RawSet {
1225
1534
  // console.log('-----1', element.innerHTML, '\n', targetElement.innerHTML)
1226
1535
  // thisNameRandom = this.drThisBindEncoding(targetElement, new RegExp(`@${optionThisName}@`, 'g'), {config: config, otherReplaceVariablePath: drThis});
1227
1536
  }
1228
- const nearThisRandom = this.drThisBindEncoding(targetElement, /@nearThis@/g, {config: config, otherReplaceVariablePath: rawSet.findNearThisPath()});
1229
- const parentThisRandom = this.drThisBindEncoding(targetElement, /@parentThis@/g, {config: config, otherReplaceVariablePath: rawSet.findParentThisPath()});
1537
+ const nearThisRandom = this.drThisBindEncoding(targetElement, /@nearThis@/g, {
1538
+ config: config,
1539
+ otherReplaceVariablePath: rawSet.findNearThisPath()
1540
+ });
1541
+ const parentThisRandom = this.drThisBindEncoding(targetElement, /@parentThis@/g, {
1542
+ config: config,
1543
+ otherReplaceVariablePath: rawSet.findParentThisPath()
1544
+ });
1230
1545
  // console.log('@@@@@@@@@@@@@1', targetElement.innerHTML, rawSet.findParentThisPath());
1231
1546
  // console.log('@@@@@@@@@@@@@-----------', rawSet.point?.parentRawSet?.point?.start, rawSet.point?.parentRawSet?.point?.start instanceof HTMLMetaElement);
1232
1547
  // if (rawSet.point?.parentRawSet?.point?.start instanceof HTMLMetaElement) {
@@ -1240,11 +1555,11 @@ export class RawSet {
1240
1555
  // console.log('------', rawSet.findParentThisPath());
1241
1556
  const vars = this.drVarEncoding(targetElement, drVarOption);
1242
1557
  this.drVarDecoding(targetElement, vars);
1243
- this.drThisDecoding(targetElement, {asIs: thisRandom, toBe: '@this@'});
1558
+ this.drThisDecoding(targetElement, { asIs: thisRandom, toBe: '@this@' });
1244
1559
  // if (optionThisName && thisNameRandom)
1245
1560
  // this.drThisBindDecoding(targetElement, {config: config, asIs: thisNameRandom, toBe: `@${optionThisName}@`});
1246
- this.drThisBindDecoding(targetElement, {config: config, asIs: nearThisRandom, toBe: '@nearThis@'});
1247
- this.drThisBindDecoding(targetElement, {config: config, asIs: parentThisRandom, toBe: '@parentThis@'});
1561
+ this.drThisBindDecoding(targetElement, { config: config, asIs: nearThisRandom, toBe: '@nearThis@' });
1562
+ this.drThisBindDecoding(targetElement, { config: config, asIs: parentThisRandom, toBe: '@parentThis@' });
1248
1563
  // if (componentName) {
1249
1564
  // RawSet.replaceInnerHTML(element, {asIs: componentNameReplaceKey, toBe: `#${componentName}#`})
1250
1565
  // }
@@ -1256,7 +1571,7 @@ export class RawSet {
1256
1571
  // console.log('------childNodes', Array.from(n.childNodes))
1257
1572
  Array.from(targetElement.childNodes).forEach(it => fag.append(it));
1258
1573
  } else {
1259
- targetElement.classList.add(`${rawSet.uuid}`)
1574
+ targetElement.classList.add(`${rawSet.uuid}`);
1260
1575
  fag.append(targetElement);
1261
1576
  }
1262
1577
  // (fag as any).__domrender_this_variable_name = drThis;
@@ -1264,10 +1579,13 @@ export class RawSet {
1264
1579
  return fag;
1265
1580
  }
1266
1581
 
1267
- private static async fetchTemplateStyle(set: { template?: string, styles?: string | (string[]) }) {
1582
+ private static async fetchTemplateStyle(set: { template?: string; styles?: string | string[] }) {
1268
1583
  // const id = RandomUtils.getRandomString(20);
1269
1584
  const stylePromises: Promise<string>[] = [];
1270
- const templatePromise = (set.template && set.template.startsWith('lazy://') ? (await fetch(set.template.substring(6))).text() : Promise.resolve(set.template));
1585
+ const templatePromise =
1586
+ set.template && set.template.startsWith('lazy://')
1587
+ ? (await fetch(set.template.substring(6))).text()
1588
+ : Promise.resolve(set.template);
1271
1589
  if (Array.isArray(set.styles)) {
1272
1590
  for (let i = 0; set.styles && i < (set.styles.length ?? 0); i++) {
1273
1591
  const it = set.styles[i];
@@ -1285,7 +1603,11 @@ export class RawSet {
1285
1603
  };
1286
1604
  }
1287
1605
 
1288
- public static createComponentTargetAttribute(name: string, getThisObj: (element: Element, attrValue: string, obj: any, rawSet: RawSet) => any, factory: (element: Element, attrValue: string, obj: any, rawSet: RawSet) => DocumentFragment) {
1606
+ public static createComponentTargetAttribute(
1607
+ name: string,
1608
+ getThisObj: (element: Element, attrValue: string, obj: any, rawSet: RawSet) => any,
1609
+ factory: (element: Element, attrValue: string, obj: any, rawSet: RawSet) => DocumentFragment
1610
+ ) {
1289
1611
  const targetAttribute: TargetAttr = {
1290
1612
  name,
1291
1613
  callBack(element: Element, attrValue: string, obj: any, rawSet: RawSet): DocumentFragment {
@@ -1302,35 +1624,42 @@ export class RawSet {
1302
1624
  }
1303
1625
  return data;
1304
1626
  }
1305
-
1306
1627
  };
1307
1628
  return targetAttribute;
1308
1629
  }
1309
1630
 
1310
- public static createComponentTargetElement(
1311
- {name, objFactory, template = '', styles = [], noStrip}: {
1312
- name: string,
1313
- noStrip?: boolean;
1314
- objFactory: (element: Element, obj: any, rawSet: RawSet, counstructorParam: any[]) => any,
1315
- template?: string,
1316
- styles?: string | (string[])
1317
- }
1318
- ): TargetElement {
1319
-
1631
+ public static createComponentTargetElement({
1632
+ name,
1633
+ objFactory,
1634
+ template = '',
1635
+ styles = [],
1636
+ noStrip
1637
+ }: {
1638
+ name: string;
1639
+ noStrip?: boolean;
1640
+ objFactory: (element: Element, obj: any, rawSet: RawSet, counstructorParam: any[]) => any;
1641
+ template?: string;
1642
+ styles?: string | string[];
1643
+ }): TargetElement {
1320
1644
  const targetElement: TargetElement = {
1321
1645
  name,
1322
1646
  styles,
1323
1647
  template,
1324
1648
  noStrip,
1325
- async callBack(element: Element, obj: any, rawSet: RawSet, attrs: Attrs, config: DomRenderConfig): Promise<DocumentFragment | undefined> {
1326
- const templateStyle = await RawSet.fetchTemplateStyle({template: this.template, styles: this.styles});
1649
+ async callBack(
1650
+ element: Element,
1651
+ obj: any,
1652
+ rawSet: RawSet,
1653
+ attrs: Attrs,
1654
+ config: DomRenderConfig
1655
+ ): Promise<DocumentFragment | undefined> {
1656
+ const templateStyle = await RawSet.fetchTemplateStyle({ template: this.template, styles: this.styles });
1327
1657
  this.template = templateStyle.template;
1328
1658
  this.styles = templateStyle.styles;
1329
1659
  obj.__domrender_components ??= {};
1330
1660
  const domrenderComponents = obj.__domrender_components;
1331
1661
  // debugger;
1332
1662
  const renderScript = ` /*createComponentTargetElement*/
1333
- // console.log('-------------------',this.__render);
1334
1663
  var ${EventManager.RAWSET_VARNAME} = this.__render.rawSet;
1335
1664
  var ${EventManager.COMPONENT_VARNAME} = this.__render.component;
1336
1665
  var ${EventManager.ELEMENT_VARNAME} = this.__render.element;
@@ -1365,21 +1694,24 @@ export class RawSet {
1365
1694
  const constructor = element.getAttribute(RawSet.DR_ON_CONSTRUCTOR_ARGUMENTS_OPTIONNAME);
1366
1695
  let constructorParam = [];
1367
1696
  // script 부분은 처리되어 바인딩 시켜준다
1368
- render.attribute = RawSet.getAttributeObject(element, {script: renderScript, obj: obj, renderData: render})
1697
+ render.attribute = RawSet.getAttributeObject(element, { script: renderScript, obj: obj, renderData: render });
1369
1698
  render = Object.freeze(render);
1370
1699
  //
1371
1700
  // // dr-constructor
1372
1701
  if (constructor) {
1373
- let param = ScriptUtils.evaluateReturn({bodyScript: renderScript, returnScript: ObjectUtils.Path.toOptionalChainPath(constructor)}, Object.assign(obj, {__render: render})) ?? [];
1702
+ let param =
1703
+ ObjectUtils.Script.evaluateReturn(
1704
+ { bodyScript: renderScript, returnScript: ObjectUtils.Path.toOptionalChainPath(constructor) },
1705
+ Object.assign(obj, { __render: render })
1706
+ ) ?? [];
1374
1707
  if (!Array.isArray(param)) {
1375
1708
  param = [param];
1376
1709
  }
1377
1710
  constructorParam = param;
1378
1711
  }
1379
1712
 
1380
-
1381
1713
  // // console.log('------22', attrs);
1382
- const instance = domrenderComponents[rawSet.uuid] = objFactory(element, obj, rawSet, constructorParam);
1714
+ const instance = (domrenderComponents[rawSet.uuid] = objFactory(element, obj, rawSet, constructorParam));
1383
1715
  render = {
1384
1716
  currentThis: instance,
1385
1717
  // creatorMetaData: i,
@@ -1401,7 +1733,7 @@ export class RawSet {
1401
1733
  // i.drAttrs = attrs;
1402
1734
  // i.innerHTML = element.innerHTML;
1403
1735
  // i.rootCreator = new Proxy(obj, new DomRenderFinalProxy());
1404
- // i.creator = new Proxy(rawSet.point.thisVariableName ? ScriptUtils.evalReturn(rawSet.point.thisVariableName, obj) : obj, new DomRenderFinalProxy());
1736
+ // i.creator = new Proxy(rawSet.point.thisVariableName ? ObjectUtils.Script.evalReturn(rawSet.point.thisVariableName, obj) : obj, new DomRenderFinalProxy());
1405
1737
  // this.__creatorMetaData = i;
1406
1738
  // render = {
1407
1739
  // component: instance,
@@ -1414,7 +1746,7 @@ export class RawSet {
1414
1746
  // if (isOnChangeAttrRender(instance) && normalAttrMap) {
1415
1747
  // new Map<string, string>(JSON.parse(normalAttrMap)).forEach((value, key) => {
1416
1748
  // const script = `${renderScript} return ${value} `;
1417
- // const cval = ScriptUtils.eval(script, Object.assign(obj, { __render: render }));
1749
+ // const cval = ObjectUtils.Script.eval(script, Object.assign(obj, { __render: render }));
1418
1750
  // // element.setAttribute(key, cval);
1419
1751
  // instance.onChangeAttrRender(key, cval);
1420
1752
  // });
@@ -1422,7 +1754,7 @@ export class RawSet {
1422
1754
  //
1423
1755
  // // dr-on-create data
1424
1756
  // const onCreateDataScript = `return {rootParent: this, render: this.__render}`;
1425
- // const onCreateDataParam = ScriptUtils.eval(onCreateDataScript, Object.assign(obj, { __render: render }));
1757
+ // const onCreateDataParam = ObjectUtils.Script.eval(onCreateDataScript, Object.assign(obj, { __render: render }));
1426
1758
  // if (isOnCreateRenderData(instance)) {
1427
1759
  // instance?.onCreateRenderData(onCreateDataParam);
1428
1760
  // }
@@ -1433,7 +1765,7 @@ export class RawSet {
1433
1765
  // let createParam = [];
1434
1766
  // if (onCreate) {
1435
1767
  // const script = `${renderScript} return ${onCreate} `;
1436
- // createParam = ScriptUtils.eval(script, Object.assign(obj, { __render: render }));
1768
+ // createParam = ObjectUtils.Script.eval(script, Object.assign(obj, { __render: render }));
1437
1769
  // if (!Array.isArray(createParam)) {
1438
1770
  // createParam = [createParam];
1439
1771
  // }
@@ -1442,25 +1774,58 @@ export class RawSet {
1442
1774
  // instance?.onCreateRender?.(...createParam);
1443
1775
  // }
1444
1776
  let applayTemplate = element.innerHTML;
1777
+ let applayTemplateText = element.textContent?.trim() ?? '';
1778
+ let applayTemplateEscape = ConvertUtils.escapeHTML(element.innerHTML);
1445
1779
  let innerHTMLThisRandom;
1446
- const componentName = element.getAttribute(RawSet.DR_COMPONENT_NAME_OPTIONNAME) ?? 'component';
1447
- const innerHTMLName = element.getAttribute(RawSet.DR_COMPONENT_INNER_HTML_NAME_OPTIONNAME) ?? 'innerHTML';
1780
+ const componentName = element.getAttribute(RawSet.DR_VARIABLE_NAME_OPTIONNAME) ?? 'component';
1781
+ const innerHTMLName = element.getAttribute(RawSet.DR_INNER_HTML_NAME_OPTIONNAME) ?? 'innerHTML';
1782
+ const innerTEXTName = element.getAttribute(RawSet.DR_INNER_TEXT_NAME_OPTIONNAME) ?? 'innerTEXT';
1783
+ const innerHTMLEscapedName = element.getAttribute(RawSet.DR_INNER_HTML_ESCAPED_NAME_OPTIONNAME) ?? 'innerHTMLEscaped';
1784
+
1785
+ // if (element.getAttribute(RawSet.DR_COMPONENT_VARIABLE_NAME_OPTIONNAME)) {
1786
+ // console.log('vvvvvvv', element.getAttribute(RawSet.DR_COMPONENT_VARIABLE_NAME_OPTIONNAME));
1787
+ // }
1448
1788
  if (applayTemplate) {
1449
1789
  // if (rawSet.point.thisVariableName) {
1450
1790
  // 넘어온 innerHTML에 this가 있으면 해당안되게 우선 치환.
1451
1791
  innerHTMLThisRandom = RandomUtils.uuid();
1452
- applayTemplate = applayTemplate.replace(/this\./g, innerHTMLThisRandom);
1792
+ applayTemplate = StringUtils.replaceSequentially(applayTemplate, [
1793
+ {
1794
+ regex: /this\./g,
1795
+ callback: () => innerHTMLThisRandom
1796
+ },
1797
+ {
1798
+ regex: new RegExp(`#${componentName}#`, 'g'),
1799
+ callback: () => nearThisPath
1800
+ }
1801
+ ]);
1453
1802
  // }
1454
- applayTemplate = applayTemplate.replace(RegExp(`#${componentName}#`, 'g'), 'this');
1803
+ // applayTemplate = applayTemplate.replace(RegExp(`#${componentName}#`, 'g'), 'this');
1455
1804
  }
1456
1805
  // applayTemplate = template.replace(RegExp(`#${innerHTMLName}#`, 'g'), applayTemplate);
1457
- applayTemplate = (this.template ?? '').replace(RegExp(`#${innerHTMLName}#`, 'g'), applayTemplate);
1806
+ // RawSet.replaceInnerHTML(
1807
+ // applayTemplate = StringUtils.regexExecArrayReplace(this.template, RegExp(`#${innerHTMLName}#`, 'g'), applayTemplate)
1808
+ // applayTemplate = StringUtils.regexExecArrayReplace(this.template, [RegExp(`#${innerHTMLName}#`, 'g')], applayTemplate)
1809
+ applayTemplate = StringUtils.replaceSequentially((this.template ?? ''), [
1810
+ {
1811
+ regex: new RegExp(`#${innerHTMLName}#`, 'g'),
1812
+ callback: () => applayTemplate
1813
+ },
1814
+ {
1815
+ regex: new RegExp(`#${innerTEXTName}#`, 'g'),
1816
+ callback: () => applayTemplateText
1817
+ },
1818
+ {
1819
+ regex: new RegExp(`#${innerHTMLEscapedName}#`, 'g'),
1820
+ callback: () => applayTemplateEscape
1821
+ }
1822
+ ]);
1458
1823
  // dr-on-component-init
1459
1824
  // const oninit = element.getAttribute(`${EventManager.attrPrefix}on-component-init`); // dr-on-component-init
1460
1825
  // const oninit = element.getAttribute(RawSet.DR_ON_CREATED_CALLBACK_OPTIONNAME); // dr-on-component-init
1461
1826
  // if (oninit) {
1462
1827
  // const script = `${renderScript} ${oninit} `;
1463
- // ScriptUtils.eval(script, Object.assign(obj, {
1828
+ // ObjectUtils.Script.eval(script, Object.assign(obj, {
1464
1829
  // __render: render
1465
1830
  // }));
1466
1831
  // }
@@ -1470,17 +1835,36 @@ export class RawSet {
1470
1835
 
1471
1836
  // 여기서 targetElement의 옷을 벗긴다.
1472
1837
  // console.log('---createComponentTargetElement', element);
1473
- let data = await RawSet.drThisCreate(rawSet, element, `this.__domrender_components.${rawSet.uuid}`, '', !noStrip, obj, config);
1838
+ let data = await RawSet.drThisCreate(
1839
+ rawSet,
1840
+ element,
1841
+ `this.__domrender_components.${rawSet.uuid}`,
1842
+ '',
1843
+ !noStrip,
1844
+ obj,
1845
+ config
1846
+ );
1474
1847
  // const tempDiv = document.createElement("div");
1475
1848
  // tempDiv.appendChild(data.cloneNode(true)); // 원본 보존
1476
1849
  // console.log('-------------ddddddddddddd', element.innerHTML, tempDiv.innerHTML);
1477
1850
  // let data = await RawSet.drThisCreate(rawSet, element, `this.__domrender_components.${componentKey}`, '', false, obj, config);
1478
1851
 
1479
1852
  // 넘어온 innerHTML에 this가 있는걸 다시 복호화해서 제대로 작동하도록한다. 부모에서의 this면 부모껄로 작동되게
1853
+ // console.log('!!!!!@', (data && innerHTMLThisRandom) ,innerHTMLThisRandom);
1480
1854
  if (data && innerHTMLThisRandom) {
1481
1855
  const template = config.window.document.createElement('template') as HTMLTemplateElement;
1482
- template.content.append(data);
1483
- template.innerHTML = template.innerHTML.replace(RegExp(innerHTMLThisRandom, 'g'), 'this.');
1856
+
1857
+ // console.log('------->', template.content);
1858
+ // 브라우저에서는 이게되는데 linkedom 에서는 안된다. 그래서 innerhtml로 처리함
1859
+ // template.content.append(data);
1860
+ // console.log('-------', template.innerHTML);
1861
+ // const d = config.window.document.createElement('div')
1862
+ // d.innerHTML='<a></a>'
1863
+ // console.log('-----XX', ElementUtils.toInnerHTML(data, {document: config.window.document}));
1864
+ // template.innerHTML = template.innerHTML.replace(RegExp(innerHTMLThisRandom, 'g'), 'this.');
1865
+ template.innerHTML = ElementUtils.toInnerHTML(data, {document: config.window.document}).replace(RegExp(innerHTMLThisRandom, 'g'), 'this.');;
1866
+ // console.log('ccc?', template.innerHTML);
1867
+ // template.innerHTML = '<div>zzzzzzz</div>'
1484
1868
  data = template.content;
1485
1869
  }
1486
1870
  // (data as any).render = render;
@@ -1504,7 +1888,12 @@ export class RawSet {
1504
1888
  return StringUtils.regexExec(reg, data ?? '');
1505
1889
  }
1506
1890
 
1507
- public static destroy(obj: any | undefined, parameter: OnDestroyRenderParams, config: DomRenderConfig, destroyOptions: (DestroyOptionType | string)[] = []): void {
1891
+ public static destroy(
1892
+ obj: any | undefined,
1893
+ parameter: OnDestroyRenderParams,
1894
+ config: DomRenderConfig,
1895
+ destroyOptions: (DestroyOptionType | string)[] = []
1896
+ ): void {
1508
1897
  // console.log('destroy destroydestroydestroydestroy', obj, parameter, config, destroyOptions);
1509
1898
  if (!destroyOptions.some(it => it === DestroyOptionType.NO_DESTROY)) {
1510
1899
  if (!destroyOptions.some(it => it === DestroyOptionType.NO_MESSENGER_DESTROY)) {
@@ -1519,13 +1908,12 @@ export class RawSet {
1519
1908
  }
1520
1909
  }
1521
1910
 
1522
-
1523
1911
  public findNearThis = (obj: any, rawSet: RawSet = this) => {
1524
1912
  const path = this.findNearThisPath(rawSet);
1525
1913
  if (path) {
1526
1914
  const optionalPath = ObjectUtils.Path.toOptionalChainPath(path);
1527
1915
  // console.log('ppppp-', path, optionalPath)
1528
- return ScriptUtils.evaluateReturn(optionalPath, obj);
1916
+ return ObjectUtils.Script.evaluateReturn(optionalPath, obj);
1529
1917
  }
1530
1918
  };
1531
1919
 
@@ -1533,7 +1921,7 @@ export class RawSet {
1533
1921
  const path = this.findParentThisPath(rawSet);
1534
1922
  if (path) {
1535
1923
  const optionalPath = ObjectUtils.Path.toOptionalChainPath(path);
1536
- return ScriptUtils.evaluateReturn(optionalPath, obj);
1924
+ return ObjectUtils.Script.evaluateReturn(optionalPath, obj);
1537
1925
  }
1538
1926
  };
1539
1927
 
@@ -1552,11 +1940,14 @@ export class RawSet {
1552
1940
  const findPath = (rawSet: RawSet) => {
1553
1941
  if (rawSet && rawSet.point) {
1554
1942
  // jsDom에서 instranceof HTMLMetaElement가 안먹히는것같아? 간혈적으로?
1555
- if ('getAttribute' in rawSet.point.start && rawSet.point.start.getAttribute('this-path')) {
1943
+ if (
1944
+ rawSet.point?.start &&
1945
+ 'getAttribute' in rawSet.point.start &&
1946
+ rawSet.point.start.getAttribute('this-path')
1947
+ ) {
1556
1948
  paths.push(rawSet.point.start.getAttribute('this-path')!);
1557
1949
  }
1558
- if (rawSet.point.parentRawSet)
1559
- findPath(rawSet.point.parentRawSet);
1950
+ if (rawSet.point.parentRawSet) findPath(rawSet.point.parentRawSet);
1560
1951
  }
1561
1952
  };
1562
1953
  findPath(rawSet);
@@ -1564,19 +1955,42 @@ export class RawSet {
1564
1955
  return paths.reverse();
1565
1956
  };
1566
1957
 
1567
- public static getAttributeObject(element: Element, config: { script: string, obj: any, renderData?: any }) {
1958
+ public static getAttributeObject(element: Element, config: { script: string; obj: any; renderData?: any }) {
1568
1959
  if (!element) {
1569
1960
  return undefined;
1570
1961
  }
1571
1962
  const attribute = ElementUtils.getAttributeToObject(element);
1572
1963
  const normalAttribute = attribute[EventManager.normalAttrMapAttrName];
1573
1964
  if (normalAttribute) {
1574
- new Map<string, string>(JSON.parse(normalAttribute)).forEach((v, k) => {
1575
- const cval = ScriptUtils.evaluateReturn({bodyScript: config.script, returnScript: v}, Object.assign(config.obj, config.renderData ? {__render:config.renderData} : undefined));
1965
+ new Map<string, NormalAttrDataType>(JSON.parse(normalAttribute)).forEach((v, k) => {
1966
+ const variablePaths = v.variablePaths;
1967
+ let targetScript = v.originalAttrValue.trim();
1968
+
1969
+ let checktargetScript = v.originalAttrValue.trim();
1970
+ variablePaths.forEach(it => {
1971
+ checktargetScript = targetScript.replaceAll(it.origin, '');
1972
+ })
1973
+
1974
+
1975
+ //중요!! expression 하나만 존재 및 그외것들이 없을때 그자체가 값이다 그외 여러개 있으면 문자열 합치는걸로 간주한다.
1976
+ let isScriptValue = checktargetScript.length === 0 && variablePaths.length === 1;
1977
+
1978
+ if (isScriptValue) {
1979
+ let r = ObjectUtils.Path.toOptionalChainPath(variablePaths[0].inner);
1980
+ targetScript = targetScript.replaceAll(variablePaths[0].origin, r);
1981
+ } else {
1982
+ variablePaths.forEach(it => {
1983
+ let r = ObjectUtils.Path.toOptionalChainPath(it.inner);
1984
+ targetScript = targetScript.replaceAll(it.origin, `\${${r}}`);
1985
+ });
1986
+ }
1987
+ const cval = ObjectUtils.Script.evaluateReturn(
1988
+ { bodyScript: config.script, returnScript: isScriptValue ? targetScript : '`' + targetScript + '`' },
1989
+ Object.assign(config.obj, config.renderData ? { __render: config.renderData } : undefined)
1990
+ );
1576
1991
  attribute[k] = cval;
1577
1992
  });
1578
1993
  }
1579
1994
  return attribute;
1580
1995
  }
1581
-
1582
1996
  }