reladraw 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
@@ -68,7 +68,7 @@ It is [plain Markdown](.claude/skills/reladraw/SKILL.md) with the syntax referen
68
68
 
69
69
  ## Status
70
70
 
71
- Version 0.7.0. Early, but it runs: a parser, resolver and SVG renderer in TypeScript with no runtime dependencies, and a command-line tool that takes a text file and writes a standalone SVG. The comparison at the top of this page is that pipeline run on [`examples/arch.reladraw`](examples/arch.reladraw). What is still visibly off there is typography, not placement.
71
+ Version 0.7.1. Early, but it runs: a parser, resolver and SVG renderer in TypeScript with no runtime dependencies, and a command-line tool that takes a text file and writes a standalone SVG. The comparison at the top of this page is that pipeline run on [`examples/arch.reladraw`](examples/arch.reladraw). What is still visibly off there is typography, not placement.
72
72
 
73
73
  ```
74
74
  npm install -g reladraw
package/SYNTAX.md CHANGED
@@ -1,4 +1,4 @@
1
- # Syntax reference — 0.7.0
1
+ # Syntax reference — 0.7.1
2
2
 
3
3
  What the language accepts. The parser, resolver and SVG renderer implement all of it; the sections at the end record what is defective, unchecked or undecided.
4
4
 
@@ -1012,6 +1012,10 @@ That one was found by testing the lexer, not by rendering — and it could not h
1012
1012
 
1013
1013
  Pre-1.0, so the minor number is where a breaking change goes. Every removal below is refused by name with the replacement quoted, rather than dropped in silence — an older file stops with an error saying what to write instead.
1014
1014
 
1015
+ **0.7.1**
1016
+
1017
+ - A fix, no syntax change. An edge with `line: (path: straight)` and a clause such as `below m` could draw its text on top of `m`. The line now bends through the room left for the text, so the text sits clear of the node. Existing diagrams with such an edge will look different, and correct.
1018
+
1015
1019
  **0.7.0**
1016
1020
 
1017
1021
  - `line:` takes a bracket for everything about how the line is drawn: `path: curved | square | straight`, `corners: sharp | rounded`, `crossing: none | arc | gap | square`, `pattern: solid | dashed | dotted | dash-dot` and `thickness: thin | normal | thick` or a number. `line: red` still works, as the short form of `line: (color: red)`. Every default is how lines were drawn before, so no existing file changes.
package/dist/render.js CHANGED
@@ -450,8 +450,20 @@ function jointedLine(edge, ends, corridor, route, nodes, textWidth) {
450
450
  if (route) {
451
451
  if (square)
452
452
  return { points: route.points, mid: route.mid };
453
- const points = straighten(route.points, edge, nodes);
454
- return { points, mid: textSpot(points, textWidth) };
453
+ if (textWidth === 0) {
454
+ const points = straighten(route.points, edge, nodes);
455
+ return { points, mid: textSpot(points, textWidth) };
456
+ }
457
+ // The route pushed its run out far enough to hold the text clear of the
458
+ // boxes it passes, and that room is only on the run. So a straight line
459
+ // with a text keeps the text's point and straightens either side of it;
460
+ // cutting across the run would put the text back against the box.
461
+ const [before, after] = splitAt(route.points, route.mid);
462
+ const points = tidyRoute([
463
+ ...straighten(before, edge, nodes),
464
+ ...straighten(after, edge, nodes).slice(1),
465
+ ]);
466
+ return { points, mid: route.mid };
455
467
  }
456
468
  if (corridor) {
457
469
  const p1 = corridorPoint(corridor, corridor.enter);
@@ -607,6 +619,29 @@ function straighten(points, edge, nodes) {
607
619
  }
608
620
  return kept;
609
621
  }
622
+ /**
623
+ * A line cut in two at `at`, a point on one of its pieces, each half keeping
624
+ * `at` as its end. A point on no piece cuts at the nearest one.
625
+ */
626
+ function splitAt(points, at) {
627
+ let piece = 0;
628
+ let nearest = Infinity;
629
+ for (let index = 1; index < points.length; index += 1) {
630
+ const a = points[index - 1];
631
+ const b = points[index];
632
+ const length = Math.hypot(b.x - a.x, b.y - a.y);
633
+ const t = length === 0 ? 0 : Math.max(0, Math.min(1, ((at.x - a.x) * (b.x - a.x) + (at.y - a.y) * (b.y - a.y)) / (length * length)));
634
+ const off = Math.hypot(a.x + t * (b.x - a.x) - at.x, a.y + t * (b.y - a.y) - at.y);
635
+ if (off < nearest) {
636
+ nearest = off;
637
+ piece = index;
638
+ }
639
+ }
640
+ return [
641
+ tidyRoute([...points.slice(0, piece), at]),
642
+ tidyRoute([at, ...points.slice(piece)]),
643
+ ];
644
+ }
610
645
  function extentOfBox(box) {
611
646
  return { minX: box.x, minY: box.y, maxX: box.x + box.width, maxY: box.y + box.height };
612
647
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reladraw",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "A diagram language where you say where things go.",
5
5
  "type": "module",
6
6
  "bin": {