@jxsuite/studio 0.23.2 → 0.25.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/studio.js +2311 -718
- package/dist/studio.js.map +121 -104
- package/package.json +8 -7
- package/src/browse/{browse-modal.js → browse-modal.ts} +9 -10
- package/src/browse/{browse.js → browse.ts} +109 -84
- package/src/canvas/{canvas-diff.js → canvas-diff.ts} +42 -35
- package/src/canvas/{canvas-helpers.js → canvas-helpers.ts} +25 -19
- package/src/canvas/{canvas-live-render.js → canvas-live-render.ts} +53 -63
- package/src/canvas/{canvas-render.js → canvas-render.ts} +110 -121
- package/src/canvas/{canvas-utils.js → canvas-utils.ts} +48 -44
- package/src/canvas/{nested-site-style.js → nested-site-style.ts} +3 -3
- package/src/editor/{component-inline-edit.js → component-inline-edit.ts} +45 -33
- package/src/editor/{content-inline-edit.js → content-inline-edit.ts} +27 -45
- package/src/editor/{context-menu.js → context-menu.ts} +38 -36
- package/src/editor/{convert-targets.js → convert-targets.ts} +15 -12
- package/src/editor/{convert-to-component.js → convert-to-component.ts} +25 -26
- package/src/editor/{convert-to-repeater.js → convert-to-repeater.ts} +60 -40
- package/src/editor/{inline-edit.js → inline-edit.ts} +91 -55
- package/src/editor/{inline-format.js → inline-format.ts} +46 -51
- package/src/editor/{insertion-helper.js → insertion-helper.ts} +47 -63
- package/src/editor/{shortcuts.js → shortcuts.ts} +45 -31
- package/src/editor/{slash-menu.js → slash-menu.ts} +34 -35
- package/src/files/{components.js → components.ts} +12 -15
- package/src/files/{file-ops.js → file-ops.ts} +36 -29
- package/src/files/{files.js → files.ts} +102 -84
- package/src/github/{github-auth.js → github-auth.ts} +3 -3
- package/src/github/{github-publish.js → github-publish.ts} +20 -18
- package/src/markdown/{md-allowlist.js → md-allowlist.ts} +5 -2
- package/src/markdown/{md-convert.js → md-convert.ts} +146 -169
- package/src/new-project/{new-project-modal.js → new-project-modal.ts} +16 -18
- package/src/panels/{activity-bar.js → activity-bar.ts} +26 -34
- package/src/panels/{ai-panel.js → ai-panel.ts} +30 -30
- package/src/panels/{block-action-bar.js → block-action-bar.ts} +64 -73
- package/src/panels/{canvas-dnd.js → canvas-dnd.ts} +44 -49
- package/src/panels/{data-explorer.js → data-explorer.ts} +21 -15
- package/src/panels/dnd.ts +417 -0
- package/src/panels/{editors.js → editors.ts} +43 -50
- package/src/panels/{elements-panel.js → elements-panel.ts} +30 -27
- package/src/panels/{events-panel.js → events-panel.ts} +33 -25
- package/src/panels/{git-panel.js → git-panel.ts} +97 -83
- package/src/panels/{head-panel.js → head-panel.ts} +117 -139
- package/src/panels/{imports-panel.js → imports-panel.ts} +69 -89
- package/src/panels/{layers-panel.js → layers-panel.ts} +61 -57
- package/src/panels/{left-panel.js → left-panel.ts} +56 -63
- package/src/panels/{overlays.js → overlays.ts} +28 -36
- package/src/panels/{panel-events.js → panel-events.ts} +53 -51
- package/src/panels/{preview-render.js → preview-render.ts} +20 -15
- package/src/panels/{properties-panel.js → properties-panel.ts} +212 -246
- package/src/panels/{pseudo-preview.js → pseudo-preview.ts} +9 -8
- package/src/panels/{quick-search.js → quick-search.ts} +16 -17
- package/src/panels/{right-panel.js → right-panel.ts} +41 -59
- package/src/panels/{shared.js → shared.ts} +8 -6
- package/src/panels/{signals-panel.js → signals-panel.ts} +322 -362
- package/src/panels/{statusbar.js → statusbar.ts} +14 -14
- package/src/panels/{style-inputs.js → style-inputs.ts} +66 -48
- package/src/panels/{style-panel.js → style-panel.ts} +235 -290
- package/src/panels/{style-utils.js → style-utils.ts} +32 -31
- package/src/panels/{stylebook-layers-panel.js → stylebook-layers-panel.ts} +22 -14
- package/src/panels/{stylebook-panel.js → stylebook-panel.ts} +127 -140
- package/src/panels/{tab-strip.js → tab-strip.ts} +12 -14
- package/src/panels/{toolbar.js → toolbar.ts} +68 -70
- package/src/panels/{welcome-screen.js → welcome-screen.ts} +14 -16
- package/src/{platform.js → platform.ts} +5 -3
- package/src/platforms/{devserver.js → devserver.ts} +53 -44
- package/src/{recent-projects.js → recent-projects.ts} +17 -12
- package/src/{resize-edges.js → resize-edges.ts} +18 -13
- package/src/services/{cem-export.js → cem-export.ts} +14 -7
- package/src/services/{code-services.js → code-services.ts} +29 -20
- package/src/services/{monaco-setup.js → monaco-setup.ts} +2 -3
- package/src/settings/{content-types-editor.js → content-types-editor.ts} +88 -67
- package/src/settings/{css-vars-editor.js → css-vars-editor.ts} +78 -51
- package/src/settings/{defs-editor.js → defs-editor.ts} +70 -56
- package/src/settings/{general-settings.js → general-settings.ts} +29 -28
- package/src/settings/{head-editor.js → head-editor.ts} +37 -35
- package/src/settings/{schema-field-ui.js → schema-field-ui.ts} +86 -76
- package/src/settings/{settings-modal.js → settings-modal.ts} +14 -16
- package/src/{site-context.js → site-context.ts} +35 -32
- package/src/{state.js → state.ts} +95 -78
- package/src/{store.js → store.ts} +60 -63
- package/src/{studio.js → studio.ts} +117 -119
- package/src/tabs/tab.ts +196 -0
- package/src/tabs/{transact.js → transact.ts} +107 -60
- package/src/types.ts +185 -0
- package/src/ui/{button-group.js → button-group.ts} +21 -21
- package/src/ui/{color-selector.js → color-selector.ts} +44 -37
- package/src/ui/{expression-editor.js → expression-editor.ts} +65 -40
- package/src/ui/{field-row.js → field-row.ts} +19 -2
- package/src/ui/{icons.js → icons.ts} +2 -2
- package/src/ui/{layers.js → layers.ts} +33 -24
- package/src/ui/{media-picker.js → media-picker.ts} +13 -9
- package/src/ui/{panel-resize.js → panel-resize.ts} +9 -4
- package/src/ui/{spectrum.js → spectrum.ts} +4 -4
- package/src/ui/{unit-selector.js → unit-selector.ts} +16 -19
- package/src/ui/{value-selector.js → value-selector.ts} +28 -28
- package/src/ui/{widgets.js → widgets.ts} +62 -15
- package/src/utils/{canvas-media.js → canvas-media.ts} +29 -14
- package/src/utils/edit-display.ts +298 -0
- package/src/utils/{google-fonts.js → google-fonts.ts} +14 -13
- package/src/utils/{inherited-style.js → inherited-style.ts} +15 -10
- package/src/utils/{studio-utils.js → studio-utils.ts} +35 -23
- package/src/{view.js → view.ts} +53 -55
- package/src/workspace/{workspace.js → workspace.ts} +44 -33
- package/src/panels/dnd.js +0 -426
- package/src/tabs/tab.js +0 -192
- package/src/utils/edit-display.js +0 -203
- /package/src/{reactivity.js → reactivity.ts} +0 -0
package/src/tabs/tab.js
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import { reactive, effectScope } from "../reactivity.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {{
|
|
5
|
-
* rightTab: string;
|
|
6
|
-
* canvasMode: string;
|
|
7
|
-
* zoom: number;
|
|
8
|
-
* activeMedia: string | null;
|
|
9
|
-
* activeSelector: string | null;
|
|
10
|
-
* editingFunction: FunctionEditDef | null;
|
|
11
|
-
* featureToggles: Record<string, boolean>;
|
|
12
|
-
* styleSections: Record<string, boolean>;
|
|
13
|
-
* inspectorSections: Record<string, boolean>;
|
|
14
|
-
* styleShorthands: Record<string, boolean>;
|
|
15
|
-
* styleFilter: string;
|
|
16
|
-
* styleFilterActive: boolean;
|
|
17
|
-
* stylebookSelection: string | null;
|
|
18
|
-
* stylebookTab: string;
|
|
19
|
-
* stylebookFilter: string;
|
|
20
|
-
* stylebookCustomizedOnly: boolean;
|
|
21
|
-
* settingsTab: string;
|
|
22
|
-
* gitStatus: GitStatusResult | null;
|
|
23
|
-
* gitBranches: GitBranchesResult | null;
|
|
24
|
-
* gitCommitMessage: string;
|
|
25
|
-
* gitLoading: boolean;
|
|
26
|
-
* gitError: string | null;
|
|
27
|
-
* gitDiffState: GitDiffState | null;
|
|
28
|
-
* pendingInlineEdit: InlineEditDef | null;
|
|
29
|
-
* }} TabUi
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @typedef {{
|
|
34
|
-
* document: Record<string, unknown>;
|
|
35
|
-
* selection: (string | number)[] | null;
|
|
36
|
-
* }} HistorySnapshot
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @typedef {{
|
|
41
|
-
* id: string;
|
|
42
|
-
* documentPath: string | null;
|
|
43
|
-
* fileHandle: FileSystemFileHandle | null;
|
|
44
|
-
* capabilities: { modes: string[] };
|
|
45
|
-
* scope: { stop(): void; run<T>(fn: () => T): T | undefined; [k: string]: unknown };
|
|
46
|
-
* doc: {
|
|
47
|
-
* document: JxMutableNode;
|
|
48
|
-
* content: { frontmatter: Record<string, unknown> };
|
|
49
|
-
* mode: string;
|
|
50
|
-
* sourceFormat: string | null;
|
|
51
|
-
* handlersSource: string | null;
|
|
52
|
-
* dirty: boolean;
|
|
53
|
-
* };
|
|
54
|
-
* session: {
|
|
55
|
-
* selection: (string | number)[] | null;
|
|
56
|
-
* hover: (string | number)[] | null;
|
|
57
|
-
* clipboard: JxMutableNode | null;
|
|
58
|
-
* documentStack: DocumentStackEntry[];
|
|
59
|
-
* ui: TabUi;
|
|
60
|
-
* canvas: {
|
|
61
|
-
* status: string;
|
|
62
|
-
* scope: { stop(): void; [k: string]: unknown } | null;
|
|
63
|
-
* error: string | null;
|
|
64
|
-
* pendingInlineEdit: InlineEditDef | null;
|
|
65
|
-
* };
|
|
66
|
-
* };
|
|
67
|
-
* history: {
|
|
68
|
-
* snapshots: HistorySnapshot[];
|
|
69
|
-
* index: number;
|
|
70
|
-
* };
|
|
71
|
-
* }} Tab
|
|
72
|
-
*/
|
|
73
|
-
|
|
74
|
-
/** @returns {TabUi} */
|
|
75
|
-
function createDefaultUi() {
|
|
76
|
-
return {
|
|
77
|
-
rightTab: "properties",
|
|
78
|
-
canvasMode: "edit",
|
|
79
|
-
zoom: 1,
|
|
80
|
-
activeMedia: null,
|
|
81
|
-
activeSelector: null,
|
|
82
|
-
editingFunction: null,
|
|
83
|
-
featureToggles: {},
|
|
84
|
-
styleSections: {},
|
|
85
|
-
inspectorSections: {},
|
|
86
|
-
styleShorthands: {},
|
|
87
|
-
styleFilter: "",
|
|
88
|
-
styleFilterActive: false,
|
|
89
|
-
stylebookSelection: null,
|
|
90
|
-
stylebookTab: "elements",
|
|
91
|
-
stylebookFilter: "",
|
|
92
|
-
stylebookCustomizedOnly: false,
|
|
93
|
-
settingsTab: "stylebook",
|
|
94
|
-
gitStatus: null,
|
|
95
|
-
gitBranches: null,
|
|
96
|
-
gitCommitMessage: "",
|
|
97
|
-
gitLoading: false,
|
|
98
|
-
gitError: null,
|
|
99
|
-
gitDiffState: null,
|
|
100
|
-
pendingInlineEdit: null,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const ALL_MODES = ["edit", "design", "preview", "source", "stylebook"];
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Create a new tab with reactive doc/session/history trees, owned by an effectScope.
|
|
108
|
-
*
|
|
109
|
-
* @param {{
|
|
110
|
-
* id: string;
|
|
111
|
-
* documentPath?: string | null;
|
|
112
|
-
* fileHandle?: FileSystemFileHandle | null;
|
|
113
|
-
* document: Record<string, unknown>;
|
|
114
|
-
* frontmatter?: Record<string, unknown>;
|
|
115
|
-
* sourceFormat?: string | null;
|
|
116
|
-
* capabilities?: { modes?: string[] };
|
|
117
|
-
* }} opts
|
|
118
|
-
* @returns {Tab}
|
|
119
|
-
*/
|
|
120
|
-
export function createTab({
|
|
121
|
-
id,
|
|
122
|
-
documentPath = null,
|
|
123
|
-
fileHandle = null,
|
|
124
|
-
document,
|
|
125
|
-
frontmatter,
|
|
126
|
-
sourceFormat = null,
|
|
127
|
-
capabilities,
|
|
128
|
-
}) {
|
|
129
|
-
const scope = effectScope();
|
|
130
|
-
|
|
131
|
-
const resolvedModes = capabilities?.modes ?? inferModes(documentPath, sourceFormat);
|
|
132
|
-
|
|
133
|
-
const tab = /** @type {Tab} */ (
|
|
134
|
-
/** @type {unknown} */ (
|
|
135
|
-
scope.run(() => ({
|
|
136
|
-
id,
|
|
137
|
-
documentPath,
|
|
138
|
-
fileHandle,
|
|
139
|
-
capabilities: { modes: resolvedModes },
|
|
140
|
-
scope,
|
|
141
|
-
doc: reactive({
|
|
142
|
-
document,
|
|
143
|
-
sourceFormat,
|
|
144
|
-
content: { frontmatter: frontmatter || {} },
|
|
145
|
-
mode:
|
|
146
|
-
sourceFormat === "md"
|
|
147
|
-
? "content"
|
|
148
|
-
: documentPath?.endsWith(".md")
|
|
149
|
-
? "content"
|
|
150
|
-
: "component",
|
|
151
|
-
handlersSource: null,
|
|
152
|
-
dirty: false,
|
|
153
|
-
}),
|
|
154
|
-
session: reactive({
|
|
155
|
-
selection: null,
|
|
156
|
-
hover: null,
|
|
157
|
-
clipboard: null,
|
|
158
|
-
documentStack: [],
|
|
159
|
-
ui: createDefaultUi(),
|
|
160
|
-
canvas: { status: "idle", scope: null, error: null, pendingInlineEdit: null },
|
|
161
|
-
}),
|
|
162
|
-
history: reactive({
|
|
163
|
-
snapshots: [{ document: structuredClone(document), selection: null }],
|
|
164
|
-
index: 0,
|
|
165
|
-
}),
|
|
166
|
-
}))
|
|
167
|
-
)
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
return tab;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* @param {string | null | undefined} documentPath
|
|
175
|
-
* @param {string | null} sourceFormat
|
|
176
|
-
* @returns {string[]}
|
|
177
|
-
*/
|
|
178
|
-
function inferModes(documentPath, sourceFormat) {
|
|
179
|
-
if (documentPath === "project.json") return ["stylebook", "source"];
|
|
180
|
-
if (sourceFormat === "md" || documentPath?.endsWith(".md"))
|
|
181
|
-
return ["edit", "design", "preview", "source"];
|
|
182
|
-
return ALL_MODES;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Dispose a tab — stops its effectScope, killing all effects created within it.
|
|
187
|
-
*
|
|
188
|
-
* @param {Tab} tab
|
|
189
|
-
*/
|
|
190
|
-
export function disposeTab(tab) {
|
|
191
|
-
tab.scope.stop();
|
|
192
|
-
}
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Edit-mode display transforms — extracted from studio.js (Phase 4i). Pure stateless functions that
|
|
3
|
-
* convert document trees for visual editing (template expressions, $map, $switch, empty
|
|
4
|
-
* placeholders).
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Convert a template string to a displayable expression for edit mode. Replaces ${expr} with ❮ expr
|
|
9
|
-
* ❯ so the runtime renders it as literal text.
|
|
10
|
-
*
|
|
11
|
-
* @param {string} str
|
|
12
|
-
*/
|
|
13
|
-
export function templateToEditDisplay(str) {
|
|
14
|
-
return str.replace(/\$\{([^}]+)\}/g, "\u276A $1 \u276B");
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Reverse templateToEditDisplay: walk all text nodes in `el` and replace ❪ expr ❫ back to ${expr}
|
|
19
|
-
* so the user edits raw template syntax.
|
|
20
|
-
*
|
|
21
|
-
* @param {HTMLElement} el
|
|
22
|
-
*/
|
|
23
|
-
export function restoreTemplateExpressions(el) {
|
|
24
|
-
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
25
|
-
while (walker.nextNode()) {
|
|
26
|
-
const node = /** @type {Text} */ (walker.currentNode);
|
|
27
|
-
if (node.data.includes("\u276A")) {
|
|
28
|
-
node.data = node.data.replace(/\u276A\s*(.*?)\s*\u276B/g, "${$1}");
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Prepare a document for edit-mode rendering. Replaces template strings with readable literal text,
|
|
35
|
-
* $prototype:Array with placeholders, and $ref bindings with display labels. Preserves state so the
|
|
36
|
-
* runtime can still initialise scope.
|
|
37
|
-
*
|
|
38
|
-
* @param {JxMutableNode} node
|
|
39
|
-
* @returns {JxMutableNode}
|
|
40
|
-
*/
|
|
41
|
-
export function prepareForEditMode(node) {
|
|
42
|
-
if (!node || typeof node !== "object") return node;
|
|
43
|
-
if (Array.isArray(node)) return node.map(prepareForEditMode);
|
|
44
|
-
|
|
45
|
-
const /** @type {Record<string, unknown>} */ obj = /** @type {Record<string, unknown>} */ (node);
|
|
46
|
-
|
|
47
|
-
/** @type {Record<string, unknown>} */
|
|
48
|
-
const out = {};
|
|
49
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
50
|
-
if (k === "state" || k === "$media" || k === "$props" || k === "$elements") {
|
|
51
|
-
out[k] = v; // preserve as-is for runtime resolution
|
|
52
|
-
} else if (k === "children") {
|
|
53
|
-
if (Array.isArray(v)) {
|
|
54
|
-
out.children = v.map(prepareForEditMode);
|
|
55
|
-
} else if (
|
|
56
|
-
v &&
|
|
57
|
-
typeof v === "object" &&
|
|
58
|
-
/** @type {Record<string, unknown>} */ (v).$prototype === "Array"
|
|
59
|
-
) {
|
|
60
|
-
// Wrap the map template in a visual repeater perimeter
|
|
61
|
-
const vObj = /** @type {Record<string, unknown>} */ (v);
|
|
62
|
-
const template = vObj.map;
|
|
63
|
-
if (template && typeof template === "object") {
|
|
64
|
-
out.children = [
|
|
65
|
-
{
|
|
66
|
-
tagName: "div",
|
|
67
|
-
className: "repeater-perimeter",
|
|
68
|
-
children: [prepareForEditMode(/** @type {JxMutableNode} */ (template))],
|
|
69
|
-
},
|
|
70
|
-
];
|
|
71
|
-
} else {
|
|
72
|
-
out.children = [];
|
|
73
|
-
}
|
|
74
|
-
} else {
|
|
75
|
-
out.children = prepareForEditMode(/** @type {JxMutableNode} */ (v));
|
|
76
|
-
}
|
|
77
|
-
} else if (k === "cases" && obj.$switch && v && typeof v === "object") {
|
|
78
|
-
// Replace $switch cases with a placeholder showing the first case or a label
|
|
79
|
-
const caseKeys = Object.keys(v);
|
|
80
|
-
if (caseKeys.length > 0) {
|
|
81
|
-
const firstCase = /** @type {Record<string, unknown>} */ (v)[caseKeys[0]];
|
|
82
|
-
if (
|
|
83
|
-
firstCase &&
|
|
84
|
-
typeof firstCase === "object" &&
|
|
85
|
-
!(/** @type {Record<string, unknown>} */ (firstCase).$ref)
|
|
86
|
-
) {
|
|
87
|
-
out.children = [prepareForEditMode(firstCase)];
|
|
88
|
-
} else {
|
|
89
|
-
out.children = [
|
|
90
|
-
{
|
|
91
|
-
tagName: "div",
|
|
92
|
-
textContent: `[$switch: ${caseKeys.join(" | ")}]`,
|
|
93
|
-
style: {
|
|
94
|
-
fontFamily: "'SF Mono', 'Fira Code', monospace",
|
|
95
|
-
fontSize: "11px",
|
|
96
|
-
padding: "6px 10px",
|
|
97
|
-
background: "color-mix(in srgb, var(--danger) 8%, transparent)",
|
|
98
|
-
border: "1px dashed color-mix(in srgb, var(--danger) 40%, transparent)",
|
|
99
|
-
borderRadius: "4px",
|
|
100
|
-
color: "var(--danger)",
|
|
101
|
-
fontStyle: "italic",
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
];
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
} else if (k === "style") {
|
|
108
|
-
// Replace template strings in style values with empty strings
|
|
109
|
-
if (v && typeof v === "object") {
|
|
110
|
-
/** @type {Record<string, unknown>} */
|
|
111
|
-
const s = {};
|
|
112
|
-
for (const [sk, sv] of Object.entries(v)) {
|
|
113
|
-
s[sk] = typeof sv === "string" && sv.includes("${") ? "" : sv;
|
|
114
|
-
}
|
|
115
|
-
out.style = s;
|
|
116
|
-
} else {
|
|
117
|
-
out.style = v;
|
|
118
|
-
}
|
|
119
|
-
} else if (typeof v === "string" && v.includes("${")) {
|
|
120
|
-
// Template string in a display property → show raw expression
|
|
121
|
-
out[k] = templateToEditDisplay(v);
|
|
122
|
-
} else if (v && typeof v === "object" && /** @type {Record<string, unknown>} */ (v).$ref) {
|
|
123
|
-
// $ref binding → show ref path as literal text
|
|
124
|
-
const ref = /** @type {string} */ (/** @type {Record<string, unknown>} */ (v).$ref);
|
|
125
|
-
const label = ref.startsWith("#/state/") ? ref.slice(8) : ref;
|
|
126
|
-
out[k] = `{${label}}`;
|
|
127
|
-
} else {
|
|
128
|
-
out[k] = prepareForEditMode(/** @type {JxMutableNode} */ (v));
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Mark empty elements with placeholder classes for design-mode visibility
|
|
133
|
-
if (out.tagName && !out.textContent && !out.innerHTML) {
|
|
134
|
-
const hasChildren = Array.isArray(out.children) && out.children.length > 0;
|
|
135
|
-
if (!hasChildren) {
|
|
136
|
-
const tag = /** @type {string} */ (out.tagName);
|
|
137
|
-
const textTags = new Set([
|
|
138
|
-
"p",
|
|
139
|
-
"h1",
|
|
140
|
-
"h2",
|
|
141
|
-
"h3",
|
|
142
|
-
"h4",
|
|
143
|
-
"h5",
|
|
144
|
-
"h6",
|
|
145
|
-
"blockquote",
|
|
146
|
-
"li",
|
|
147
|
-
"dt",
|
|
148
|
-
"dd",
|
|
149
|
-
"th",
|
|
150
|
-
"td",
|
|
151
|
-
"span",
|
|
152
|
-
"strong",
|
|
153
|
-
"em",
|
|
154
|
-
"small",
|
|
155
|
-
"mark",
|
|
156
|
-
"code",
|
|
157
|
-
"abbr",
|
|
158
|
-
"q",
|
|
159
|
-
"sub",
|
|
160
|
-
"sup",
|
|
161
|
-
"time",
|
|
162
|
-
"a",
|
|
163
|
-
"button",
|
|
164
|
-
"label",
|
|
165
|
-
"legend",
|
|
166
|
-
"caption",
|
|
167
|
-
"summary",
|
|
168
|
-
"pre",
|
|
169
|
-
"option",
|
|
170
|
-
]);
|
|
171
|
-
const containerTags = new Set([
|
|
172
|
-
"div",
|
|
173
|
-
"section",
|
|
174
|
-
"article",
|
|
175
|
-
"aside",
|
|
176
|
-
"header",
|
|
177
|
-
"footer",
|
|
178
|
-
"main",
|
|
179
|
-
"nav",
|
|
180
|
-
"figure",
|
|
181
|
-
"figcaption",
|
|
182
|
-
"details",
|
|
183
|
-
"fieldset",
|
|
184
|
-
"form",
|
|
185
|
-
"ul",
|
|
186
|
-
"ol",
|
|
187
|
-
"dl",
|
|
188
|
-
"table",
|
|
189
|
-
]);
|
|
190
|
-
if (textTags.has(tag)) {
|
|
191
|
-
out.className = out.className
|
|
192
|
-
? out.className + " empty-text-placeholder"
|
|
193
|
-
: "empty-text-placeholder";
|
|
194
|
-
} else if (containerTags.has(tag)) {
|
|
195
|
-
out.className = out.className
|
|
196
|
-
? out.className + " empty-container-placeholder"
|
|
197
|
-
: "empty-container-placeholder";
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return out;
|
|
203
|
-
}
|
|
File without changes
|