@diagrammo/dgmo 0.2.25 → 0.2.27
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/cli.cjs +28 -28
- package/dist/index.cjs +23 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +23 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +5 -0
- package/src/initiative-status/parser.ts +24 -7
- package/src/sharing.ts +3 -1
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -249,6 +249,11 @@ async function main(): Promise<void> {
|
|
|
249
249
|
noInput();
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
// Strip any ANSI escape codes that may have leaked into input
|
|
253
|
+
// (e.g. from shell aliases like cat=bat with --color always)
|
|
254
|
+
// eslint-disable-next-line no-control-regex
|
|
255
|
+
content = content.replace(/\x1b\[[0-9;]*m/g, '');
|
|
256
|
+
|
|
252
257
|
// Resolve org chart imports (tags: and import: directives)
|
|
253
258
|
if (opts.input && parseDgmoChartType(content) === 'org') {
|
|
254
259
|
const inputPath = resolve(opts.input);
|
|
@@ -26,6 +26,7 @@ export function looksLikeInitiativeStatus(content: string): boolean {
|
|
|
26
26
|
const lines = content.split('\n');
|
|
27
27
|
let hasArrow = false;
|
|
28
28
|
let hasStatus = false;
|
|
29
|
+
let hasIndentedArrow = false;
|
|
29
30
|
for (const line of lines) {
|
|
30
31
|
const trimmed = line.trim();
|
|
31
32
|
if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('//')) continue;
|
|
@@ -33,9 +34,12 @@ export function looksLikeInitiativeStatus(content: string): boolean {
|
|
|
33
34
|
if (trimmed.match(/^title\s*:/i)) continue;
|
|
34
35
|
if (trimmed.includes('->')) hasArrow = true;
|
|
35
36
|
if (/\|\s*(done|wip|todo|na)\s*$/i.test(trimmed)) hasStatus = true;
|
|
37
|
+
// Indented arrow is a strong signal — only initiative-status uses this
|
|
38
|
+
const isIndented = line.length > 0 && line !== trimmed && /^\s/.test(line);
|
|
39
|
+
if (isIndented && trimmed.startsWith('->')) hasIndentedArrow = true;
|
|
36
40
|
if (hasArrow && hasStatus) return true;
|
|
37
41
|
}
|
|
38
|
-
return
|
|
42
|
+
return hasIndentedArrow;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
// ============================================================
|
|
@@ -44,7 +48,7 @@ export function looksLikeInitiativeStatus(content: string): boolean {
|
|
|
44
48
|
|
|
45
49
|
function parseStatus(raw: string, line: number, diagnostics: DgmoError[]): InitiativeStatus {
|
|
46
50
|
const trimmed = raw.trim().toLowerCase();
|
|
47
|
-
if (!trimmed) return
|
|
51
|
+
if (!trimmed) return 'na';
|
|
48
52
|
if (VALID_STATUSES.includes(trimmed)) return trimmed as InitiativeStatus;
|
|
49
53
|
|
|
50
54
|
// Unknown status — emit warning with suggestion
|
|
@@ -70,6 +74,7 @@ export function parseInitiativeStatus(content: string): ParsedInitiativeStatus {
|
|
|
70
74
|
const lines = content.split('\n');
|
|
71
75
|
const nodeLabels = new Set<string>();
|
|
72
76
|
let currentGroup: ISGroup | null = null;
|
|
77
|
+
let lastNodeLabel: string | null = null;
|
|
73
78
|
|
|
74
79
|
for (let i = 0; i < lines.length; i++) {
|
|
75
80
|
const lineNum = i + 1; // 1-based
|
|
@@ -120,7 +125,18 @@ export function parseInitiativeStatus(content: string): ParsedInitiativeStatus {
|
|
|
120
125
|
|
|
121
126
|
// Edge: contains `->`
|
|
122
127
|
if (trimmed.includes('->')) {
|
|
123
|
-
|
|
128
|
+
let edgeText = trimmed;
|
|
129
|
+
// Indented `-> Target` shorthand — prepend the last node label as source
|
|
130
|
+
if (trimmed.startsWith('->')) {
|
|
131
|
+
if (!lastNodeLabel) {
|
|
132
|
+
result.diagnostics.push(
|
|
133
|
+
makeDgmoError(lineNum, 'Indented edge has no preceding node to use as source', 'warning')
|
|
134
|
+
);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
edgeText = `${lastNodeLabel} ${trimmed}`;
|
|
138
|
+
}
|
|
139
|
+
const edge = parseEdgeLine(edgeText, lineNum, result.diagnostics);
|
|
124
140
|
if (edge) result.edges.push(edge);
|
|
125
141
|
continue;
|
|
126
142
|
}
|
|
@@ -128,6 +144,7 @@ export function parseInitiativeStatus(content: string): ParsedInitiativeStatus {
|
|
|
128
144
|
// Node: everything else
|
|
129
145
|
const node = parseNodeLine(trimmed, lineNum, result.diagnostics);
|
|
130
146
|
if (node) {
|
|
147
|
+
lastNodeLabel = node.label;
|
|
131
148
|
if (nodeLabels.has(node.label)) {
|
|
132
149
|
result.diagnostics.push(
|
|
133
150
|
makeDgmoError(lineNum, `Duplicate node "${node.label}"`, 'warning')
|
|
@@ -156,7 +173,7 @@ export function parseInitiativeStatus(content: string): ParsedInitiativeStatus {
|
|
|
156
173
|
);
|
|
157
174
|
// Auto-create an implicit node
|
|
158
175
|
if (!result.nodes.some((n) => n.label === edge.source)) {
|
|
159
|
-
result.nodes.push({ label: edge.source, status:
|
|
176
|
+
result.nodes.push({ label: edge.source, status: 'na', shape: inferParticipantType(edge.source), lineNumber: edge.lineNumber });
|
|
160
177
|
nodeLabels.add(edge.source);
|
|
161
178
|
}
|
|
162
179
|
}
|
|
@@ -165,7 +182,7 @@ export function parseInitiativeStatus(content: string): ParsedInitiativeStatus {
|
|
|
165
182
|
makeDgmoError(edge.lineNumber, `Edge target "${edge.target}" is not a declared node`, 'warning')
|
|
166
183
|
);
|
|
167
184
|
if (!result.nodes.some((n) => n.label === edge.target)) {
|
|
168
|
-
result.nodes.push({ label: edge.target, status:
|
|
185
|
+
result.nodes.push({ label: edge.target, status: 'na', shape: inferParticipantType(edge.target), lineNumber: edge.lineNumber });
|
|
169
186
|
nodeLabels.add(edge.target);
|
|
170
187
|
}
|
|
171
188
|
}
|
|
@@ -193,7 +210,7 @@ function parseNodeLine(
|
|
|
193
210
|
const status = parseStatus(statusRaw, lineNum, diagnostics);
|
|
194
211
|
return { label, status, shape: inferParticipantType(label), lineNumber: lineNum };
|
|
195
212
|
}
|
|
196
|
-
return { label: trimmed, status:
|
|
213
|
+
return { label: trimmed, status: 'na', shape: inferParticipantType(trimmed), lineNumber: lineNum };
|
|
197
214
|
}
|
|
198
215
|
|
|
199
216
|
function parseEdgeLine(
|
|
@@ -218,7 +235,7 @@ function parseEdgeLine(
|
|
|
218
235
|
}
|
|
219
236
|
|
|
220
237
|
// Extract status from end (after last |)
|
|
221
|
-
let status: InitiativeStatus =
|
|
238
|
+
let status: InitiativeStatus = 'na';
|
|
222
239
|
const lastPipe = rest.lastIndexOf('|');
|
|
223
240
|
if (lastPipe >= 0) {
|
|
224
241
|
const statusRaw = rest.slice(lastPipe + 1).trim();
|
package/src/sharing.ts
CHANGED
|
@@ -47,7 +47,9 @@ export function encodeDiagramUrl(
|
|
|
47
47
|
hash += `&tag=${encodeURIComponent(options.viewState.activeTagGroup)}`;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
// Encode in both query param AND hash fragment — some share mechanisms
|
|
51
|
+
// strip one or the other (iOS share sheet strips #, AirDrop strips ?)
|
|
52
|
+
return { url: `${baseUrl}?${hash}#${hash}` };
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
/**
|