@miragon/wardley-dsl 0.7.0 → 0.7.1

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 CHANGED
@@ -1,10 +1,10 @@
1
1
  # @miragon/wardley-dsl
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@miragon/wardley-dsl)](https://www.npmjs.com/package/@miragon/wardley-dsl)
4
- [![License: MIT](https://img.shields.io/github/license/Miragon/wardley-maps-modeler)](https://github.com/Miragon/wardley-maps-modeler/blob/main/LICENSE)
4
+ [![License: MIT](https://img.shields.io/github/license/Miragon/modeler-suite)](https://github.com/Miragon/modeler-suite/blob/main/modelers/wardley-maps/LICENSE)
5
5
 
6
6
  DOM-free bridge between the [Online-Wardley-Maps](https://docs.onlinewardleymaps.com/) text DSL and
7
- the `WardleyMap` model — a lossless round-trip.
7
+ the `WardleyMap` model, as a lossless round-trip.
8
8
 
9
9
  ## Install
10
10
 
@@ -15,7 +15,7 @@ npm install @miragon/wardley-dsl
15
15
  ## Usage
16
16
 
17
17
  ```ts
18
- import { parseDSL, serializeDSL } from '@miragon/wardley-dsl';
18
+ import { parseDSL, serializeDSL } from "@miragon/wardley-dsl";
19
19
 
20
20
  const map = parseDSL(`title Tea Shop
21
21
  component Kettle [0.43, 0.35]
@@ -31,7 +31,7 @@ the end, numbers like `0.80` as `0.8`. Where the text file is the source of trut
31
31
  file under Git), write an edited map back with `patchDSL` instead:
32
32
 
33
33
  ```ts
34
- import { parseDSL, patchDSL } from '@miragon/wardley-dsl';
34
+ import { parseDSL, patchDSL } from "@miragon/wardley-dsl";
35
35
 
36
36
  const map = parseDSL(fileText);
37
37
  // … the user moves, renames, adds or deletes something …
@@ -57,12 +57,12 @@ an element holds an id the text does not give it until the text is read again. `
57
57
  tells, by the ids of `map`, which id each element carries once `serializeDSL(map)` is read back:
58
58
 
59
59
  ```ts
60
- import { readBackIds } from '@miragon/wardley-dsl';
60
+ import { readBackIds } from "@miragon/wardley-dsl";
61
61
 
62
- readBackIds(editedMap).get('shape_42'); // 'cmp_hot_water'
62
+ readBackIds(editedMap).get("shape_42"); // 'cmp_hot_water'
63
63
  ```
64
64
 
65
- Part of the [Wardley Maps](https://github.com/Miragon/wardley-maps-modeler) monorepo.
65
+ Part of the [Wardley Maps Modeler](https://github.com/Miragon/modeler-suite/tree/main/modelers/wardley-maps) in the [Miragon modeler suite](https://github.com/Miragon/modeler-suite).
66
66
 
67
67
  ## License
68
68
 
package/dist/index.cjs CHANGED
@@ -465,7 +465,7 @@ function unknownStatementMessage(line) {
465
465
  const core = linkCore(line);
466
466
  if (/->|\+('[^']*')?(<>|>|<)/.test(core)) return "Link needs a name on both sides";
467
467
  const flowValue = /\+'[^']*'/.exec(core);
468
- if (flowValue) return `Flow ${flowValue[0]} has no direction \u2014 add ">", "<" or "<>"`;
468
+ if (flowValue) return `Flow ${flowValue[0]} has no direction: add ">", "<" or "<>"`;
469
469
  return `Unknown statement "${line.split(/\s/)[0]}"`;
470
470
  }
471
471
  function buildEdges(links, idOfName, unresolved, labelOf, built) {
@@ -595,7 +595,7 @@ var MapReader = class {
595
595
  }
596
596
  /** For a line that looks like a known construct but cannot be parsed. */
597
597
  failed(line) {
598
- this.keep(line, "Line not understood \u2014 kept as written");
598
+ this.keep(line, "Line not understood: kept as written");
599
599
  }
600
600
  // A reference binds to the name as written first, so `X 2` stays bound to an explicit "X 2" even
601
601
  // when a duplicate "X" was renamed to "X 2"; the serializer then writes that reference by the
@@ -610,7 +610,7 @@ var MapReader = class {
610
610
  setConfig(keyword, update) {
611
611
  const earlier = this.lineThatSetConfig.get(keyword);
612
612
  if (earlier !== void 0) {
613
- this.diag(`Repeated "${keyword}" \u2014 replaces the one on line ${earlier}`);
613
+ this.diag(`Repeated "${keyword}": replaces the one on line ${earlier}`);
614
614
  }
615
615
  this.lineThatSetConfig.set(keyword, this.lineNo);
616
616
  const configLines2 = this.configLinesByKeyword.get(keyword) ?? [];
@@ -648,7 +648,7 @@ var MapReader = class {
648
648
  return true;
649
649
  }
650
650
  this.keywordLinks.push(link);
651
- if (leftDeclared) this.diag(`Link: "${link.right}" not found \u2014 read as a "${kw}" statement`);
651
+ if (leftDeclared) this.diag(`Link: "${link.right}" not found; read as a "${kw}" statement`);
652
652
  return false;
653
653
  }
654
654
  /** Clamps a normalized value to [0,1] — with a diagnostic instead of a later validation crash. */
@@ -664,7 +664,7 @@ var MapReader = class {
664
664
  }
665
665
  /** A suffix written in front of the coordinates is part of the name or text (OWM). */
666
666
  reportMisplacedSuffix(groups, where, fix) {
667
- if (groups.length) this.diag(`"${groups.join(" ")}" ${where} \u2014 ${fix}`);
667
+ if (groups.length) this.diag(`"${groups.join(" ")}" ${where}: ${fix}`);
668
668
  }
669
669
  /**
670
670
  * A text as the serializer writes it. Its comment markers are protected only by flow values
@@ -675,7 +675,7 @@ var MapReader = class {
675
675
  const written = escapeCommentMarkers(text);
676
676
  if (written !== text) {
677
677
  this.diag(
678
- `"${text}" read as "${written}" \u2014 "//" or "/*" there would start a comment once saved`,
678
+ `"${text}" read as "${written}", because "//" or "/*" there would start a comment once saved`,
679
679
  line,
680
680
  source
681
681
  );
@@ -688,7 +688,7 @@ var MapReader = class {
688
688
  const name = this.namesInUse.claim(base);
689
689
  if (name !== base) {
690
690
  this.diag(
691
- `Duplicate name "${sourceName}" \u2014 renamed to "${name}"; links bind to the first "${sourceName}"`,
691
+ `Duplicate name "${sourceName}": renamed to "${name}"; links bind to the first "${sourceName}"`,
692
692
  atLine,
693
693
  atText
694
694
  );
@@ -702,20 +702,20 @@ var MapReader = class {
702
702
  this.blockPipeline = this.lastPipeline;
703
703
  this.recordBlockLine(this.blockPipeline, "open");
704
704
  this.blockOpening = { line: this.lineNo, text: this.currentLine };
705
- } else this.diag('Ignored "{" \u2014 a block must directly follow a pipeline line');
705
+ } else this.diag('Ignored "{": a block must directly follow a pipeline line');
706
706
  this.lastPipeline = null;
707
707
  }
708
708
  closeBlock() {
709
709
  if (this.blockPipeline) {
710
710
  this.recordBlockLine(this.blockPipeline, "close");
711
711
  this.blockPipeline = null;
712
- } else this.diag('Ignored "}" \u2014 no pipeline block is open');
712
+ } else this.diag('Ignored "}": no pipeline block is open');
713
713
  this.lastPipeline = null;
714
714
  }
715
715
  endUnclosedBlock() {
716
716
  if (!this.blockPipeline) return;
717
717
  this.diag(
718
- `Pipeline block of "${this.blockPipeline.name}" is never closed \u2014 add "}"`,
718
+ `Pipeline block of "${this.blockPipeline.name}" is never closed: add "}"`,
719
719
  this.blockOpening.line,
720
720
  this.blockOpening.text
721
721
  );
@@ -755,7 +755,7 @@ var MapReader = class {
755
755
  if (blockCommentStart) {
756
756
  const { line, text: startText } = blockCommentStart;
757
757
  this.diag(
758
- 'Block comment "/*" is never closed \u2014 the rest of the file is a comment',
758
+ 'Block comment "/*" is never closed: the rest of the file is a comment',
759
759
  line,
760
760
  startText
761
761
  );
@@ -856,7 +856,7 @@ var MapReader = class {
856
856
  }
857
857
  if (splitAtCoords(after)?.name) {
858
858
  this.diag(
859
- `Component with [visibility, maturity] inside the block of pipeline "${blockPipeline.name}" is not a child \u2014 use [maturity]`
859
+ `Component with [visibility, maturity] inside the block of pipeline "${blockPipeline.name}" is not a child: use [maturity]`
860
860
  );
861
861
  }
862
862
  return false;
@@ -924,7 +924,7 @@ var MapReader = class {
924
924
  let body = after;
925
925
  let opensBlock = false;
926
926
  while (body.endsWith("{")) {
927
- if (opensBlock) this.diag('Ignored "{" \u2014 a block must directly follow a pipeline line');
927
+ if (opensBlock) this.diag('Ignored "{": a block must directly follow a pipeline line');
928
928
  opensBlock = true;
929
929
  body = body.slice(0, -1).trim();
930
930
  }
@@ -991,7 +991,7 @@ var MapReader = class {
991
991
  if (problem) this.diag(problem);
992
992
  if (!Number.isInteger(coords.a) || !Number.isInteger(coords.b)) {
993
993
  this.diag(
994
- `Map size ${coords.a}\xD7${coords.b} is not in whole pixels \u2014 OWM only reads whole-pixel sizes`
994
+ `Map size ${coords.a}\xD7${coords.b} is not in whole pixels: OWM only reads whole-pixel sizes`
995
995
  );
996
996
  }
997
997
  }
@@ -1020,7 +1020,7 @@ var MapReader = class {
1020
1020
  });
1021
1021
  if (written.length !== 1 && !(written.length === 3 && written.every(Boolean))) {
1022
1022
  const read = [label, ...ends ?? []].join("->");
1023
- this.diag(`y-axis takes "Label" or "Label->Bottom->Top" \u2014 read as "${read}"`);
1023
+ this.diag(`y-axis takes "Label" or "Label->Bottom->Top": read as "${read}"`);
1024
1024
  }
1025
1025
  }
1026
1026
  readAnnotationsBox(line, after) {
@@ -1028,7 +1028,7 @@ var MapReader = class {
1028
1028
  if (!split) {
1029
1029
  return this.keep(
1030
1030
  line,
1031
- "Annotations box has no position \u2014 not used; add [visibility, maturity]"
1031
+ "Annotations box has no position: not used; add [visibility, maturity]"
1032
1032
  );
1033
1033
  }
1034
1034
  this.reportTextBefore(split.name);
@@ -1043,7 +1043,7 @@ var MapReader = class {
1043
1043
  if (!Number.isSafeInteger(number)) return this.failed(line);
1044
1044
  const found = parsePositions(after.replace(/^\s*\d+\s*/, ""));
1045
1045
  if (!found) {
1046
- return this.keep(line, "Annotation has no position \u2014 not drawn; add [visibility, maturity]");
1046
+ return this.keep(line, "Annotation has no position: not drawn; add [visibility, maturity]");
1047
1047
  }
1048
1048
  if (!found.tuples.length) return this.failed(line);
1049
1049
  for (const unreadable of found.unreadable) this.diag(unreadableNumberMessage(unreadable));
@@ -1110,7 +1110,7 @@ var MapReader = class {
1110
1110
  */
1111
1111
  readMethod(line, after, kw) {
1112
1112
  if (this.pushComponent(after, kw)) return;
1113
- if (!after) return this.keep(line, `${kw}: needs a component name \u2014 not used`);
1113
+ if (!after) return this.keep(line, `${kw}: needs a component name; not used`);
1114
1114
  this.pendingMethod.push({
1115
1115
  name: after,
1116
1116
  method: kw,
@@ -1282,7 +1282,7 @@ var MapReader = class {
1282
1282
  this.keepLine(p.raw, p.lineNo, p.text);
1283
1283
  if (!component) {
1284
1284
  this.diag(
1285
- `Pipeline "${p.name}" has no range \u2014 not drawn; add [start, end] or child components`,
1285
+ `Pipeline "${p.name}" has no range: not drawn; add [start, end] or child components`,
1286
1286
  p.lineNo,
1287
1287
  p.text
1288
1288
  );
@@ -1295,7 +1295,7 @@ var MapReader = class {
1295
1295
  const widened = range.start !== writtenRange.start || range.end !== writtenRange.end;
1296
1296
  if (widened && !writtenRange.fromChildren) {
1297
1297
  this.diag(
1298
- `Pipeline "${p.name}" range is empty or reversed \u2014 changed to [${range.start}, ${range.end}]`,
1298
+ `Pipeline "${p.name}" range is empty or reversed: changed to [${range.start}, ${range.end}]`,
1299
1299
  p.lineNo,
1300
1300
  p.text
1301
1301
  );
@@ -1344,7 +1344,7 @@ var MapReader = class {
1344
1344
  const component = this.elements[index];
1345
1345
  const earlier = evolveLineOf.get(component.id);
1346
1346
  if (earlier !== void 0) {
1347
- const message = `Repeated evolve for "${ev.name}" \u2014 replaces the one on line ${earlier}`;
1347
+ const message = `Repeated evolve for "${ev.name}": replaces the one on line ${earlier}`;
1348
1348
  this.diag(message, ev.lineNo, ev.text);
1349
1349
  }
1350
1350
  evolveLineOf.set(component.id, ev.lineNo);
@@ -1372,7 +1372,7 @@ var MapReader = class {
1372
1372
  const el = this.elements[index];
1373
1373
  const replaced = el.decorators?.method;
1374
1374
  if (replaced && replaced !== pm.method) {
1375
- const message = `${pm.method}: "${pm.name}" already has the method "${replaced}" \u2014 replaced`;
1375
+ const message = `${pm.method}: replaces the method "${replaced}" of "${pm.name}"`;
1376
1376
  this.diag(message, pm.lineNo, pm.text);
1377
1377
  }
1378
1378
  this.elements[index] = { ...el, decorators: { ...el.decorators, method: pm.method } };
@@ -1383,7 +1383,7 @@ var MapReader = class {
1383
1383
  }
1384
1384
  };
1385
1385
  function renamedMessage(sourceName, name) {
1386
- return `Name "${sourceName}" renamed to "${name}" \u2014 a name cannot hold link operators ("->", "+>", "+<", "+'"), comment markers or a leading "{"`;
1386
+ return `Name "${sourceName}" renamed to "${name}", because a name cannot hold link operators ("->", "+>", "+<", "+'"), comment markers or a leading "{"`;
1387
1387
  }
1388
1388
  function withoutTrailingCarriageReturns(line) {
1389
1389
  let end = line.length;
@@ -1397,7 +1397,7 @@ function withoutClosersOfKeptComments(entries, report) {
1397
1397
  if (!entry.isComment && nextParse.insideBlockComment && text.includes("*/")) {
1398
1398
  text = text.replaceAll("*/", " ");
1399
1399
  report(
1400
- 'Ignored "*/" \u2014 this line is kept after an unclosed "/*" and would end that comment',
1400
+ 'Ignored "*/": this line is kept after an unclosed "/*" and would end that comment',
1401
1401
  entry.lineNo,
1402
1402
  entry.source
1403
1403
  );
@@ -1416,7 +1416,7 @@ function replacedConfigLines(unusedLines, config, report) {
1416
1416
  const replaced = configIsSet[unused.keyword];
1417
1417
  if (replaced) replacedIndexes.add(unused.index);
1418
1418
  const outcome = replaced ? `removed; another "${unused.keyword}" line sets it` : "not used";
1419
- report(`${unused.reason} \u2014 ${outcome}`, unused.line, unused.text);
1419
+ report(`${unused.reason}: ${outcome}`, unused.line, unused.text);
1420
1420
  }
1421
1421
  return replacedIndexes;
1422
1422
  }
@@ -1428,7 +1428,7 @@ function resolveUrlReferences(elements, refs, definitions, report, resolved) {
1428
1428
  if (earlier) {
1429
1429
  replaced.add(earlier);
1430
1430
  report(
1431
- `Repeated url definition "${definition.name}" \u2014 replaces the one on line ${earlier.lineNo}, which is kept unused`,
1431
+ `Repeated url definition "${definition.name}": replaces the one on line ${earlier.lineNo}, which is kept unused`,
1432
1432
  definition.lineNo,
1433
1433
  definition.text
1434
1434
  );
@@ -1441,7 +1441,7 @@ function resolveUrlReferences(elements, refs, definitions, report, resolved) {
1441
1441
  if (definition) used.add(definition);
1442
1442
  const address = definition?.address ?? (/^[a-z][\w+.-]*:\/\//i.test(ref) ? ref : void 0);
1443
1443
  if (!address) {
1444
- report(`url(${ref}) has no matching "url ${ref} [address]" line \u2014 ignored`, line, text);
1444
+ report(`url(${ref}) has no matching "url ${ref} [address]" line: ignored`, line, text);
1445
1445
  continue;
1446
1446
  }
1447
1447
  const el = elements[index];
@@ -1576,7 +1576,7 @@ function splitPipelineLine(body) {
1576
1576
  return { name: rest, range: null, suffixText: groups.join(" "), misplaced: [] };
1577
1577
  }
1578
1578
  function unreadableNumberMessage(text) {
1579
- return `Unreadable number in "${text}" \u2014 ignored`;
1579
+ return `Unreadable number in "${text}": ignored`;
1580
1580
  }
1581
1581
  function pipelineRange(p) {
1582
1582
  if (p.start !== void 0 && p.end !== void 0) {
@@ -1668,7 +1668,7 @@ function splitMisplacedEvolveSuffix(name) {
1668
1668
  return rest ? { name: rest, suffix: m[0] } : null;
1669
1669
  }
1670
1670
  function misplacedEvolveSuffixHint({ name, suffix }) {
1671
- return suffix.startsWith("(") ? ` \u2014 for component "${name}", write "${suffix}" after the target` : ` \u2014 for component "${name}", write "${suffix}" on its component line`;
1671
+ return suffix.startsWith("(") ? `; for component "${name}", write "${suffix}" after the target` : `; for component "${name}", write "${suffix}" on its component line`;
1672
1672
  }
1673
1673
  var NUMBER_TOKEN_RE = /(^|\s)([-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[-+]?\d+)?)(?=\s|\(|$)/gi;
1674
1674
  function parseEvolve(after, report) {
@@ -1707,7 +1707,7 @@ function sizeOutsideLimits(width, height) {
1707
1707
  const minimum = `${wardleySchemaModel.PLOT_MIN.width}\xD7${wardleySchemaModel.PLOT_MIN.height}`;
1708
1708
  const maximum = `${wardleySchemaModel.PLOT_MAX.width}\xD7${wardleySchemaModel.PLOT_MAX.height}`;
1709
1709
  const limit = below && above ? `outside ${minimum} to ${maximum}` : below ? `below the minimum ${minimum}` : `above the maximum ${maximum}`;
1710
- return `Map size ${width}\xD7${height} is ${limit} \u2014 drawn at ${drawnWidth}\xD7${drawnHeight}`;
1710
+ return `Map size ${width}\xD7${height} is ${limit}: drawn at ${drawnWidth}\xD7${drawnHeight}`;
1711
1711
  }
1712
1712
 
1713
1713
  // src/serializer.ts