@diagrammo/dgmo 0.15.0 → 0.16.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/README.md +23 -10
- package/dist/advanced.cjs +53094 -0
- package/dist/advanced.d.cts +4690 -0
- package/dist/advanced.d.ts +4690 -0
- package/dist/advanced.js +52849 -0
- package/dist/auto.cjs +2298 -2069
- package/dist/auto.js +132 -109
- package/dist/auto.mjs +2294 -2065
- package/dist/cli.cjs +175 -152
- package/dist/editor.cjs +8 -9
- package/dist/editor.js +8 -9
- package/dist/highlight.cjs +8 -9
- package/dist/highlight.js +8 -9
- package/dist/index.cjs +2281 -2048
- package/dist/index.d.cts +45 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +2276 -2044
- package/dist/internal.cjs +2064 -1831
- package/dist/internal.d.cts +113 -113
- package/dist/internal.d.ts +113 -113
- package/dist/internal.js +2059 -1826
- package/dist/pert.cjs +325 -0
- package/dist/pert.d.cts +542 -0
- package/dist/pert.d.ts +542 -0
- package/dist/pert.js +294 -0
- package/docs/language-reference.md +83 -66
- package/gallery/fixtures/area.dgmo +3 -3
- package/gallery/fixtures/bar-stacked.dgmo +5 -5
- package/gallery/fixtures/boxes-and-lines.dgmo +2 -2
- package/gallery/fixtures/c4-full.dgmo +8 -8
- package/gallery/fixtures/class-full.dgmo +2 -2
- package/gallery/fixtures/doughnut.dgmo +6 -6
- package/gallery/fixtures/flowchart-colors.dgmo +3 -3
- package/gallery/fixtures/function.dgmo +3 -3
- package/gallery/fixtures/gantt-full.dgmo +9 -9
- package/gallery/fixtures/gantt.dgmo +7 -7
- package/gallery/fixtures/infra-full.dgmo +6 -6
- package/gallery/fixtures/infra.dgmo +2 -2
- package/gallery/fixtures/kanban.dgmo +9 -9
- package/gallery/fixtures/line.dgmo +2 -2
- package/gallery/fixtures/multi-line.dgmo +3 -3
- package/gallery/fixtures/org-full.dgmo +6 -6
- package/gallery/fixtures/quadrant.dgmo +2 -2
- package/gallery/fixtures/sankey.dgmo +9 -9
- package/gallery/fixtures/scatter.dgmo +3 -3
- package/gallery/fixtures/sequence-tags-protocols.dgmo +8 -8
- package/gallery/fixtures/sequence-tags.dgmo +7 -7
- package/gallery/fixtures/sitemap-full.dgmo +7 -7
- package/gallery/fixtures/slope.dgmo +5 -5
- package/gallery/fixtures/spr-eras.dgmo +9 -9
- package/gallery/fixtures/timeline.dgmo +3 -3
- package/gallery/fixtures/venn.dgmo +3 -3
- package/package.json +28 -3
- package/src/advanced.ts +730 -0
- package/src/auto/index.ts +14 -13
- package/src/boxes-and-lines/layout.ts +481 -445
- package/src/boxes-and-lines/renderer.ts +5 -1
- package/src/c4/parser.ts +8 -8
- package/src/c4/renderer.ts +15 -8
- package/src/chart-types.ts +0 -5
- package/src/chart.ts +18 -9
- package/src/class/parser.ts +8 -15
- package/src/class/renderer.ts +17 -6
- package/src/cli.ts +15 -13
- package/src/completion-types.ts +28 -0
- package/src/completion.ts +28 -21
- package/src/cycle/layout.ts +2 -2
- package/src/cycle/parser.ts +14 -0
- package/src/cycle/renderer.ts +6 -3
- package/src/d3.ts +1537 -1164
- package/src/echarts.ts +37 -20
- package/src/editor/dgmo.grammar +1 -3
- package/src/editor/dgmo.grammar.js +8 -8
- package/src/editor/dgmo.grammar.terms.js +11 -12
- package/src/editor/highlight-api.ts +0 -1
- package/src/editor/highlight.ts +0 -1
- package/src/er/parser.ts +19 -20
- package/src/er/renderer.ts +20 -8
- package/src/gantt/calculator.ts +1 -11
- package/src/gantt/parser.ts +17 -17
- package/src/gantt/renderer.ts +9 -6
- package/src/graph/flowchart-parser.ts +19 -85
- package/src/graph/flowchart-renderer.ts +4 -9
- package/src/graph/layout.ts +0 -2
- package/src/graph/state-parser.ts +17 -62
- package/src/graph/state-renderer.ts +4 -9
- package/src/index.ts +17 -1
- package/src/infra/parser.ts +40 -30
- package/src/infra/renderer.ts +9 -6
- package/src/internal.ts +9 -721
- package/src/journey-map/parser.ts +10 -3
- package/src/journey-map/renderer.ts +3 -1
- package/src/kanban/parser.ts +12 -8
- package/src/kanban/renderer.ts +3 -1
- package/src/mindmap/layout.ts +1 -1
- package/src/mindmap/parser.ts +3 -3
- package/src/mindmap/renderer.ts +2 -1
- package/src/org/parser.ts +3 -3
- package/src/org/renderer.ts +5 -4
- package/src/pert/layout.ts +1 -1
- package/src/pert/monte-carlo.ts +2 -2
- package/src/pert/parser.ts +10 -10
- package/src/pert/renderer.ts +7 -2
- package/src/pert/types.ts +1 -1
- package/src/pyramid/parser.ts +12 -0
- package/src/raci/parser.ts +44 -14
- package/src/raci/renderer.ts +3 -2
- package/src/raci/types.ts +4 -3
- package/src/ring/parser.ts +12 -0
- package/src/sequence/parser.ts +15 -9
- package/src/sequence/renderer.ts +2 -5
- package/src/sitemap/layout.ts +0 -2
- package/src/sitemap/parser.ts +12 -38
- package/src/sitemap/renderer.ts +13 -13
- package/src/sitemap/types.ts +0 -1
- package/src/tech-radar/interactive.ts +1 -1
- package/src/tech-radar/renderer.ts +6 -4
- package/src/tech-radar/types.ts +2 -0
- package/src/utils/arrows.ts +3 -28
- package/src/utils/legend-d3.ts +12 -6
- package/src/utils/legend-layout.ts +1 -1
- package/src/utils/legend-types.ts +1 -1
- package/src/utils/parsing.ts +64 -35
- package/src/utils/tag-groups.ts +109 -30
- package/src/wireframe/layout.ts +11 -7
- package/src/wireframe/parser.ts +4 -4
- package/src/wireframe/renderer.ts +5 -2
package/src/utils/tag-groups.ts
CHANGED
|
@@ -9,8 +9,9 @@ import {
|
|
|
9
9
|
tagShorthandRemovedMessage,
|
|
10
10
|
type DgmoError,
|
|
11
11
|
} from '../diagnostics';
|
|
12
|
+
import { RECOGNIZED_COLOR_NAMES } from '../colors';
|
|
12
13
|
|
|
13
|
-
/** A single entry inside a tag group: `Value
|
|
14
|
+
/** A single entry inside a tag group: `Value color` */
|
|
14
15
|
export interface TagEntry {
|
|
15
16
|
value: string;
|
|
16
17
|
color: string;
|
|
@@ -32,7 +33,7 @@ interface TagBlockMatch {
|
|
|
32
33
|
name: string;
|
|
33
34
|
alias: string | undefined;
|
|
34
35
|
colorHint: string | undefined;
|
|
35
|
-
/** Inline tag values parsed from single-line form (e.g., `tag Priority as p High
|
|
36
|
+
/** Inline tag values parsed from single-line form (e.g., `tag Priority as p High red, Low blue`) */
|
|
36
37
|
inlineValues?: string[];
|
|
37
38
|
/**
|
|
38
39
|
* If the heading used the legacy `tag Name <alias>` (bare shorthand)
|
|
@@ -51,8 +52,8 @@ interface TagBlockMatch {
|
|
|
51
52
|
* Returns the cleaned text and whether the keyword was present.
|
|
52
53
|
*
|
|
53
54
|
* Examples:
|
|
54
|
-
* "NA
|
|
55
|
-
* "Done
|
|
55
|
+
* "NA gray default" → { text: "NA gray", isDefault: true }
|
|
56
|
+
* "Done green" → { text: "Done green", isDefault: false }
|
|
56
57
|
*/
|
|
57
58
|
export function stripDefaultModifier(text: string): {
|
|
58
59
|
text: string;
|
|
@@ -90,7 +91,7 @@ export function isTagBlockHeading(trimmed: string): boolean {
|
|
|
90
91
|
/**
|
|
91
92
|
* Parse a tag declaration line: `tag Name [as <alias>] [Values...]`
|
|
92
93
|
*
|
|
93
|
-
* Canonical form
|
|
94
|
+
* Canonical form: `tag Priority as p High red, Low blue` (universal §1.5).
|
|
94
95
|
*
|
|
95
96
|
* Legacy forms still parse for graceful degradation but set
|
|
96
97
|
* `legacyForm` on the result so the caller can emit
|
|
@@ -117,12 +118,26 @@ export function parseTagDeclaration(line: string): TagBlockMatch | null {
|
|
|
117
118
|
let restStartIdx = 1;
|
|
118
119
|
|
|
119
120
|
// Locate any keyword separator (`as` or legacy `alias`) that appears
|
|
120
|
-
// BEFORE the first inline-value token. Inline values are
|
|
121
|
-
//
|
|
121
|
+
// BEFORE the first inline-value token. Inline values are recognized by
|
|
122
|
+
// a comma in the line: scan tokens for one. Under §1.5 trailing-token
|
|
123
|
+
// syntax there's no `(color)` marker anymore — a comma anywhere after
|
|
124
|
+
// the name span signals that inline values follow.
|
|
122
125
|
let valueStart = tokens.length;
|
|
123
126
|
for (let i = 1; i < tokens.length; i++) {
|
|
124
|
-
if (tokens[i].includes('
|
|
127
|
+
if (tokens[i].includes(',')) {
|
|
128
|
+
// valueStart is the FIRST token of the first inline value, which is
|
|
129
|
+
// the token immediately following the alias / keyword span. Walk
|
|
130
|
+
// back to the start of the value span by finding the most recent
|
|
131
|
+
// word boundary — but for the simple heuristic here, the inline
|
|
132
|
+
// value list starts at the previous non-keyword token.
|
|
125
133
|
valueStart = i;
|
|
134
|
+
// The token containing the comma might be `High` (in `High red,`)
|
|
135
|
+
// or `red,` (in `High red,` if tokenized differently). Treat the
|
|
136
|
+
// value span as starting at the token BEFORE the first comma
|
|
137
|
+
// unless that token is the alias / keyword.
|
|
138
|
+
// Simpler: use this index as a coarse upper bound. The keyword
|
|
139
|
+
// search below uses [1, valueStart) — anything past `as`/`alias`
|
|
140
|
+
// belongs to the value span.
|
|
126
141
|
break;
|
|
127
142
|
}
|
|
128
143
|
}
|
|
@@ -170,16 +185,77 @@ export function parseTagDeclaration(line: string): TagBlockMatch | null {
|
|
|
170
185
|
} else {
|
|
171
186
|
// No `as`/`alias` keyword — try legacy bare-shorthand. The trailing
|
|
172
187
|
// token of the name span (just before inline values) is the alias
|
|
173
|
-
// candidate; if it passes the universal alias regex
|
|
174
|
-
//
|
|
175
|
-
|
|
188
|
+
// candidate; if it passes the universal alias regex AND is NOT a
|
|
189
|
+
// recognized palette color (§1.5 escape hatch), accept it.
|
|
190
|
+
//
|
|
191
|
+
// When inline values are present (valueStart < tokens.length), the
|
|
192
|
+
// tokens immediately before the first value-segment-with-color form
|
|
193
|
+
// the (name + alias) prefix. The first value contains at least the
|
|
194
|
+
// value name + trailing color, so we walk back to find where it
|
|
195
|
+
// starts: skip the trailing color token, then 1+ name tokens.
|
|
196
|
+
const isColorWord = (s: string): boolean =>
|
|
197
|
+
(RECOGNIZED_COLOR_NAMES as readonly string[]).includes(s);
|
|
198
|
+
|
|
199
|
+
if (valueStart < tokens.length) {
|
|
200
|
+
// Inline values are present (we found a comma at valueStart).
|
|
201
|
+
// The first value's last token is at index commaIdx; strip the
|
|
202
|
+
// comma to inspect. Walk back to determine the value name length.
|
|
203
|
+
const commaTokenIdx = valueStart;
|
|
204
|
+
// Find where the first value starts: the value contains at least
|
|
205
|
+
// 1 word + optional trailing color. Walk back from commaTokenIdx
|
|
206
|
+
// while the previous tokens look like value-name words (i.e. not
|
|
207
|
+
// a recognized alias-shaped lowercase short token that is followed
|
|
208
|
+
// by a value start).
|
|
209
|
+
// Simpler heuristic: pre-comma trailing color is the last token if
|
|
210
|
+
// it's a recognized color (after stripping comma). The value's
|
|
211
|
+
// name is the token immediately before that. So the value spans
|
|
212
|
+
// (firstValueStart..=commaTokenIdx). The "name + alias" prefix
|
|
213
|
+
// is [0, firstValueStart).
|
|
214
|
+
const lastBeforeComma = tokens[commaTokenIdx].replace(/,$/, '');
|
|
215
|
+
// value = `<name word(s)> <color>` if trailing token is a recognized
|
|
216
|
+
// palette word; otherwise value = `<name word(s)>` (no color).
|
|
217
|
+
const firstValueStart = isColorWord(lastBeforeComma)
|
|
218
|
+
? commaTokenIdx - 1
|
|
219
|
+
: commaTokenIdx;
|
|
220
|
+
// Now firstValueStart points at the first token of value #1.
|
|
221
|
+
// [0, firstValueStart) is the `<name + optional alias>` prefix.
|
|
222
|
+
const prefixEnd = firstValueStart;
|
|
223
|
+
const aliasCandidate = prefixEnd > 1 ? tokens[prefixEnd - 1] : undefined;
|
|
224
|
+
if (
|
|
225
|
+
aliasCandidate &&
|
|
226
|
+
isAliasToken(aliasCandidate) &&
|
|
227
|
+
!isColorWord(aliasCandidate)
|
|
228
|
+
) {
|
|
229
|
+
alias = aliasCandidate;
|
|
230
|
+
legacyForm = 'bare-shorthand';
|
|
231
|
+
name = tokens
|
|
232
|
+
.slice(0, prefixEnd - 1)
|
|
233
|
+
.map((t) => stripQuotes(t))
|
|
234
|
+
.join(' ');
|
|
235
|
+
restStartIdx = prefixEnd;
|
|
236
|
+
} else {
|
|
237
|
+
name = tokens
|
|
238
|
+
.slice(0, prefixEnd)
|
|
239
|
+
.map((t) => stripQuotes(t))
|
|
240
|
+
.join(' ');
|
|
241
|
+
restStartIdx = prefixEnd;
|
|
242
|
+
}
|
|
243
|
+
} else if (tokens[0][0] === '"' || tokens[0][0] === "'") {
|
|
176
244
|
// Quoted name. Check the next token for legacy bare alias.
|
|
177
|
-
if (
|
|
245
|
+
if (
|
|
246
|
+
tokens.length > 1 &&
|
|
247
|
+
isAliasToken(tokens[1]) &&
|
|
248
|
+
!isColorWord(tokens[1])
|
|
249
|
+
) {
|
|
178
250
|
alias = tokens[1];
|
|
179
251
|
legacyForm = 'bare-shorthand';
|
|
180
252
|
restStartIdx = 2;
|
|
181
253
|
}
|
|
182
|
-
} else if (
|
|
254
|
+
} else if (
|
|
255
|
+
valueStart > 1 &&
|
|
256
|
+
isAliasToken(tokens[valueStart - 1]) &&
|
|
257
|
+
!isColorWord(tokens[valueStart - 1])
|
|
258
|
+
) {
|
|
183
259
|
// Bare shorthand at the end of the name span.
|
|
184
260
|
alias = tokens[valueStart - 1];
|
|
185
261
|
legacyForm = 'bare-shorthand';
|
|
@@ -207,12 +283,16 @@ export function parseTagDeclaration(line: string): TagBlockMatch | null {
|
|
|
207
283
|
.filter(Boolean);
|
|
208
284
|
}
|
|
209
285
|
|
|
210
|
-
// Trailing
|
|
286
|
+
// Trailing recognized-color token on the name itself (no inline values).
|
|
287
|
+
// Per §1.5 universal trailing-token: case-sensitive lowercase match.
|
|
211
288
|
if (!inlineValues || inlineValues.length === 0) {
|
|
212
|
-
const
|
|
213
|
-
if (
|
|
214
|
-
|
|
215
|
-
|
|
289
|
+
const lastSpaceIdx = name.lastIndexOf(' ');
|
|
290
|
+
if (lastSpaceIdx > 0) {
|
|
291
|
+
const trailing = name.substring(lastSpaceIdx + 1);
|
|
292
|
+
if ((RECOGNIZED_COLOR_NAMES as readonly string[]).includes(trailing)) {
|
|
293
|
+
colorHint = trailing;
|
|
294
|
+
name = name.substring(0, lastSpaceIdx).trimEnd();
|
|
295
|
+
}
|
|
216
296
|
}
|
|
217
297
|
}
|
|
218
298
|
|
|
@@ -418,25 +498,21 @@ export function injectDefaultTagMetadata(
|
|
|
418
498
|
*
|
|
419
499
|
* 1. Programmatic override (from render API / CLI flag) — highest priority
|
|
420
500
|
* 2. Diagram-level `active-tag` option (from parsed source)
|
|
421
|
-
* 3.
|
|
501
|
+
* 3. Auto-activate first declared tag group
|
|
502
|
+
* 4. No coloring (null)
|
|
422
503
|
*
|
|
423
504
|
* The sentinel value `"none"` (case-insensitive) at any level means
|
|
424
|
-
* "suppress tag coloring."
|
|
505
|
+
* "suppress tag coloring." Diagrams with tag groups render colored by
|
|
506
|
+
* default across every render path (CLI, export, share-link, app); use
|
|
507
|
+
* `active-tag none` to opt out.
|
|
425
508
|
*
|
|
426
|
-
*
|
|
427
|
-
* opt-in: either the source carries `active-tag <name>` or the caller
|
|
428
|
-
* (typically the app on user click) supplies a programmatic override.
|
|
429
|
-
* Static exports therefore render the legend as a row of collapsed
|
|
430
|
-
* pills with nodes uncolored — consistent with the app's pre-click
|
|
431
|
-
* default.
|
|
432
|
-
*
|
|
433
|
-
* @param _tagGroups Declared tag groups (kept for API stability; unused since auto-activation removed)
|
|
509
|
+
* @param tagGroups Declared tag groups (only `.name` is used)
|
|
434
510
|
* @param explicitActiveTag Value of `active-tag` option from parsed diagram, if any
|
|
435
511
|
* @param programmaticOverride Value from render API / CLI; `undefined` = not set,
|
|
436
512
|
* `null` or `''` = explicitly no coloring
|
|
437
513
|
*/
|
|
438
514
|
export function resolveActiveTagGroup(
|
|
439
|
-
|
|
515
|
+
tagGroups: ReadonlyArray<{ name: string }>,
|
|
440
516
|
explicitActiveTag: string | undefined,
|
|
441
517
|
programmaticOverride?: string | null
|
|
442
518
|
): string | null {
|
|
@@ -453,7 +529,10 @@ export function resolveActiveTagGroup(
|
|
|
453
529
|
return explicitActiveTag;
|
|
454
530
|
}
|
|
455
531
|
|
|
456
|
-
// 3.
|
|
532
|
+
// 3. Auto-activate first declared group
|
|
533
|
+
if (tagGroups.length > 0) return tagGroups[0].name;
|
|
534
|
+
|
|
535
|
+
// 4. No tag groups → no coloring
|
|
457
536
|
return null;
|
|
458
537
|
}
|
|
459
538
|
|
package/src/wireframe/layout.ts
CHANGED
|
@@ -333,7 +333,8 @@ function layoutElement(
|
|
|
333
333
|
|
|
334
334
|
// Container — layout children
|
|
335
335
|
const isInlineRow =
|
|
336
|
-
el.metadata
|
|
336
|
+
el.metadata['_inlineRow'] === 'true' ||
|
|
337
|
+
el.metadata['_labelField'] === 'true';
|
|
337
338
|
const padTop = isInlineRow ? 0 : GROUP_PADDING_TOP;
|
|
338
339
|
const padBottom = isInlineRow ? 0 : GROUP_PADDING_BOTTOM;
|
|
339
340
|
const padX = isInlineRow ? 0 : GROUP_PADDING_X;
|
|
@@ -402,8 +403,8 @@ function allocateEqualWidths(
|
|
|
402
403
|
function getElementHeight(el: WireframeElement): number {
|
|
403
404
|
if (el.type === 'heading') {
|
|
404
405
|
return el.headingLevel === 2
|
|
405
|
-
? (ELEMENT_HEIGHTS
|
|
406
|
-
: (ELEMENT_HEIGHTS
|
|
406
|
+
? (ELEMENT_HEIGHTS['subheading'] ?? 36)
|
|
407
|
+
: (ELEMENT_HEIGHTS['heading'] ?? 48);
|
|
407
408
|
}
|
|
408
409
|
|
|
409
410
|
if (el.type === 'textInput' && el.fieldVariant === 'textarea') {
|
|
@@ -421,11 +422,11 @@ function getElementHeight(el: WireframeElement): number {
|
|
|
421
422
|
if (el.type === 'image') {
|
|
422
423
|
if (el.imageHint === 'round') return 80;
|
|
423
424
|
if (el.imageHint === 'wide') return 80;
|
|
424
|
-
return ELEMENT_HEIGHTS
|
|
425
|
+
return ELEMENT_HEIGHTS['image'] ?? 120;
|
|
425
426
|
}
|
|
426
427
|
|
|
427
428
|
// Label-field wrapper
|
|
428
|
-
if (el.metadata
|
|
429
|
+
if (el.metadata['_labelField'] === 'true') {
|
|
429
430
|
return 36; // input height
|
|
430
431
|
}
|
|
431
432
|
|
|
@@ -434,7 +435,7 @@ function getElementHeight(el: WireframeElement): number {
|
|
|
434
435
|
|
|
435
436
|
function getSpacingAfter(el: WireframeElement): number {
|
|
436
437
|
if (el.type === 'heading' && el.headingLevel === 2) {
|
|
437
|
-
return SPACING_AFTER
|
|
438
|
+
return SPACING_AFTER['subheading'] ?? 12;
|
|
438
439
|
}
|
|
439
440
|
return SPACING_AFTER[el.type] ?? 8;
|
|
440
441
|
}
|
|
@@ -448,7 +449,10 @@ function computeFieldAlignX(children: WireframeElement[]): number {
|
|
|
448
449
|
let labelFieldCount = 0;
|
|
449
450
|
|
|
450
451
|
for (const child of children) {
|
|
451
|
-
if (
|
|
452
|
+
if (
|
|
453
|
+
child.metadata['_labelField'] === 'true' &&
|
|
454
|
+
child.children.length >= 2
|
|
455
|
+
) {
|
|
452
456
|
const labelEl = child.children[0];
|
|
453
457
|
const labelWidth = labelEl.label.length * CHAR_WIDTH;
|
|
454
458
|
maxLabelWidth = Math.max(maxLabelWidth, labelWidth);
|
package/src/wireframe/parser.ts
CHANGED
|
@@ -650,7 +650,7 @@ export function parseWireframe(content: string): ParsedWireframe {
|
|
|
650
650
|
wrapper.isContainer = true;
|
|
651
651
|
wrapper.orientation = 'horizontal';
|
|
652
652
|
wrapper.children = children;
|
|
653
|
-
wrapper.metadata
|
|
653
|
+
wrapper.metadata['_inlineRow'] = 'true';
|
|
654
654
|
pushElement(wrapper);
|
|
655
655
|
}
|
|
656
656
|
|
|
@@ -718,7 +718,7 @@ export function parseWireframe(content: string): ParsedWireframe {
|
|
|
718
718
|
}
|
|
719
719
|
}
|
|
720
720
|
|
|
721
|
-
// Indented tag entry: `Value
|
|
721
|
+
// Indented tag entry: `Value color` or `Value color default`
|
|
722
722
|
if (indent > 0 && currentTagGroup) {
|
|
723
723
|
const { text: cleanEntry, isDefault } = stripDefaultModifier(trimmed);
|
|
724
724
|
const { label, color } = extractColor(cleanEntry);
|
|
@@ -736,7 +736,7 @@ export function parseWireframe(content: string): ParsedWireframe {
|
|
|
736
736
|
} else {
|
|
737
737
|
pushWarning(
|
|
738
738
|
lineNumber,
|
|
739
|
-
`Expected 'Value
|
|
739
|
+
`Expected 'Value color' in tag group '${currentTagGroup.name}'`
|
|
740
740
|
);
|
|
741
741
|
}
|
|
742
742
|
continue;
|
|
@@ -852,7 +852,7 @@ export function parseWireframe(content: string): ParsedWireframe {
|
|
|
852
852
|
wrapper.isContainer = true;
|
|
853
853
|
wrapper.orientation = 'horizontal';
|
|
854
854
|
wrapper.children.push(labelEl, fieldEl);
|
|
855
|
-
wrapper.metadata
|
|
855
|
+
wrapper.metadata['_labelField'] = 'true';
|
|
856
856
|
pushElement(wrapper);
|
|
857
857
|
}
|
|
858
858
|
} else {
|
|
@@ -268,7 +268,10 @@ function renderGroup(
|
|
|
268
268
|
const el = node.element;
|
|
269
269
|
|
|
270
270
|
// Inline rows and label-field wrappers — no group chrome, just render children
|
|
271
|
-
if (
|
|
271
|
+
if (
|
|
272
|
+
el.metadata['_inlineRow'] === 'true' ||
|
|
273
|
+
el.metadata['_labelField'] === 'true'
|
|
274
|
+
) {
|
|
272
275
|
for (const child of node.children) {
|
|
273
276
|
renderNode(g, child, ctx, depth);
|
|
274
277
|
}
|
|
@@ -637,7 +640,7 @@ function renderText(
|
|
|
637
640
|
const el = node.element;
|
|
638
641
|
|
|
639
642
|
// Check if this is a label-field wrapper
|
|
640
|
-
if (el.metadata
|
|
643
|
+
if (el.metadata['_labelField'] === 'true' && el.children.length >= 2) {
|
|
641
644
|
for (const child of node.children) {
|
|
642
645
|
renderNode(g, child, ctx, 0);
|
|
643
646
|
}
|