starmark 1.0.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/bin/starmark.js +5 -0
- package/package.json +43 -0
- package/public/app.js +2952 -0
- package/public/frontmatter-editor.js +490 -0
- package/public/frontmatter.js +554 -0
- package/public/icons.js +52 -0
- package/public/index.html +113 -0
- package/public/styles.css +1564 -0
- package/public/toolkit.js +19 -0
- package/public/tools/10-undo.js +26 -0
- package/public/tools/11-redo.js +26 -0
- package/public/tools/20-bold.js +21 -0
- package/public/tools/21-italic.js +21 -0
- package/public/tools/22-strikethrough.js +21 -0
- package/public/tools/30-link.js +136 -0
- package/public/tools/31-image.js +488 -0
- package/src/content-config.js +391 -0
- package/src/server.js +1056 -0
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { icons } from "./icons.js";
|
|
2
|
+
import {
|
|
3
|
+
defaultValueForType,
|
|
4
|
+
inferValueType,
|
|
5
|
+
normalizeFrontmatter,
|
|
6
|
+
parseFrontmatter,
|
|
7
|
+
stringifyFrontmatter,
|
|
8
|
+
} from "./frontmatter.js";
|
|
9
|
+
|
|
10
|
+
const VALUE_TYPES = [
|
|
11
|
+
{ value: "string", label: "Text" },
|
|
12
|
+
{ value: "number", label: "Number" },
|
|
13
|
+
{ value: "boolean", label: "Boolean" },
|
|
14
|
+
{ value: "null", label: "Null" },
|
|
15
|
+
{ value: "array", label: "List" },
|
|
16
|
+
{ value: "object", label: "Object" },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
function coerceScalar(type, rawValue) {
|
|
20
|
+
switch (type) {
|
|
21
|
+
case "boolean":
|
|
22
|
+
return rawValue === true || rawValue === "true";
|
|
23
|
+
case "number": {
|
|
24
|
+
const parsed = Number(rawValue);
|
|
25
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
26
|
+
}
|
|
27
|
+
case "null":
|
|
28
|
+
return null;
|
|
29
|
+
default:
|
|
30
|
+
return rawValue ?? "";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createFrontmatterEditor(root, { onChange } = {}) {
|
|
35
|
+
let data = {};
|
|
36
|
+
let parseError = null;
|
|
37
|
+
let rawFallback = "";
|
|
38
|
+
let silent = false;
|
|
39
|
+
|
|
40
|
+
const container = document.createElement("div");
|
|
41
|
+
container.className = "frontmatter-form";
|
|
42
|
+
root.replaceChildren(container);
|
|
43
|
+
|
|
44
|
+
function emitChange() {
|
|
45
|
+
if (silent || !onChange) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
onChange(getValue());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getValue() {
|
|
53
|
+
if (parseError) {
|
|
54
|
+
return normalizeFrontmatter(rawFallback);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
return normalizeFrontmatter(stringifyFrontmatter(data));
|
|
59
|
+
} catch {
|
|
60
|
+
return normalizeFrontmatter(rawFallback);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function setValue(text) {
|
|
65
|
+
silent = true;
|
|
66
|
+
const trimmed = (text ?? "").trim();
|
|
67
|
+
|
|
68
|
+
if (trimmed === "") {
|
|
69
|
+
data = {};
|
|
70
|
+
parseError = null;
|
|
71
|
+
rawFallback = "";
|
|
72
|
+
render();
|
|
73
|
+
silent = false;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
data = parseFrontmatter(trimmed);
|
|
79
|
+
parseError = null;
|
|
80
|
+
rawFallback = trimmed;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
parseError = error instanceof Error ? error.message : "Could not parse frontmatter";
|
|
83
|
+
rawFallback = trimmed;
|
|
84
|
+
data = {};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
render();
|
|
88
|
+
silent = false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function refresh() {
|
|
92
|
+
render();
|
|
93
|
+
emitChange();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function touchData() {
|
|
97
|
+
emitChange();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function render() {
|
|
101
|
+
container.replaceChildren();
|
|
102
|
+
|
|
103
|
+
if (parseError) {
|
|
104
|
+
container.appendChild(renderParseError());
|
|
105
|
+
container.appendChild(renderRawEditor());
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
container.appendChild(renderObjectEditor(data, refresh, touchData, 0));
|
|
110
|
+
container.appendChild(renderAddFieldButton(data, refresh));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
container.addEventListener("keydown", (event) => {
|
|
114
|
+
const isMod = event.metaKey || event.ctrlKey;
|
|
115
|
+
if (isMod && event.key.toLowerCase() === "s") {
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
onChange?.(getValue(), { save: true });
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
function renderParseError() {
|
|
122
|
+
const banner = document.createElement("div");
|
|
123
|
+
banner.className = "frontmatter-form-error";
|
|
124
|
+
banner.textContent = `Could not parse frontmatter: ${parseError}. Edit the raw YAML below.`;
|
|
125
|
+
return banner;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function renderRawEditor() {
|
|
129
|
+
const textarea = document.createElement("textarea");
|
|
130
|
+
textarea.className = "frontmatter-content frontmatter-raw-fallback";
|
|
131
|
+
textarea.value = rawFallback;
|
|
132
|
+
textarea.rows = 8;
|
|
133
|
+
textarea.spellcheck = false;
|
|
134
|
+
textarea.autocomplete = "off";
|
|
135
|
+
textarea.setAttribute("aria-label", "Frontmatter raw YAML");
|
|
136
|
+
|
|
137
|
+
textarea.addEventListener("input", () => {
|
|
138
|
+
rawFallback = textarea.value;
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
data = parseFrontmatter(rawFallback);
|
|
142
|
+
parseError = null;
|
|
143
|
+
render();
|
|
144
|
+
} catch {
|
|
145
|
+
// Stay in raw fallback mode until YAML is valid.
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
emitChange();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
textarea.addEventListener("keydown", (event) => {
|
|
152
|
+
const isMod = event.metaKey || event.ctrlKey;
|
|
153
|
+
if (isMod && event.key.toLowerCase() === "s") {
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
onChange?.(getValue(), { save: true });
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return textarea;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function focus() {
|
|
163
|
+
const focusTarget = container.querySelector("input, textarea, select, button");
|
|
164
|
+
focusTarget?.focus();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
setValue("");
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
setValue,
|
|
171
|
+
getValue,
|
|
172
|
+
focus,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function renderAddFieldButton(objectValue, onRefresh, label = "Add field") {
|
|
177
|
+
const footer = document.createElement("div");
|
|
178
|
+
footer.className = "frontmatter-form-footer";
|
|
179
|
+
|
|
180
|
+
const button = document.createElement("button");
|
|
181
|
+
button.type = "button";
|
|
182
|
+
button.className = "frontmatter-add-btn";
|
|
183
|
+
button.innerHTML = `${icons.plus}<span>${label}</span>`;
|
|
184
|
+
button.addEventListener("click", () => {
|
|
185
|
+
let key = "field";
|
|
186
|
+
let suffix = 1;
|
|
187
|
+
while (Object.prototype.hasOwnProperty.call(objectValue, key)) {
|
|
188
|
+
key = `field${suffix}`;
|
|
189
|
+
suffix += 1;
|
|
190
|
+
}
|
|
191
|
+
objectValue[key] = "";
|
|
192
|
+
onRefresh();
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
footer.appendChild(button);
|
|
196
|
+
return footer;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function renderObjectEditor(objectValue, onRefresh, onValueChange, depth) {
|
|
200
|
+
const section = document.createElement("div");
|
|
201
|
+
section.className = "frontmatter-node frontmatter-object";
|
|
202
|
+
if (depth > 0) {
|
|
203
|
+
section.dataset.depth = String(depth);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const entries = Object.entries(objectValue);
|
|
207
|
+
if (entries.length === 0 && depth > 0) {
|
|
208
|
+
const empty = document.createElement("p");
|
|
209
|
+
empty.className = "frontmatter-empty";
|
|
210
|
+
empty.textContent = "No fields yet.";
|
|
211
|
+
section.appendChild(empty);
|
|
212
|
+
return section;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
for (const [key, value] of entries) {
|
|
216
|
+
section.appendChild(renderFieldRow(key, value, objectValue, onRefresh, onValueChange, depth));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return section;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function renderFieldRow(key, value, parentObject, onRefresh, onValueChange, depth) {
|
|
223
|
+
const field = document.createElement("div");
|
|
224
|
+
field.className = "frontmatter-field";
|
|
225
|
+
|
|
226
|
+
const row = document.createElement("div");
|
|
227
|
+
row.className = "frontmatter-row";
|
|
228
|
+
|
|
229
|
+
const keyInput = document.createElement("input");
|
|
230
|
+
keyInput.type = "text";
|
|
231
|
+
keyInput.className = "frontmatter-key-input";
|
|
232
|
+
keyInput.value = key;
|
|
233
|
+
keyInput.placeholder = "key";
|
|
234
|
+
keyInput.spellcheck = false;
|
|
235
|
+
keyInput.addEventListener("change", () => {
|
|
236
|
+
const nextKey = keyInput.value.trim();
|
|
237
|
+
if (nextKey === "" || nextKey === key) {
|
|
238
|
+
keyInput.value = key;
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (Object.prototype.hasOwnProperty.call(parentObject, nextKey)) {
|
|
243
|
+
keyInput.value = key;
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const entryValue = parentObject[key];
|
|
248
|
+
delete parentObject[key];
|
|
249
|
+
parentObject[nextKey] = entryValue;
|
|
250
|
+
onRefresh();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const typeSelect = document.createElement("select");
|
|
254
|
+
typeSelect.className = "frontmatter-type-select";
|
|
255
|
+
typeSelect.setAttribute("aria-label", `Type for ${key}`);
|
|
256
|
+
|
|
257
|
+
for (const option of VALUE_TYPES) {
|
|
258
|
+
const element = document.createElement("option");
|
|
259
|
+
element.value = option.value;
|
|
260
|
+
element.textContent = option.label;
|
|
261
|
+
typeSelect.appendChild(element);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const currentType = inferValueType(value);
|
|
265
|
+
typeSelect.value = currentType;
|
|
266
|
+
typeSelect.addEventListener("change", () => {
|
|
267
|
+
parentObject[key] = defaultValueForType(typeSelect.value);
|
|
268
|
+
onRefresh();
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const removeButton = document.createElement("button");
|
|
272
|
+
removeButton.type = "button";
|
|
273
|
+
removeButton.className = "frontmatter-remove-btn";
|
|
274
|
+
removeButton.innerHTML = icons.trash;
|
|
275
|
+
removeButton.setAttribute("aria-label", `Remove ${key}`);
|
|
276
|
+
removeButton.addEventListener("click", () => {
|
|
277
|
+
delete parentObject[key];
|
|
278
|
+
onRefresh();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const isNestedType = currentType === "array" || currentType === "object";
|
|
282
|
+
|
|
283
|
+
if (isNestedType) {
|
|
284
|
+
row.classList.add("frontmatter-row--compact");
|
|
285
|
+
row.append(keyInput, typeSelect, removeButton);
|
|
286
|
+
} else {
|
|
287
|
+
const valueHost = document.createElement("div");
|
|
288
|
+
valueHost.className = "frontmatter-value-host";
|
|
289
|
+
valueHost.appendChild(
|
|
290
|
+
renderScalarEditor(value, currentType, parentObject, key, onValueChange),
|
|
291
|
+
);
|
|
292
|
+
row.append(keyInput, typeSelect, valueHost, removeButton);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
field.appendChild(row);
|
|
296
|
+
|
|
297
|
+
if (isNestedType) {
|
|
298
|
+
const children = document.createElement("div");
|
|
299
|
+
children.className = "frontmatter-children";
|
|
300
|
+
children.appendChild(
|
|
301
|
+
renderValueEditor(value, currentType, parentObject, key, onRefresh, onValueChange, depth + 1),
|
|
302
|
+
);
|
|
303
|
+
field.appendChild(children);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return field;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function renderValueEditor(
|
|
310
|
+
value,
|
|
311
|
+
type,
|
|
312
|
+
parentContainer,
|
|
313
|
+
parentKey,
|
|
314
|
+
onRefresh,
|
|
315
|
+
onValueChange,
|
|
316
|
+
depth,
|
|
317
|
+
) {
|
|
318
|
+
if (type === "array") {
|
|
319
|
+
const arrayValue = Array.isArray(value) ? value : [];
|
|
320
|
+
if (!Array.isArray(parentContainer[parentKey])) {
|
|
321
|
+
parentContainer[parentKey] = arrayValue;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return renderArrayEditor(parentContainer[parentKey], onRefresh, onValueChange, depth);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (type === "object") {
|
|
328
|
+
const objectValue =
|
|
329
|
+
value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
330
|
+
if (
|
|
331
|
+
parentContainer[parentKey] === null ||
|
|
332
|
+
typeof parentContainer[parentKey] !== "object" ||
|
|
333
|
+
Array.isArray(parentContainer[parentKey])
|
|
334
|
+
) {
|
|
335
|
+
parentContainer[parentKey] = objectValue;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return renderNestedObjectEditor(parentContainer[parentKey], onRefresh, onValueChange, depth);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return renderScalarEditor(value, type, parentContainer, parentKey, onValueChange);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function renderScalarEditor(value, type, parentContainer, parentKey, onValueChange) {
|
|
345
|
+
const wrapper = document.createElement("div");
|
|
346
|
+
wrapper.className = "frontmatter-scalar";
|
|
347
|
+
|
|
348
|
+
if (type === "boolean") {
|
|
349
|
+
const checkbox = document.createElement("input");
|
|
350
|
+
checkbox.type = "checkbox";
|
|
351
|
+
checkbox.className = "frontmatter-boolean-input";
|
|
352
|
+
checkbox.checked = value === true;
|
|
353
|
+
checkbox.addEventListener("change", () => {
|
|
354
|
+
parentContainer[parentKey] = checkbox.checked;
|
|
355
|
+
onValueChange();
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
const label = document.createElement("label");
|
|
359
|
+
label.className = "frontmatter-boolean-label";
|
|
360
|
+
label.textContent = "true";
|
|
361
|
+
label.prepend(checkbox);
|
|
362
|
+
wrapper.appendChild(label);
|
|
363
|
+
return wrapper;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const input = document.createElement("input");
|
|
367
|
+
input.type = type === "number" ? "number" : "text";
|
|
368
|
+
input.className = "frontmatter-value-input";
|
|
369
|
+
input.value =
|
|
370
|
+
type === "null" ? "" : value === null || value === undefined ? "" : String(value);
|
|
371
|
+
input.placeholder = type === "null" ? "null" : "value";
|
|
372
|
+
input.spellcheck = false;
|
|
373
|
+
|
|
374
|
+
input.addEventListener("input", () => {
|
|
375
|
+
parentContainer[parentKey] = coerceScalar(type, input.value);
|
|
376
|
+
onValueChange();
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
wrapper.appendChild(input);
|
|
380
|
+
return wrapper;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function renderNestedObjectEditor(objectValue, onRefresh, onValueChange, depth) {
|
|
384
|
+
const wrapper = document.createElement("div");
|
|
385
|
+
wrapper.className = "frontmatter-nested";
|
|
386
|
+
|
|
387
|
+
wrapper.appendChild(renderObjectEditor(objectValue, onRefresh, onValueChange, depth));
|
|
388
|
+
wrapper.appendChild(renderAddFieldButton(objectValue, onRefresh));
|
|
389
|
+
return wrapper;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function renderArrayEditor(arrayValue, onRefresh, onValueChange, depth) {
|
|
393
|
+
const wrapper = document.createElement("div");
|
|
394
|
+
wrapper.className = "frontmatter-array";
|
|
395
|
+
|
|
396
|
+
if (arrayValue.length === 0) {
|
|
397
|
+
const empty = document.createElement("p");
|
|
398
|
+
empty.className = "frontmatter-empty";
|
|
399
|
+
empty.textContent = "No items yet.";
|
|
400
|
+
wrapper.appendChild(empty);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
arrayValue.forEach((item, index) => {
|
|
404
|
+
wrapper.appendChild(renderArrayItemRow(item, index, arrayValue, onRefresh, onValueChange, depth));
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
const footer = document.createElement("div");
|
|
408
|
+
footer.className = "frontmatter-form-footer";
|
|
409
|
+
|
|
410
|
+
const button = document.createElement("button");
|
|
411
|
+
button.type = "button";
|
|
412
|
+
button.className = "frontmatter-add-btn";
|
|
413
|
+
button.innerHTML = `${icons.plus}<span>Add item</span>`;
|
|
414
|
+
button.addEventListener("click", () => {
|
|
415
|
+
arrayValue.push("");
|
|
416
|
+
onRefresh();
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
footer.appendChild(button);
|
|
420
|
+
wrapper.appendChild(footer);
|
|
421
|
+
return wrapper;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function renderArrayItemRow(item, index, parentArray, onRefresh, onValueChange, depth) {
|
|
425
|
+
const entry = document.createElement("div");
|
|
426
|
+
entry.className = "frontmatter-array-entry";
|
|
427
|
+
|
|
428
|
+
const row = document.createElement("div");
|
|
429
|
+
row.className = "frontmatter-array-item";
|
|
430
|
+
|
|
431
|
+
const marker = document.createElement("span");
|
|
432
|
+
marker.className = "frontmatter-array-marker";
|
|
433
|
+
marker.textContent = "–";
|
|
434
|
+
marker.setAttribute("aria-hidden", "true");
|
|
435
|
+
|
|
436
|
+
const typeSelect = document.createElement("select");
|
|
437
|
+
typeSelect.className = "frontmatter-type-select";
|
|
438
|
+
typeSelect.setAttribute("aria-label", `Type for item ${index + 1}`);
|
|
439
|
+
|
|
440
|
+
for (const option of VALUE_TYPES) {
|
|
441
|
+
const element = document.createElement("option");
|
|
442
|
+
element.value = option.value;
|
|
443
|
+
element.textContent = option.label;
|
|
444
|
+
typeSelect.appendChild(element);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const currentType = inferValueType(item);
|
|
448
|
+
typeSelect.value = currentType;
|
|
449
|
+
typeSelect.addEventListener("change", () => {
|
|
450
|
+
parentArray[index] = defaultValueForType(typeSelect.value);
|
|
451
|
+
onRefresh();
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
const removeButton = document.createElement("button");
|
|
455
|
+
removeButton.type = "button";
|
|
456
|
+
removeButton.className = "frontmatter-remove-btn";
|
|
457
|
+
removeButton.innerHTML = icons.trash;
|
|
458
|
+
removeButton.setAttribute("aria-label", `Remove item ${index + 1}`);
|
|
459
|
+
removeButton.addEventListener("click", () => {
|
|
460
|
+
parentArray.splice(index, 1);
|
|
461
|
+
onRefresh();
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
const isNestedType = currentType === "array" || currentType === "object";
|
|
465
|
+
|
|
466
|
+
if (isNestedType) {
|
|
467
|
+
row.classList.add("frontmatter-row--compact");
|
|
468
|
+
row.append(marker, typeSelect, removeButton);
|
|
469
|
+
} else {
|
|
470
|
+
const valueHost = document.createElement("div");
|
|
471
|
+
valueHost.className = "frontmatter-value-host";
|
|
472
|
+
valueHost.appendChild(
|
|
473
|
+
renderScalarEditor(item, currentType, parentArray, index, onValueChange),
|
|
474
|
+
);
|
|
475
|
+
row.append(marker, typeSelect, valueHost, removeButton);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
entry.appendChild(row);
|
|
479
|
+
|
|
480
|
+
if (isNestedType) {
|
|
481
|
+
const children = document.createElement("div");
|
|
482
|
+
children.className = "frontmatter-children";
|
|
483
|
+
children.appendChild(
|
|
484
|
+
renderValueEditor(item, currentType, parentArray, index, onRefresh, onValueChange, depth + 1),
|
|
485
|
+
);
|
|
486
|
+
entry.appendChild(children);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return entry;
|
|
490
|
+
}
|