@diagrammo/dgmo 0.2.8 → 0.2.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diagrammo/dgmo",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "DGMO diagram markup language — parser, renderer, and color system",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/chart.ts CHANGED
@@ -23,6 +23,7 @@ export interface ChartDataPoint {
23
23
  export interface ParsedChart {
24
24
  type: ChartType;
25
25
  title?: string;
26
+ titleLineNumber?: number;
26
27
  series?: string;
27
28
  xlabel?: string;
28
29
  ylabel?: string;
@@ -120,6 +121,7 @@ export function parseChart(
120
121
 
121
122
  if (key === 'title') {
122
123
  result.title = value;
124
+ result.titleLineNumber = lineNumber;
123
125
  continue;
124
126
  }
125
127
 
package/src/d3.ts CHANGED
@@ -139,6 +139,7 @@ export interface D3ExportDimensions {
139
139
  export interface ParsedD3 {
140
140
  type: D3ChartType | null;
141
141
  title: string | null;
142
+ titleLineNumber: number | null;
142
143
  orientation: 'horizontal' | 'vertical';
143
144
  periods: string[];
144
145
  data: D3DataItem[];
@@ -265,6 +266,7 @@ export function parseD3(content: string, palette?: PaletteColors): ParsedD3 {
265
266
  const result: ParsedD3 = {
266
267
  type: null,
267
268
  title: null,
269
+ titleLineNumber: null,
268
270
  orientation: 'horizontal',
269
271
  periods: [],
270
272
  data: [],
@@ -609,6 +611,7 @@ export function parseD3(content: string, palette?: PaletteColors): ParsedD3 {
609
611
 
610
612
  if (key === 'title') {
611
613
  result.title = line.substring(colonIndex + 1).trim();
614
+ result.titleLineNumber = lineNumber;
612
615
  if (result.type === 'quadrant') {
613
616
  result.quadrantTitleLineNumber = lineNumber;
614
617
  }
@@ -1120,15 +1123,27 @@ export function renderSlopeChart(
1120
1123
 
1121
1124
  // Title
1122
1125
  if (title) {
1123
- svg
1126
+ const titleEl = svg
1124
1127
  .append('text')
1128
+ .attr('class', 'chart-title')
1125
1129
  .attr('x', width / 2)
1126
1130
  .attr('y', 30)
1127
1131
  .attr('text-anchor', 'middle')
1128
1132
  .attr('fill', textColor)
1129
1133
  .attr('font-size', '20px')
1130
1134
  .attr('font-weight', '700')
1135
+ .style('cursor', onClickItem && parsed.titleLineNumber ? 'pointer' : 'default')
1131
1136
  .text(title);
1137
+
1138
+ if (parsed.titleLineNumber) {
1139
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
1140
+ if (onClickItem) {
1141
+ titleEl
1142
+ .on('click', () => onClickItem(parsed.titleLineNumber!))
1143
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
1144
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
1145
+ }
1146
+ }
1132
1147
  }
1133
1148
 
1134
1149
  // Period column headers
@@ -1501,15 +1516,27 @@ export function renderArcDiagram(
1501
1516
 
1502
1517
  // Title
1503
1518
  if (title) {
1504
- svg
1519
+ const titleEl = svg
1505
1520
  .append('text')
1521
+ .attr('class', 'chart-title')
1506
1522
  .attr('x', width / 2)
1507
1523
  .attr('y', 30)
1508
1524
  .attr('text-anchor', 'middle')
1509
1525
  .attr('fill', textColor)
1510
1526
  .attr('font-size', '20px')
1511
1527
  .attr('font-weight', '700')
1528
+ .style('cursor', onClickItem && parsed.titleLineNumber ? 'pointer' : 'default')
1512
1529
  .text(title);
1530
+
1531
+ if (parsed.titleLineNumber) {
1532
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
1533
+ if (onClickItem) {
1534
+ titleEl
1535
+ .on('click', () => onClickItem(parsed.titleLineNumber!))
1536
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
1537
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
1538
+ }
1539
+ }
1513
1540
  }
1514
1541
 
1515
1542
  // Build adjacency map for hover interactions
@@ -2745,15 +2772,27 @@ export function renderTimeline(
2745
2772
  .attr('transform', `translate(${margin.left},${margin.top})`);
2746
2773
 
2747
2774
  if (title) {
2748
- svg
2775
+ const titleEl = svg
2749
2776
  .append('text')
2777
+ .attr('class', 'chart-title')
2750
2778
  .attr('x', width / 2)
2751
2779
  .attr('y', 30)
2752
2780
  .attr('text-anchor', 'middle')
2753
2781
  .attr('fill', textColor)
2754
2782
  .attr('font-size', '20px')
2755
2783
  .attr('font-weight', '700')
2784
+ .style('cursor', onClickItem && parsed.titleLineNumber ? 'pointer' : 'default')
2756
2785
  .text(title);
2786
+
2787
+ if (parsed.titleLineNumber) {
2788
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
2789
+ if (onClickItem) {
2790
+ titleEl
2791
+ .on('click', () => onClickItem(parsed.titleLineNumber!))
2792
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
2793
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
2794
+ }
2795
+ }
2757
2796
  }
2758
2797
 
2759
2798
  renderEras(
@@ -2936,15 +2975,27 @@ export function renderTimeline(
2936
2975
  .attr('transform', `translate(${margin.left},${margin.top})`);
2937
2976
 
2938
2977
  if (title) {
2939
- svg
2978
+ const titleEl = svg
2940
2979
  .append('text')
2980
+ .attr('class', 'chart-title')
2941
2981
  .attr('x', width / 2)
2942
2982
  .attr('y', 30)
2943
2983
  .attr('text-anchor', 'middle')
2944
2984
  .attr('fill', textColor)
2945
2985
  .attr('font-size', '20px')
2946
2986
  .attr('font-weight', '700')
2987
+ .style('cursor', onClickItem && parsed.titleLineNumber ? 'pointer' : 'default')
2947
2988
  .text(title);
2989
+
2990
+ if (parsed.titleLineNumber) {
2991
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
2992
+ if (onClickItem) {
2993
+ titleEl
2994
+ .on('click', () => onClickItem(parsed.titleLineNumber!))
2995
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
2996
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
2997
+ }
2998
+ }
2948
2999
  }
2949
3000
 
2950
3001
  renderEras(
@@ -3188,15 +3239,27 @@ export function renderTimeline(
3188
3239
  .attr('transform', `translate(${margin.left},${margin.top})`);
3189
3240
 
3190
3241
  if (title) {
3191
- svg
3242
+ const titleEl = svg
3192
3243
  .append('text')
3244
+ .attr('class', 'chart-title')
3193
3245
  .attr('x', width / 2)
3194
3246
  .attr('y', 30)
3195
3247
  .attr('text-anchor', 'middle')
3196
3248
  .attr('fill', textColor)
3197
3249
  .attr('font-size', '20px')
3198
3250
  .attr('font-weight', '700')
3251
+ .style('cursor', onClickItem && parsed.titleLineNumber ? 'pointer' : 'default')
3199
3252
  .text(title);
3253
+
3254
+ if (parsed.titleLineNumber) {
3255
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
3256
+ if (onClickItem) {
3257
+ titleEl
3258
+ .on('click', () => onClickItem(parsed.titleLineNumber!))
3259
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
3260
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
3261
+ }
3262
+ }
3200
3263
  }
3201
3264
 
3202
3265
  renderEras(
@@ -3472,15 +3535,27 @@ export function renderTimeline(
3472
3535
  .attr('transform', `translate(${margin.left},${margin.top})`);
3473
3536
 
3474
3537
  if (title) {
3475
- svg
3538
+ const titleEl = svg
3476
3539
  .append('text')
3540
+ .attr('class', 'chart-title')
3477
3541
  .attr('x', width / 2)
3478
3542
  .attr('y', 30)
3479
3543
  .attr('text-anchor', 'middle')
3480
3544
  .attr('fill', textColor)
3481
3545
  .attr('font-size', '20px')
3482
3546
  .attr('font-weight', '700')
3547
+ .style('cursor', onClickItem && parsed.titleLineNumber ? 'pointer' : 'default')
3483
3548
  .text(title);
3549
+
3550
+ if (parsed.titleLineNumber) {
3551
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
3552
+ if (onClickItem) {
3553
+ titleEl
3554
+ .on('click', () => onClickItem(parsed.titleLineNumber!))
3555
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
3556
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
3557
+ }
3558
+ }
3484
3559
  }
3485
3560
 
3486
3561
  renderEras(
@@ -3767,15 +3842,27 @@ export function renderWordCloud(
3767
3842
  .style('background', bgColor);
3768
3843
 
3769
3844
  if (title) {
3770
- svg
3845
+ const titleEl = svg
3771
3846
  .append('text')
3847
+ .attr('class', 'chart-title')
3772
3848
  .attr('x', width / 2)
3773
3849
  .attr('y', 30)
3774
3850
  .attr('text-anchor', 'middle')
3775
3851
  .attr('fill', textColor)
3776
3852
  .attr('font-size', '20px')
3777
3853
  .attr('font-weight', '700')
3854
+ .style('cursor', onClickItem && parsed.titleLineNumber ? 'pointer' : 'default')
3778
3855
  .text(title);
3856
+
3857
+ if (parsed.titleLineNumber) {
3858
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
3859
+ if (onClickItem) {
3860
+ titleEl
3861
+ .on('click', () => onClickItem(parsed.titleLineNumber!))
3862
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
3863
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
3864
+ }
3865
+ }
3779
3866
  }
3780
3867
 
3781
3868
  const g = svg
@@ -3872,8 +3959,9 @@ function renderWordCloudAsync(
3872
3959
  .style('background', bgColor);
3873
3960
 
3874
3961
  if (title) {
3875
- svg
3962
+ const titleEl = svg
3876
3963
  .append('text')
3964
+ .attr('class', 'chart-title')
3877
3965
  .attr('x', width / 2)
3878
3966
  .attr('y', 30)
3879
3967
  .attr('text-anchor', 'middle')
@@ -3881,6 +3969,10 @@ function renderWordCloudAsync(
3881
3969
  .attr('font-size', '20px')
3882
3970
  .attr('font-weight', '700')
3883
3971
  .text(title);
3972
+
3973
+ if (parsed.titleLineNumber) {
3974
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
3975
+ }
3884
3976
  }
3885
3977
 
3886
3978
  const g = svg
@@ -4217,15 +4309,27 @@ export function renderVenn(
4217
4309
 
4218
4310
  // Title
4219
4311
  if (title) {
4220
- svg
4312
+ const titleEl = svg
4221
4313
  .append('text')
4314
+ .attr('class', 'chart-title')
4222
4315
  .attr('x', width / 2)
4223
4316
  .attr('y', 30)
4224
4317
  .attr('text-anchor', 'middle')
4225
4318
  .attr('fill', textColor)
4226
4319
  .attr('font-size', '20px')
4227
4320
  .attr('font-weight', '700')
4321
+ .style('cursor', onClickItem && parsed.titleLineNumber ? 'pointer' : 'default')
4228
4322
  .text(title);
4323
+
4324
+ if (parsed.titleLineNumber) {
4325
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
4326
+ if (onClickItem) {
4327
+ titleEl
4328
+ .on('click', () => onClickItem(parsed.titleLineNumber!))
4329
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
4330
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
4331
+ }
4332
+ }
4229
4333
  }
4230
4334
 
4231
4335
  // ── Clip-path definitions ──
@@ -4593,6 +4697,7 @@ export function renderQuadrant(
4593
4697
  if (title) {
4594
4698
  const titleText = svg
4595
4699
  .append('text')
4700
+ .attr('class', 'chart-title')
4596
4701
  .attr('x', width / 2)
4597
4702
  .attr('y', 30)
4598
4703
  .attr('text-anchor', 'middle')
@@ -4605,6 +4710,10 @@ export function renderQuadrant(
4605
4710
  )
4606
4711
  .text(title);
4607
4712
 
4713
+ if (quadrantTitleLineNumber) {
4714
+ titleText.attr('data-line-number', quadrantTitleLineNumber);
4715
+ }
4716
+
4608
4717
  if (onClickItem && quadrantTitleLineNumber) {
4609
4718
  titleText
4610
4719
  .on('click', () => onClickItem(quadrantTitleLineNumber))
package/src/echarts.ts CHANGED
@@ -54,6 +54,7 @@ export interface ParsedHeatmapRow {
54
54
  export interface ParsedEChart {
55
55
  type: EChartsChartType;
56
56
  title?: string;
57
+ titleLineNumber?: number;
57
58
  series?: string;
58
59
  seriesNames?: string[];
59
60
  seriesNameColors?: (string | undefined)[];
@@ -174,6 +175,7 @@ export function parseEChart(
174
175
 
175
176
  if (key === 'title') {
176
177
  result.title = value;
178
+ result.titleLineNumber = lineNumber;
177
179
  continue;
178
180
  }
179
181
 
@@ -436,6 +436,7 @@ export function parseFlowchart(
436
436
 
437
437
  if (key === 'title') {
438
438
  result.title = value;
439
+ result.titleLineNumber = lineNumber;
439
440
  continue;
440
441
  }
441
442
 
@@ -257,7 +257,6 @@ export function renderFlowchart(
257
257
  .append('svg')
258
258
  .attr('width', width)
259
259
  .attr('height', height)
260
- .style('background', palette.bg)
261
260
  .style('font-family', FONT_FAMILY);
262
261
 
263
262
  // Defs: arrowhead markers
@@ -305,7 +304,7 @@ export function renderFlowchart(
305
304
 
306
305
  // Title
307
306
  if (graph.title) {
308
- mainG
307
+ const titleEl = mainG
309
308
  .append('text')
310
309
  .attr('x', diagramW / 2)
311
310
  .attr('y', TITLE_FONT_SIZE)
@@ -313,8 +312,19 @@ export function renderFlowchart(
313
312
  .attr('fill', palette.text)
314
313
  .attr('font-size', TITLE_FONT_SIZE)
315
314
  .attr('font-weight', 'bold')
316
- .attr('class', 'fc-title')
315
+ .attr('class', 'fc-title chart-title')
316
+ .style('cursor', onClickItem && graph.titleLineNumber ? 'pointer' : 'default')
317
317
  .text(graph.title);
318
+
319
+ if (graph.titleLineNumber) {
320
+ titleEl.attr('data-line-number', graph.titleLineNumber);
321
+ if (onClickItem) {
322
+ titleEl
323
+ .on('click', () => onClickItem(graph.titleLineNumber!))
324
+ .on('mouseenter', function () { d3Selection.select(this).attr('opacity', 0.7); })
325
+ .on('mouseleave', function () { d3Selection.select(this).attr('opacity', 1); });
326
+ }
327
+ }
318
328
  }
319
329
 
320
330
  // Content group (offset by title)
@@ -425,7 +435,8 @@ export function renderFlowchart(
425
435
  .append('g')
426
436
  .attr('transform', `translate(${node.x}, ${node.y})`)
427
437
  .attr('class', 'fc-node')
428
- .attr('data-line-number', String(node.lineNumber));
438
+ .attr('data-line-number', String(node.lineNumber))
439
+ .attr('data-node-id', node.id);
429
440
 
430
441
  if (onClickItem) {
431
442
  nodeG.style('cursor', 'pointer').on('click', () => {
@@ -36,6 +36,7 @@ export interface GraphGroup {
36
36
  export interface ParsedGraph {
37
37
  type: 'flowchart';
38
38
  title?: string;
39
+ titleLineNumber?: number;
39
40
  direction: GraphDirection;
40
41
  nodes: GraphNode[];
41
42
  edges: GraphEdge[];
@@ -133,6 +133,7 @@ export interface SequenceGroup {
133
133
  */
134
134
  export interface ParsedSequenceDgmo {
135
135
  title: string | null;
136
+ titleLineNumber: number | null;
136
137
  participants: SequenceParticipant[];
137
138
  messages: SequenceMessage[];
138
139
  elements: SequenceElement[];
@@ -227,6 +228,7 @@ function measureIndent(line: string): number {
227
228
  export function parseSequenceDgmo(content: string): ParsedSequenceDgmo {
228
229
  const result: ParsedSequenceDgmo = {
229
230
  title: null,
231
+ titleLineNumber: null,
230
232
  participants: [],
231
233
  messages: [],
232
234
  elements: [],
@@ -367,6 +369,7 @@ export function parseSequenceDgmo(content: string): ParsedSequenceDgmo {
367
369
 
368
370
  if (key === 'title') {
369
371
  result.title = value;
372
+ result.titleLineNumber = lineNumber;
370
373
  continue;
371
374
  }
372
375
 
@@ -1229,8 +1229,9 @@ export function renderSequenceDiagram(
1229
1229
 
1230
1230
  // Render title
1231
1231
  if (title) {
1232
- svg
1232
+ const titleEl = svg
1233
1233
  .append('text')
1234
+ .attr('class', 'chart-title')
1234
1235
  .attr('x', svgWidth / 2)
1235
1236
  .attr('y', 30)
1236
1237
  .attr('text-anchor', 'middle')
@@ -1238,6 +1239,10 @@ export function renderSequenceDiagram(
1238
1239
  .attr('font-size', 20)
1239
1240
  .attr('font-weight', 'bold')
1240
1241
  .text(title);
1242
+
1243
+ if (parsed.titleLineNumber) {
1244
+ titleEl.attr('data-line-number', parsed.titleLineNumber);
1245
+ }
1241
1246
  }
1242
1247
 
1243
1248
  // Render group boxes (behind participant shapes)