solarite 0.3.2 → 0.4.0
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.
- package/dist/Solarite-debug.js +571 -405
- package/dist/Solarite.js +567 -358
- package/dist/Solarite.min.js +11 -2
- package/package.json +2 -2
- package/readme.md +2 -2
- package/src/ExprPath.js +87 -79
- package/src/Globals.js +9 -5
- package/src/NodeGroup.js +79 -242
- package/src/RootNodeGroup.js +153 -0
- package/src/Shell.js +12 -9
- package/src/Solarite.d.ts +8 -4
- package/src/Solarite.js +10 -8
- package/src/Template.js +135 -3
- package/src/Util.js +52 -14
- package/src/createSolarite.js +2 -2
- package/src/h.js +81 -129
- package/src/toEl.js +84 -0
- package/src/udomdiff.js +0 -55
- package/src/watch.js +2 -2
package/src/Shell.js
CHANGED
|
@@ -53,7 +53,7 @@ export default class Shell {
|
|
|
53
53
|
//#ENDIF
|
|
54
54
|
|
|
55
55
|
if (html.length === 1 && !html[0].match(/[<&]/)) {
|
|
56
|
-
this.fragment =
|
|
56
|
+
this.fragment = Globals.doc.createTextNode(html[0]);
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -61,18 +61,18 @@ export default class Shell {
|
|
|
61
61
|
// 1. Add placeholders
|
|
62
62
|
let joinedHtml = Shell.addPlaceholders(html);
|
|
63
63
|
|
|
64
|
-
let template =
|
|
64
|
+
let template = Globals.doc.createElement('template'); // Using a single global template won't keep the nodes as children of the DocumentFragment.
|
|
65
65
|
if (joinedHtml)
|
|
66
66
|
template.innerHTML = joinedHtml;
|
|
67
67
|
else // Create one text node, so shell isn't empty and NodeGroups created from it have something to point the startNode and endNode at.
|
|
68
|
-
template.content.append(
|
|
68
|
+
template.content.append(Globals.doc.createTextNode(''))
|
|
69
69
|
this.fragment = template.content;
|
|
70
70
|
|
|
71
71
|
// 2. Find placeholders
|
|
72
72
|
let node;
|
|
73
73
|
let toRemove = [];
|
|
74
74
|
let placeholdersUsed = 0;
|
|
75
|
-
const walker =
|
|
75
|
+
const walker = Globals.doc.createTreeWalker(this.fragment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT);
|
|
76
76
|
while (node = walker.nextNode()) {
|
|
77
77
|
|
|
78
78
|
// Remove previous after each iteration, so paths will still be calculated correctly.
|
|
@@ -108,10 +108,13 @@ export default class Shell {
|
|
|
108
108
|
// Replace comment placeholders
|
|
109
109
|
else if (node.nodeType === 8 && node.nodeValue === '!✨!') {
|
|
110
110
|
|
|
111
|
+
if (node?.parentNode?.closest && node?.parentNode?.closest('[contenteditable]'))
|
|
112
|
+
throw new Error(`Contenteditable can't have expressions inside them. Use <div contenteditable value="\${...}"> instead.`);
|
|
113
|
+
|
|
111
114
|
// Get or create nodeBefore.
|
|
112
115
|
let nodeBefore = node.previousSibling; // Can be the same as another Path's nodeMarker.
|
|
113
116
|
if (!nodeBefore) {
|
|
114
|
-
nodeBefore =
|
|
117
|
+
nodeBefore = Globals.doc.createComment('ExprPath:'+this.paths.length);
|
|
115
118
|
node.parentNode.insertBefore(nodeBefore, node)
|
|
116
119
|
}
|
|
117
120
|
/*#IFDEV*/assert(nodeBefore);/*#ENDIF*/
|
|
@@ -136,9 +139,9 @@ export default class Shell {
|
|
|
136
139
|
placeholdersUsed ++;
|
|
137
140
|
}
|
|
138
141
|
|
|
142
|
+
// Comments become text nodes when inside textareas.
|
|
139
143
|
else if (node.nodeType === 3 && node.parentNode?.tagName === 'TEXTAREA' && node.textContent.includes('<!--!✨!-->'))
|
|
140
144
|
throw new Error(`Textarea can't have expressions inside them. Use <textarea value="\${...}"> instead.`);
|
|
141
|
-
|
|
142
145
|
|
|
143
146
|
|
|
144
147
|
// Sometimes users will comment out a block of html code that has expressions.
|
|
@@ -162,7 +165,7 @@ export default class Shell {
|
|
|
162
165
|
|
|
163
166
|
let placeholders = [];
|
|
164
167
|
for (let i = 0; i<parts.length; i++) {
|
|
165
|
-
let current =
|
|
168
|
+
let current = Globals.doc.createTextNode(parts[i]);
|
|
166
169
|
node.parentNode.insertBefore(current, node);
|
|
167
170
|
if (i > 0)
|
|
168
171
|
placeholders.push(current)
|
|
@@ -201,9 +204,9 @@ export default class Shell {
|
|
|
201
204
|
path.nodeMarkerPath = getNodePath(path.nodeMarker)
|
|
202
205
|
|
|
203
206
|
// Cache so we don't have to calculate this later inside NodeGroup.applyExprs()
|
|
204
|
-
if (path.type === ExprPathType.AttribValue && path.nodeMarker.nodeType === 1 &&
|
|
207
|
+
if ((path.type === ExprPathType.AttribValue || path.type === ExprPathType.Event) && path.nodeMarker.nodeType === 1 &&
|
|
205
208
|
(path.nodeMarker.tagName.includes('-') || path.nodeMarker.hasAttribute('is'))) {
|
|
206
|
-
path.
|
|
209
|
+
path.isComponent = true;
|
|
207
210
|
}
|
|
208
211
|
}
|
|
209
212
|
|
package/src/Solarite.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Solarite
|
|
2
|
+
* Solarite JavaScript UI library.
|
|
3
3
|
* MIT License
|
|
4
4
|
* https://vorticode.github.io/solarite/
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export default function h(htmlStrings?: HTMLElement | string | string[] | Function | {render: Function}, ...exprs: any[]): Node | HTMLElement | Template | Function;
|
|
8
|
-
export
|
|
7
|
+
export default function h(htmlStrings?: HTMLElement | string | string[] | TemplateStringsArray | Function | {render: Function}, ...exprs: any[]): Node | HTMLElement | Template | Function;
|
|
8
|
+
export function toEl(htmlOrTemplate: string|Template|{render:()=>void}) : Node|HTMLElement|DocumentFragment;
|
|
9
|
+
|
|
10
|
+
// Deprecated:
|
|
11
|
+
export function t(html: string): Template;
|
|
12
|
+
|
|
9
13
|
|
|
10
14
|
export const ArgType: {
|
|
11
15
|
Bool: string;
|
|
@@ -44,7 +48,7 @@ export function delve(obj: object, path: string[], createVal?: any): any;
|
|
|
44
48
|
|
|
45
49
|
// Globals object
|
|
46
50
|
export const Globals: {
|
|
47
|
-
componentArgsHash: WeakMap<any, any>;
|
|
51
|
+
//componentArgsHash: WeakMap<any, any>;
|
|
48
52
|
connected: WeakSet<HTMLElement>;
|
|
49
53
|
currentExprPath: any;
|
|
50
54
|
div: HTMLDivElement;
|
package/src/Solarite.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/*
|
|
2
|
+
┏┓ ┓ •
|
|
3
|
+
┗┓┏┓┃┏┓┏┓┓╋▗▖
|
|
4
|
+
┗┛┗┛┗┗┻╹ ╹╹┗
|
|
5
|
+
JavasCript UI library
|
|
6
|
+
@license MIT
|
|
7
|
+
@copyright Vorticode LLC
|
|
8
|
+
https://vorticode.github.io/solarite/ */
|
|
7
9
|
import h from './h.js';
|
|
8
10
|
export default h;
|
|
9
11
|
export {default as h, default as r} from './h.js'; //Named exports for h() are deprecated.
|
|
10
|
-
export {default as delve} from './delve.js';
|
|
11
12
|
export {getArg, ArgType} from './getArg.js';
|
|
12
13
|
export {default as Template} from './Template.js';
|
|
13
|
-
|
|
14
|
+
export {default as toEl} from './toEl.js';
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
// Experimental:
|
|
@@ -28,6 +29,7 @@ const Solarite = new Proxy(createSolarite(), {
|
|
|
28
29
|
}
|
|
29
30
|
});
|
|
30
31
|
|
|
32
|
+
|
|
31
33
|
/** @type {HTMLElement|Class} */
|
|
32
34
|
export {Solarite}
|
|
33
35
|
export {default as Globals} from './Globals.js';
|
package/src/Template.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {assert} from "./assert.js";
|
|
2
2
|
import {getObjectHash, getObjectId} from "./hash.js";
|
|
3
3
|
import Globals from "./Globals.js";
|
|
4
|
-
import
|
|
4
|
+
import RootNodeGroup from "./RootNodeGroup.js";
|
|
5
|
+
import Util from "./Util.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* The html strings and evaluated expressions from an html tagged template.
|
|
@@ -18,8 +19,7 @@ export default class Template {
|
|
|
18
19
|
/** @type {Array} Used for toJSON() and getObjectHash(). Stores values used to quickly create a string hash of this template. */
|
|
19
20
|
hashedFields;
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
nodeGroup;
|
|
22
|
+
isText;
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
*
|
|
@@ -124,6 +124,138 @@ export default class Template {
|
|
|
124
124
|
|
|
125
125
|
return this.closeKey;
|
|
126
126
|
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @param tag {string}
|
|
130
|
+
* @param props {?Record<string, any>}
|
|
131
|
+
* @param children
|
|
132
|
+
* @returns {Template} */
|
|
133
|
+
static fromJsx(tag, props, children) {
|
|
134
|
+
|
|
135
|
+
// HTML void elements that must not have closing tags
|
|
136
|
+
const isVoid = selfClosingTags.has(tag.toLowerCase());
|
|
137
|
+
|
|
138
|
+
// Build htmlStrings/exprs so Shell can place placeholders in attribute values and child content.
|
|
139
|
+
let htmlStrings = [];
|
|
140
|
+
let templateExprs = [];
|
|
141
|
+
|
|
142
|
+
// Opening tag
|
|
143
|
+
let open = `<${tag}`;
|
|
144
|
+
|
|
145
|
+
// Attributes
|
|
146
|
+
if (props && typeof props === 'object') {
|
|
147
|
+
for (let name in props) {
|
|
148
|
+
let value = props[name];
|
|
149
|
+
|
|
150
|
+
// id and data-id are static in templates — never expressions
|
|
151
|
+
if (name === 'id' || name === 'data-id') {
|
|
152
|
+
// Write directly into the opening string with quotes
|
|
153
|
+
open += ` ${name}="${value}"`;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Dynamic attribute value: functions are unquoted (e.g., onclick=${fn}), others quoted
|
|
158
|
+
if (typeof value === 'function') {
|
|
159
|
+
open += ` ${name}=`;
|
|
160
|
+
htmlStrings.push(open);
|
|
161
|
+
templateExprs.push(value);
|
|
162
|
+
// reset so subsequent attributes start fresh (e.g., ' title=')
|
|
163
|
+
open = ``;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
open += ` ${name}=`;
|
|
167
|
+
htmlStrings.push(open);
|
|
168
|
+
templateExprs.push(value);
|
|
169
|
+
// reset so subsequent attributes start fresh (e.g., ' title=')
|
|
170
|
+
open = ``;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Finalize opening tag precisely to match tagged template splitting
|
|
176
|
+
if (!isVoid) {
|
|
177
|
+
const pushedAny = htmlStrings.length > 0;
|
|
178
|
+
// If nothing pushed yet (no dynamic attrs), push the entire open + '>'
|
|
179
|
+
if (!pushedAny)
|
|
180
|
+
htmlStrings.push(open + '>');
|
|
181
|
+
else {
|
|
182
|
+
// If we were in a quoted attr (open === '"'), then the string after expr is '">' ;
|
|
183
|
+
// Otherwise (function-valued attr), the string after expr is just '>'
|
|
184
|
+
htmlStrings.push(open === '"' ? '">' : '>');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
for (let child of children)
|
|
188
|
+
addChild(child, htmlStrings, templateExprs);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Closing tag (not for void tags)
|
|
192
|
+
if (!isVoid) {
|
|
193
|
+
// If we never emitted the '>' for the open tag (no children were added),
|
|
194
|
+
// then it was appended above before children. Now just add the closing tag to the last html segment.
|
|
195
|
+
let lastIdx = htmlStrings.length - 1;
|
|
196
|
+
htmlStrings[lastIdx] += `</${tag}>`;
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
// Void element: ensure we emitted a trailing '>' segment
|
|
200
|
+
const pushedAny = htmlStrings.length > 0;
|
|
201
|
+
if (!pushedAny)
|
|
202
|
+
htmlStrings.push(open + '>');
|
|
203
|
+
else
|
|
204
|
+
htmlStrings.push('>');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Ensure invariant
|
|
208
|
+
//assert(htmlStrings.length === templateExprs.length + 1);
|
|
209
|
+
//console.log([htmlStrings, templateExprs])
|
|
210
|
+
return new Template(htmlStrings, templateExprs);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
const selfClosingTags = new Set(['area','base','br','col','embed','hr','img','input','link','meta','param','source','track','wbr']);
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Add child Templates that were already created via h() and Template.fromJsx()
|
|
220
|
+
* @param template {Template}
|
|
221
|
+
* @param html {string[]}
|
|
222
|
+
* @param exprs {any[]} */
|
|
223
|
+
const addChild = (template, html, exprs) => {
|
|
224
|
+
|
|
225
|
+
if (Array.isArray(template)) {
|
|
226
|
+
for (let c of template)
|
|
227
|
+
addChild(c, html, exprs);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
let flatten = false;
|
|
231
|
+
if (template instanceof Template) {
|
|
232
|
+
// Heuristic to match tagged-template splitting:
|
|
233
|
+
// - Flatten if the child has expressions (so JSX can inline attribute/value placeholders like tagged literals would).
|
|
234
|
+
// - Also flatten void elements (e.g., <img>) so they inline like literals.
|
|
235
|
+
// - Otherwise, keep as a dynamic child placeholder to match cases where the tagged template used an expression child.
|
|
236
|
+
const childHasExprs = template.exprs.length > 0;
|
|
237
|
+
if (childHasExprs)
|
|
238
|
+
flatten = true;
|
|
239
|
+
else {
|
|
240
|
+
const m = (template.html[0] || '').match(/^<([a-zA-Z][\w:-]*)/);
|
|
241
|
+
const childTag = m ? m[1].toLowerCase() : '';
|
|
242
|
+
flatten = selfClosingTags.has(childTag);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (flatten) {
|
|
247
|
+
// Flatten/interleave into current segment to match tagged template splitting
|
|
248
|
+
html[html.length - 1] += template.html[0];
|
|
249
|
+
for (let i = 0; i < template.exprs.length; i++) {
|
|
250
|
+
exprs.push(template.exprs[i]);
|
|
251
|
+
html.push(template.html[i + 1] ?? '');
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
// Keep as dynamic child
|
|
255
|
+
exprs.push(template);
|
|
256
|
+
html.push('');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
127
259
|
}
|
|
128
260
|
|
|
129
261
|
|
package/src/Util.js
CHANGED
|
@@ -18,12 +18,25 @@ let Util = {
|
|
|
18
18
|
return true; // the same.
|
|
19
19
|
},
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Convert HTMLElement attributes to an object.
|
|
23
|
+
* @param el {HTMLElement}
|
|
24
|
+
* @param ignore {?string} Optionally ignore this attribute.
|
|
25
|
+
* @return {Object} */
|
|
26
|
+
attribsToObject(el, ignore=null) {
|
|
27
|
+
let result = {};
|
|
28
|
+
for (let attrib of el.attributes)
|
|
29
|
+
if (attrib.name !== ignore)
|
|
30
|
+
result[Util.dashesToCamel(attrib.name)] = attrib.value;
|
|
31
|
+
return result;
|
|
32
|
+
},
|
|
33
|
+
|
|
21
34
|
bindId(root, el) {
|
|
22
35
|
let id = el.getAttribute('data-id') || el.getAttribute('id');
|
|
23
36
|
if (id) { // If something hasn't removed the id.
|
|
24
37
|
|
|
25
38
|
// Don't allow overwriting existing class properties if they already have a non-Node value.
|
|
26
|
-
if (root[id] && !(root[id]
|
|
39
|
+
if (root[id] && !(root[id]?.nodeType))
|
|
27
40
|
throw new Error(`${root.constructor.name}.${id} already has a value. ` +
|
|
28
41
|
`Can't set it as a reference to <${el.tagName.toLowerCase()} id="${id}">`);
|
|
29
42
|
|
|
@@ -32,26 +45,50 @@ let Util = {
|
|
|
32
45
|
},
|
|
33
46
|
|
|
34
47
|
/**
|
|
48
|
+
* If the style tab has a global attribute:
|
|
49
|
+
* 1. Put it in the document head as <style data-style="tag-name">...</style>
|
|
50
|
+
* 2. Replace the :host {...} CSS selector as tag-name {...}.
|
|
51
|
+
* Otherwise keep it where it is and:
|
|
52
|
+
* 1. Add data-style="1" attribute to the root element.
|
|
53
|
+
* 2. Replace the :host {...} selector in the style as tag-name[data-style='1'] {...}
|
|
35
54
|
* @param style {HTMLStyleElement}
|
|
36
55
|
* @param root {HTMLElement} */
|
|
37
56
|
bindStyles(style, root) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
|
|
58
|
+
let tagName = root.tagName.toLowerCase();
|
|
59
|
+
let styleId, attribSelector;
|
|
60
|
+
|
|
61
|
+
if (style.hasAttribute('global') || style.hasAttribute('data-global')) {
|
|
62
|
+
styleId = tagName;
|
|
63
|
+
attribSelector = '';
|
|
64
|
+
let doc = Globals.doc || root.ownerDocument || document;
|
|
65
|
+
if (!doc.head.querySelector(`style[data-style="${styleId}"]`)) {
|
|
66
|
+
doc.head.append(style)
|
|
67
|
+
style.setAttribute('data-style', styleId);
|
|
68
|
+
}
|
|
69
|
+
else // TODO: Make sure the style has no expressions.
|
|
70
|
+
style.remove(); // already in the head.
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
let styleId = root.getAttribute('data-style');
|
|
74
|
+
if (!styleId) {
|
|
75
|
+
// Keep track of one style id for each class.
|
|
76
|
+
// TODO: Put this outside the class in a map, so it doesn't conflict with static properties.
|
|
77
|
+
if (!root.constructor.styleId)
|
|
78
|
+
root.constructor.styleId = 1;
|
|
79
|
+
styleId = root.constructor.styleId++;
|
|
80
|
+
|
|
81
|
+
root.setAttribute('data-style', styleId);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
attribSelector = `[data-style="${styleId}"]`;
|
|
47
85
|
}
|
|
48
86
|
|
|
49
87
|
// Replace ":host" with "tagName[data-style=...]" in the css.
|
|
50
|
-
let tagName = root.tagName.toLowerCase();
|
|
51
88
|
for (let child of style.childNodes) {
|
|
52
89
|
if (child.nodeType === 3) {
|
|
53
90
|
let oldText = child.textContent;
|
|
54
|
-
let newText = oldText.replace(/:host(?=[^a-z0-9_])/gi, `${tagName}
|
|
91
|
+
let newText = oldText.replace(/:host(?=[^a-z0-9_])/gi, `${tagName}${attribSelector}`)
|
|
55
92
|
if (oldText !== newText)
|
|
56
93
|
child.textContent = newText;
|
|
57
94
|
}
|
|
@@ -98,7 +135,6 @@ let Util = {
|
|
|
98
135
|
return str.replace(/-([a-z])/g, g => g[1].toUpperCase());
|
|
99
136
|
},
|
|
100
137
|
|
|
101
|
-
|
|
102
138
|
/**
|
|
103
139
|
* A generator function that recursively traverses and flattens a value.
|
|
104
140
|
*
|
|
@@ -139,7 +175,7 @@ let Util = {
|
|
|
139
175
|
|
|
140
176
|
/**
|
|
141
177
|
* Get the value of an input as the most appropriate JavaScript type.
|
|
142
|
-
* @param node {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement|
|
|
178
|
+
* @param node {HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement|HTMLElement}
|
|
143
179
|
* @return {string|string[]|number|[]|File[]|Date|boolean} */
|
|
144
180
|
getInputValue(node) {
|
|
145
181
|
// .type is a built-in DOM property
|
|
@@ -153,6 +189,8 @@ let Util = {
|
|
|
153
189
|
return node.valueAsDate; // Date Object
|
|
154
190
|
if (node.type === 'select-multiple') // <select multiple>
|
|
155
191
|
return [...node.selectedOptions].map(option => option.value); // Array of Strings
|
|
192
|
+
if (node.hasAttribute('contenteditable'))
|
|
193
|
+
return node.innerHTML;
|
|
156
194
|
|
|
157
195
|
return node.value; // String
|
|
158
196
|
},
|
package/src/createSolarite.js
CHANGED
|
@@ -42,7 +42,7 @@ export default function createSolarite(extendsTag=null) {
|
|
|
42
42
|
|
|
43
43
|
BaseClass = Globals.elementClasses[extendsTag];
|
|
44
44
|
if (!BaseClass) { // TODO: Use Cache
|
|
45
|
-
BaseClass =
|
|
45
|
+
BaseClass = Globals.doc.createElement(extendsTag).constructor;
|
|
46
46
|
Globals.elementClasses[extendsTag] = BaseClass
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -103,7 +103,7 @@ export default function createSolarite(extendsTag=null) {
|
|
|
103
103
|
this.innerHTML = html;
|
|
104
104
|
}
|
|
105
105
|
else
|
|
106
|
-
this.modifications =
|
|
106
|
+
this.modifications = h(this, html, options);
|
|
107
107
|
}
|
|
108
108
|
})*/
|
|
109
109
|
|