@crouton-kit/humanloop 0.4.5 → 0.4.7

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.
Files changed (101) hide show
  1. package/dist/editor/terminal-review.d.ts +61 -24
  2. package/dist/editor/terminal-review.js +165 -74
  3. package/dist/render/termrender.d.ts +4 -0
  4. package/dist/render/termrender.js +46 -8
  5. package/dist/render/version.d.ts +1 -1
  6. package/dist/render/version.js +1 -1
  7. package/dist/web/assets/{abnfDiagram-VRR7QNED-B71KRG4-.js → abnfDiagram-VRR7QNED-DTJq6212.js} +1 -1
  8. package/dist/web/assets/{arc-BzH4jnTf.js → arc-o4T8NCG8.js} +1 -1
  9. package/dist/web/assets/architecture-TIHT7OUA-C6XhPF72.js +1 -0
  10. package/dist/web/assets/{architectureDiagram-ZJ3FMSHR-D8ZCrOlr.js → architectureDiagram-ZJ3FMSHR-CP2V5kWN.js} +1 -1
  11. package/dist/web/assets/{blockDiagram-677ZJIJ3-DJrvEHzG.js → blockDiagram-677ZJIJ3-CZOM4oT_.js} +1 -1
  12. package/dist/web/assets/{c4Diagram-LMCZKHZV-BhpT2Gsz.js → c4Diagram-LMCZKHZV-n-m7nrvJ.js} +1 -1
  13. package/dist/web/assets/channel-De47oeqL.js +1 -0
  14. package/dist/web/assets/{chunk-32BRIVSS-ECC6qGeB.js → chunk-32BRIVSS-CyV2cpjd.js} +1 -1
  15. package/dist/web/assets/{chunk-52WLFC77-DavNmYy5.js → chunk-52WLFC77-DqmdnEq-.js} +1 -1
  16. package/dist/web/assets/{chunk-C7G6YPKG-BAknDHkJ.js → chunk-C7G6YPKG-CrHl-N3N.js} +1 -1
  17. package/dist/web/assets/{chunk-EX3LRPZG-D8FzKvzP.js → chunk-EX3LRPZG-B0pgzfwr.js} +1 -1
  18. package/dist/web/assets/{chunk-FWX5IMBZ-DmneLaBP.js → chunk-FWX5IMBZ-B7_XlEfW.js} +2 -2
  19. package/dist/web/assets/{chunk-HOUHSVGY-DfL8sRH8.js → chunk-HOUHSVGY-ZA8jG_x_.js} +1 -1
  20. package/dist/web/assets/{chunk-ICXQ74PX-BDsAibh6.js → chunk-ICXQ74PX-EqZj8Pcl.js} +1 -1
  21. package/dist/web/assets/{chunk-MOJQB5TN-CNuZ6pa2.js → chunk-MOJQB5TN-CFi0PbZk.js} +1 -1
  22. package/dist/web/assets/{chunk-OGEWGWER-BzCEWO5x.js → chunk-OGEWGWER-BA_T8lA7.js} +1 -1
  23. package/dist/web/assets/{chunk-PUDLZKDR-C9EdjbBR.js → chunk-PUDLZKDR-Bvu4w9xw.js} +1 -1
  24. package/dist/web/assets/{chunk-Q4XR5HBZ-BXjEOFZL.js → chunk-Q4XR5HBZ-DknWi4Rx.js} +1 -1
  25. package/dist/web/assets/{chunk-RYQCIY6F-Bjx13MLc.js → chunk-RYQCIY6F-d-ko28HJ.js} +1 -1
  26. package/dist/web/assets/{chunk-V7JOEXUC-Tvu7hSiY.js → chunk-V7JOEXUC-B8n1LhxA.js} +1 -1
  27. package/dist/web/assets/{chunk-VAUOI2AC-CtE8-0Em.js → chunk-VAUOI2AC-Bq5B95aK.js} +1 -1
  28. package/dist/web/assets/{chunk-VR4S4FIN-BxDOvumS.js → chunk-VR4S4FIN-DSbvQuOD.js} +1 -1
  29. package/dist/web/assets/{chunk-WYO6CB5R-NSErcIKL.js → chunk-WYO6CB5R-CzhFb-MZ.js} +1 -1
  30. package/dist/web/assets/{chunk-XXDRQBXY-CvnzTWOn.js → chunk-XXDRQBXY-Bhmu_cHP.js} +1 -1
  31. package/dist/web/assets/{chunk-ZGVPDNZ5-c3Lgoc6U.js → chunk-ZGVPDNZ5-bhybkPMI.js} +1 -1
  32. package/dist/web/assets/classDiagram-OUVF2IWQ-ngekp8QL.js +1 -0
  33. package/dist/web/assets/classDiagram-v2-EOCWNBFH-ngekp8QL.js +1 -0
  34. package/dist/web/assets/{cose-bilkent-JH36ORCC-FucxEJcd.js → cose-bilkent-JH36ORCC-BN-6Pzbb.js} +1 -1
  35. package/dist/web/assets/{cynefin-VYW2F7L2-Dao-QhOj.js → cynefin-VYW2F7L2-CNF6CpH7.js} +1 -1
  36. package/dist/web/assets/{cynefinDiagram-TSTJHNR4-CTzeNNi6.js → cynefinDiagram-TSTJHNR4-BpYvrpNh.js} +1 -1
  37. package/dist/web/assets/{dagre-VKFMJZFB-DHJBohq9.js → dagre-VKFMJZFB-DEpoQc9-.js} +1 -1
  38. package/dist/web/assets/{diagram-FQU43EPY-BJD429Ew.js → diagram-FQU43EPY-CPnv8unx.js} +1 -1
  39. package/dist/web/assets/{diagram-G47NLZAW-Rr7qWaPB.js → diagram-G47NLZAW-v4VMprYl.js} +1 -1
  40. package/dist/web/assets/{diagram-NH7WQ7WH-DWt2lASp.js → diagram-NH7WQ7WH-CvlEne1Y.js} +1 -1
  41. package/dist/web/assets/{diagram-OA4YK3LP-BEffXGoK.js → diagram-OA4YK3LP-D3J9c6OE.js} +1 -1
  42. package/dist/web/assets/{diagram-WEI45ONY-DmptqIxd.js → diagram-WEI45ONY-CQkf-qIb.js} +1 -1
  43. package/dist/web/assets/{dist-RLVSx5kB.js → dist-DFjfKcIt.js} +1 -1
  44. package/dist/web/assets/{ebnfDiagram-CCIWWBDH-CJAdBcoT.js → ebnfDiagram-CCIWWBDH-JVq-uXuo.js} +1 -1
  45. package/dist/web/assets/{erDiagram-Q63AITRT-NlmP932t.js → erDiagram-Q63AITRT-DQEpaJid.js} +1 -1
  46. package/dist/web/assets/eventmodeling-45OFAUF4-BbXOeK0d.js +1 -0
  47. package/dist/web/assets/flowDiagram-23GEKE2U-CQp1-GMo.js +1 -0
  48. package/dist/web/assets/{ganttDiagram-NO4QXBWP-DhaQF0vK.js → ganttDiagram-NO4QXBWP-eYm_a80H.js} +1 -1
  49. package/dist/web/assets/{gitGraph-TEB2WS4Q-jJerQW_A.js → gitGraph-TEB2WS4Q-B0r1lGs_.js} +1 -1
  50. package/dist/web/assets/{gitGraphDiagram-IHSO6WYX-B7ujXqgi.js → gitGraphDiagram-IHSO6WYX-CSDQYKOU.js} +1 -1
  51. package/dist/web/assets/{index-DV35aYD7.css → index-Bbt4OR0a.css} +1 -1
  52. package/dist/web/assets/{index-BMZ4RcHs.js → index-Cf9ctfTY.js} +27 -27
  53. package/dist/web/assets/{info-DKCQHKI2-9B9vE5Rs.js → info-DKCQHKI2-CGinBKpz.js} +1 -1
  54. package/dist/web/assets/{infoDiagram-FWYZ7A6U-QVQfmq5Q.js → infoDiagram-FWYZ7A6U-BSSbaUsL.js} +1 -1
  55. package/dist/web/assets/{ishikawaDiagram-FXEZZL3T-DINx8lcq.js → ishikawaDiagram-FXEZZL3T-BQR5zSCA.js} +1 -1
  56. package/dist/web/assets/{journeyDiagram-5HDEW3XC-CCimY8Ca.js → journeyDiagram-5HDEW3XC-D0DuRjJZ.js} +1 -1
  57. package/dist/web/assets/{kanban-definition-HUTT4EX6-CiyVpYz7.js → kanban-definition-HUTT4EX6-Cn9-uGGQ.js} +1 -1
  58. package/dist/web/assets/{line-BS6nDp3b.js → line-BeAsDQVF.js} +1 -1
  59. package/dist/web/assets/{linear-Djl12XgD.js → linear-C-1rViJJ.js} +1 -1
  60. package/dist/web/assets/{mermaid-parser.core-BbWtntfd.js → mermaid-parser.core-DvKEagUi.js} +3 -3
  61. package/dist/web/assets/{mermaid.core-BxoR3aGT.js → mermaid.core-DPZGBClg.js} +3 -3
  62. package/dist/web/assets/{mindmap-definition-LN4V7U3C-CP5EmYtx.js → mindmap-definition-LN4V7U3C-BuTo1G-g.js} +1 -1
  63. package/dist/web/assets/{packet-7NZHBO7P-BZxF_2Fs.js → packet-7NZHBO7P-C9BKVqiN.js} +1 -1
  64. package/dist/web/assets/{pegDiagram-2B236MQR-qzgVPCkt.js → pegDiagram-2B236MQR-ClKh01EI.js} +1 -1
  65. package/dist/web/assets/{pie-RZYD4A2V-BBSGE3OQ.js → pie-RZYD4A2V-BBmy20ni.js} +1 -1
  66. package/dist/web/assets/{pieDiagram-ENE6RG2P-C-IRFSgk.js → pieDiagram-ENE6RG2P-CPl3MwrT.js} +1 -1
  67. package/dist/web/assets/{quadrantDiagram-ABIIQ3AL-T5ncf2ka.js → quadrantDiagram-ABIIQ3AL-DsrToxLD.js} +1 -1
  68. package/dist/web/assets/{radar-I7S5WNFK-BEbxioN2.js → radar-I7S5WNFK-BvxgMODg.js} +1 -1
  69. package/dist/web/assets/{railroad-3IZDKUUU-CylJQRva.js → railroad-3IZDKUUU-Dh8TMd_F.js} +1 -1
  70. package/dist/web/assets/railroad-abnf-AHOZXSZD-D5CwX2YP.js +1 -0
  71. package/dist/web/assets/railroad-ebnf-EBAXGLYW-DtdS-iN2.js +1 -0
  72. package/dist/web/assets/railroad-peg-LSFZ7HO6-cuX6fLbS.js +1 -0
  73. package/dist/web/assets/{railroadDiagram-RFXS5EU6-CBYIviLP.js → railroadDiagram-RFXS5EU6-Bf_RsQBw.js} +1 -1
  74. package/dist/web/assets/{requirementDiagram-TGXJPOKE-DnUCDDfN.js → requirementDiagram-TGXJPOKE-DnSlAPip.js} +1 -1
  75. package/dist/web/assets/{sankeyDiagram-HTMAVEWB-BPcUd5rv.js → sankeyDiagram-HTMAVEWB-DkUc0_Xf.js} +1 -1
  76. package/dist/web/assets/{sequenceDiagram-DBY2YBRQ-B_KozvYN.js → sequenceDiagram-DBY2YBRQ-DZRLv0-5.js} +1 -1
  77. package/dist/web/assets/{src-COFaHe7g.js → src-Di6WPHCL.js} +1 -1
  78. package/dist/web/assets/{stateDiagram-2N3HPSRC-CU0lc0nI.js → stateDiagram-2N3HPSRC-BcyJkTgI.js} +1 -1
  79. package/dist/web/assets/stateDiagram-v2-6OUMAXLB-CCIv0x2V.js +1 -0
  80. package/dist/web/assets/{swimlanes-5IMT3BWC-ChpfV6mg.js → swimlanes-5IMT3BWC-BlwGRSum.js} +1 -1
  81. package/dist/web/assets/swimlanesDiagram-G3AALYLV-BYe45-x0.js +8 -0
  82. package/dist/web/assets/{timeline-definition-FHXFAJF6-D6Uo2p7h.js → timeline-definition-FHXFAJF6-6gzhAzqG.js} +1 -1
  83. package/dist/web/assets/{treeView-QDETBFTQ-BqyWL8XS.js → treeView-QDETBFTQ-DiPkeZhg.js} +1 -1
  84. package/dist/web/assets/{treemap-6X3UGDF4-DZt75S3Q.js → treemap-6X3UGDF4-BnVF_fmG.js} +1 -1
  85. package/dist/web/assets/{vennDiagram-L72KCM5P-Bv7XNrPm.js → vennDiagram-L72KCM5P-DYU1DzxR.js} +1 -1
  86. package/dist/web/assets/{wardley-OPB4EBWU-CeEs_UEB.js → wardley-OPB4EBWU-D-8WX8fZ.js} +1 -1
  87. package/dist/web/assets/{wardleyDiagram-EHGQE667-C4cUF7Ft.js → wardleyDiagram-EHGQE667-BuGZeBAC.js} +1 -1
  88. package/dist/web/assets/{xychartDiagram-FW5EYKEG-BntLSyoW.js → xychartDiagram-FW5EYKEG-CT8DNOFs.js} +1 -1
  89. package/dist/web/index.html +2 -2
  90. package/package.json +1 -1
  91. package/dist/web/assets/architecture-TIHT7OUA-CZWJOUVd.js +0 -1
  92. package/dist/web/assets/channel-C_TWBgFl.js +0 -1
  93. package/dist/web/assets/classDiagram-OUVF2IWQ-BraUhK-5.js +0 -1
  94. package/dist/web/assets/classDiagram-v2-EOCWNBFH-BraUhK-5.js +0 -1
  95. package/dist/web/assets/eventmodeling-45OFAUF4-BKX8_y74.js +0 -1
  96. package/dist/web/assets/flowDiagram-23GEKE2U-CBN8yaFm.js +0 -1
  97. package/dist/web/assets/railroad-abnf-AHOZXSZD-CFDo5gvn.js +0 -1
  98. package/dist/web/assets/railroad-ebnf-EBAXGLYW-Cg-yyAK9.js +0 -1
  99. package/dist/web/assets/railroad-peg-LSFZ7HO6-DcopMOfK.js +0 -1
  100. package/dist/web/assets/stateDiagram-v2-6OUMAXLB-CSRqotH1.js +0 -1
  101. package/dist/web/assets/swimlanesDiagram-G3AALYLV-Cob34HwG.js +0 -8
@@ -1,11 +1,29 @@
1
1
  import type { FeedbackComment, FeedbackResult } from '../types.js';
2
2
  import type { ReviewOptions } from './review.js';
3
3
  import { type RenderedDoc } from '../render/termrender.js';
4
- /** 1-indexed inclusive source-line bounds of one top-level rendered block. */
5
- export interface BlockRange {
4
+ /** One leaf anchor unit: the finest step j/k moves by. Consecutive rendered
5
+ * rows sharing one source span collapse into a single unit that knows both
6
+ * its source-line bounds and its rendered-row bounds. */
7
+ export interface AnchorUnit {
8
+ /** 1-indexed inclusive source-line bounds. */
6
9
  start: number;
7
10
  end: number;
11
+ /** 0-indexed inclusive rendered-row bounds in the mapped doc. */
12
+ firstRow: number;
13
+ lastRow: number;
8
14
  }
15
+ /** The anchorable shape of a rendered doc: ordered leaf units plus the
16
+ * per-row owning-unit index the painter keys off. */
17
+ export interface AnchorDoc {
18
+ units: AnchorUnit[];
19
+ /** Per rendered row: index into `units`, or null (separator rows). */
20
+ rowUnits: (number | null)[];
21
+ }
22
+ /** Derive leaf anchor units from a mapped render: dedupe runs of consecutive
23
+ * rows carrying the identical source span. A mapped row without a leaf span
24
+ * (an unmapped block) anchors at its whole block's range, so every content
25
+ * row belongs to a unit; separator rows belong to none. */
26
+ export declare function deriveAnchorUnits(doc: RenderedDoc): AnchorDoc;
9
27
  export interface ComposeState {
10
28
  buffer: string;
11
29
  cursor: number;
@@ -20,13 +38,15 @@ export interface ComposeState {
20
38
  }
21
39
  export interface ReviewState {
22
40
  sourceLines: string[];
23
- /** Top-level block source ranges, in document order. Never empty. */
24
- blocks: BlockRange[];
41
+ /** Ordered leaf anchor units. Never empty. */
42
+ units: AnchorUnit[];
43
+ /** Per rendered row: owning unit index, or null for separator rows. */
44
+ rowUnits: (number | null)[];
25
45
  comments: FeedbackComment[];
26
46
  version: number;
27
- /** 0-based index of the anchored block. */
28
- activeBlock: number;
29
- /** Set while a Shift+j/k range is being extended from this block. */
47
+ /** 0-based index of the anchored unit. */
48
+ activeUnit: number;
49
+ /** Set while a Shift+j/k range is being extended from this unit. */
30
50
  selectionAnchor: number | null;
31
51
  /** Scroll offset into the rendered (termrender) lines. */
32
52
  scroll: number;
@@ -34,25 +54,41 @@ export interface ReviewState {
34
54
  compose: ComposeState | null;
35
55
  listIndex: number;
36
56
  }
37
- /** Index of the block containing `line`; snaps forward across gaps (blank
38
- * separator lines between blocks) and clamps to the last block. */
39
- export declare function blockIndexForLine(blocks: BlockRange[], line: number): number;
40
- export declare function initReviewState(sourceLines: string[], blocks: BlockRange[], comments: FeedbackComment[], version: number): ReviewState;
41
- /** Source-line anchor of the current block selection what a committed
42
- * comment records as `line`/`endLine`. */
57
+ /** Best unit for a source line: the NARROWEST unit containing it — code/table
58
+ * chrome units carry their whole block's range and sit before the per-line
59
+ * content units in rendered order, so "first whose end reaches the line"
60
+ * would wrongly pick the chrome over the exact code line. A line no unit
61
+ * contains (a blank separator) snaps forward to the next unit; past the end
62
+ * clamps to the last. */
63
+ export declare function unitIndexForLine(units: AnchorUnit[], line: number): number;
64
+ /** Remap a unit from an old unit list into a re-derived one: an exact
65
+ * source-range match wins (chrome and leaf units can share source lines),
66
+ * else the best unit for its first line. */
67
+ export declare function remapUnitIndex(units: AnchorUnit[], prev: AnchorUnit): number;
68
+ /** First/last unit indices overlapping the source range `line..endLine`;
69
+ * a range touching no unit snaps like unitIndexForLine. */
70
+ export declare function unitRangeForSpan(units: AnchorUnit[], line: number, endLine: number): {
71
+ lo: number;
72
+ hi: number;
73
+ };
74
+ export declare function initReviewState(sourceLines: string[], anchor: AnchorDoc, comments: FeedbackComment[], version: number): ReviewState;
75
+ /** Source-line anchor of the current unit selection — what a committed
76
+ * comment records as `line`/`endLine`. Whole-block chrome units can carry a
77
+ * wider range than their neighbors, so take the min/max over the selection
78
+ * rather than trusting the endpoints alone. */
43
79
  export declare function currentAnchor(state: ReviewState): {
44
80
  line: number;
45
81
  endLine: number;
46
82
  };
47
- export declare function moveActiveBlock(state: ReviewState, delta: number, extend: boolean): ReviewState;
48
- /** Block indices overlapped by any existing comment's source range. A stale
49
- * draft range lying wholly past the last block (the file shrank between draft
50
- * save and reopen) still gets a marker on its clamped block, so every comment
83
+ export declare function moveActiveUnit(state: ReviewState, delta: number, extend: boolean): ReviewState;
84
+ /** Unit indices overlapped by any existing comment's source range. A stale
85
+ * draft range lying wholly past the last unit (the file shrank between draft
86
+ * save and reopen) still gets a marker on its clamped unit, so every comment
51
87
  * is visible somewhere in the document. */
52
- export declare function commentedBlockSet(state: ReviewState): Set<number>;
53
- /** First/last rendered-row indices produced by blocks `lo..hi`, or null when
54
- * no row maps into that range. */
55
- export declare function anchorRowRange(rows: (number | null)[], lo: number, hi: number): {
88
+ export declare function commentedUnitSet(state: ReviewState): Set<number>;
89
+ /** First/last rendered-row indices spanned by units `lo..hi`, or null when
90
+ * the indices fall outside the unit list. */
91
+ export declare function anchorRowRange(units: AnchorUnit[], lo: number, hi: number): {
56
92
  first: number;
57
93
  last: number;
58
94
  } | null;
@@ -63,7 +99,7 @@ export declare function anchorRowRange(rows: (number | null)[], lo: number, hi:
63
99
  * overwrites the preceding row, never the pinned one. Always returns a scroll
64
100
  * clamped to the document. */
65
101
  export declare function scrollToReveal(scroll: number, first: number, last: number, bodyHeight: number, total: number, margin?: number): number;
66
- /** Auto-scroll so the active block (the moving edge of a selection) is
102
+ /** Auto-scroll so the active unit (the moving edge of a selection) is
67
103
  * visible. Free-scrolling (`u`/`d`) is untouched until the next anchor move. */
68
104
  export declare function ensureAnchorVisible(state: ReviewState, doc: RenderedDoc, bodyHeight: number): ReviewState;
69
105
  export declare function scrollBy(state: ReviewState, delta: number, bodyHeight: number, totalLines: number): ReviewState;
@@ -105,8 +141,9 @@ export declare function renderReviewFrame(state: ReviewState, fileLabel: string,
105
141
  /**
106
142
  * Open a Markdown file in humanloop's own terminal review surface: the
107
143
  * document renders via termrender (Mermaid included), the anchor is a
108
- * highlighted block in the rendered document itself (gutter bar + tint via
109
- * termrender's row→source map), and the human explicitly submits a proposal.
144
+ * highlighted leaf unit a bullet, table row, code line, paragraph — in the
145
+ * rendered document itself (gutter bar + tint via termrender's per-row source
146
+ * spans), and the human explicitly submits a proposal.
110
147
  * `space w` hands the review off to the browser surface (same park/take-back
111
148
  * semantics as the Neovim path); the draft round-trips between surfaces via
112
149
  * `opts.output`. Never edits the source file. Autosaves the comment draft to
@@ -11,23 +11,106 @@ import { renderMarkdownWithMap } from '../render/termrender.js';
11
11
  import { setupTerminal, restoreTerminal, getTerminalSize, parseKeypress } from '../tui/terminal.js';
12
12
  import { diffFrame, renderInputBuffer } from '../tui/render.js';
13
13
  import { BOLD, CYAN, DIM, ESC, RESET, YELLOW, hline, sanitize, truncate } from '../tui/ansi.js';
14
- /** Index of the block containing `line`; snaps forward across gaps (blank
15
- * separator lines between blocks) and clamps to the last block. */
16
- export function blockIndexForLine(blocks, line) {
17
- for (let i = 0; i < blocks.length; i++) {
18
- if (blocks[i].end >= line)
14
+ /** Derive leaf anchor units from a mapped render: dedupe runs of consecutive
15
+ * rows carrying the identical source span. A mapped row without a leaf span
16
+ * (an unmapped block) anchors at its whole block's range, so every content
17
+ * row belongs to a unit; separator rows belong to none. */
18
+ export function deriveAnchorUnits(doc) {
19
+ const units = [];
20
+ const rowUnits = new Array(doc.lines.length).fill(null);
21
+ for (let r = 0; r < doc.lines.length; r++) {
22
+ let span = doc.spans[r] ?? null;
23
+ if (span === null) {
24
+ const b = doc.rows[r] ?? null;
25
+ const block = b !== null ? doc.blocks[b] : undefined;
26
+ if (block === undefined)
27
+ continue;
28
+ span = [block.start, block.end];
29
+ }
30
+ const prev = units[units.length - 1];
31
+ if (prev !== undefined && prev.lastRow === r - 1 && prev.start === span[0] && prev.end === span[1]) {
32
+ prev.lastRow = r;
33
+ }
34
+ else {
35
+ units.push({ start: span[0], end: span[1], firstRow: r, lastRow: r });
36
+ }
37
+ rowUnits[r] = units.length - 1;
38
+ }
39
+ if (units.length === 0) {
40
+ // Degenerate map (nothing anchorable) — one whole-doc unit over all rows.
41
+ units.push({
42
+ start: doc.blocks[0]?.start ?? 1,
43
+ end: doc.blocks[doc.blocks.length - 1]?.end ?? 1,
44
+ firstRow: 0,
45
+ lastRow: Math.max(0, doc.lines.length - 1),
46
+ });
47
+ for (let r = 0; r < rowUnits.length; r++)
48
+ rowUnits[r] = 0;
49
+ }
50
+ return { units, rowUnits };
51
+ }
52
+ /** Best unit for a source line: the NARROWEST unit containing it — code/table
53
+ * chrome units carry their whole block's range and sit before the per-line
54
+ * content units in rendered order, so "first whose end reaches the line"
55
+ * would wrongly pick the chrome over the exact code line. A line no unit
56
+ * contains (a blank separator) snaps forward to the next unit; past the end
57
+ * clamps to the last. */
58
+ export function unitIndexForLine(units, line) {
59
+ let best = -1;
60
+ for (let i = 0; i < units.length; i++) {
61
+ const u = units[i];
62
+ if (u.start <= line && u.end >= line) {
63
+ if (best === -1 || u.end - u.start < units[best].end - units[best].start)
64
+ best = i;
65
+ }
66
+ }
67
+ if (best !== -1)
68
+ return best;
69
+ for (let i = 0; i < units.length; i++) {
70
+ if (units[i].start > line)
19
71
  return i;
20
72
  }
21
- return Math.max(0, blocks.length - 1);
73
+ return Math.max(0, units.length - 1);
74
+ }
75
+ /** Remap a unit from an old unit list into a re-derived one: an exact
76
+ * source-range match wins (chrome and leaf units can share source lines),
77
+ * else the best unit for its first line. */
78
+ export function remapUnitIndex(units, prev) {
79
+ for (let i = 0; i < units.length; i++) {
80
+ if (units[i].start === prev.start && units[i].end === prev.end)
81
+ return i;
82
+ }
83
+ return unitIndexForLine(units, prev.start);
84
+ }
85
+ /** First/last unit indices overlapping the source range `line..endLine`;
86
+ * a range touching no unit snaps like unitIndexForLine. */
87
+ export function unitRangeForSpan(units, line, endLine) {
88
+ let lo = -1;
89
+ let hi = -1;
90
+ units.forEach((u, i) => {
91
+ if (u.start <= endLine && u.end >= line) {
92
+ if (lo === -1)
93
+ lo = i;
94
+ hi = i;
95
+ }
96
+ });
97
+ if (lo === -1) {
98
+ const snap = unitIndexForLine(units, line);
99
+ return { lo: snap, hi: snap };
100
+ }
101
+ return { lo, hi };
22
102
  }
23
- export function initReviewState(sourceLines, blocks, comments, version) {
24
- const safeBlocks = blocks.length > 0 ? blocks : [{ start: 1, end: Math.max(1, sourceLines.length) }];
103
+ export function initReviewState(sourceLines, anchor, comments, version) {
104
+ const safe = anchor.units.length > 0
105
+ ? anchor
106
+ : { units: [{ start: 1, end: Math.max(1, sourceLines.length), firstRow: 0, lastRow: 0 }], rowUnits: anchor.rowUnits };
25
107
  return {
26
108
  sourceLines,
27
- blocks: safeBlocks,
109
+ units: safe.units,
110
+ rowUnits: safe.rowUnits,
28
111
  comments: [...comments],
29
112
  version,
30
- activeBlock: comments.length > 0 ? blockIndexForLine(safeBlocks, comments[0].line) : 0,
113
+ activeUnit: comments.length > 0 ? unitIndexForLine(safe.units, comments[0].line) : 0,
31
114
  selectionAnchor: null,
32
115
  scroll: 0,
33
116
  mode: 'view',
@@ -35,58 +118,63 @@ export function initReviewState(sourceLines, blocks, comments, version) {
35
118
  listIndex: 0,
36
119
  };
37
120
  }
38
- function selectedBlockBounds(state) {
39
- const sel = state.selectionAnchor ?? state.activeBlock;
40
- return { lo: Math.min(state.activeBlock, sel), hi: Math.max(state.activeBlock, sel) };
121
+ function selectedUnitBounds(state) {
122
+ const sel = state.selectionAnchor ?? state.activeUnit;
123
+ return { lo: Math.min(state.activeUnit, sel), hi: Math.max(state.activeUnit, sel) };
41
124
  }
42
- /** Source-line anchor of the current block selection — what a committed
43
- * comment records as `line`/`endLine`. */
125
+ /** Source-line anchor of the current unit selection — what a committed
126
+ * comment records as `line`/`endLine`. Whole-block chrome units can carry a
127
+ * wider range than their neighbors, so take the min/max over the selection
128
+ * rather than trusting the endpoints alone. */
44
129
  export function currentAnchor(state) {
45
- const { lo, hi } = selectedBlockBounds(state);
46
- const first = state.blocks[lo] ?? { start: 1, end: Math.max(1, state.sourceLines.length) };
47
- const last = state.blocks[hi] ?? first;
48
- return { line: first.start, endLine: last.end };
49
- }
50
- export function moveActiveBlock(state, delta, extend) {
51
- const last = Math.max(0, state.blocks.length - 1);
52
- const next = Math.max(0, Math.min(last, state.activeBlock + delta));
130
+ const { lo, hi } = selectedUnitBounds(state);
131
+ let line = Number.POSITIVE_INFINITY;
132
+ let endLine = 0;
133
+ for (let i = lo; i <= hi; i++) {
134
+ const u = state.units[i];
135
+ if (u === undefined)
136
+ continue;
137
+ line = Math.min(line, u.start);
138
+ endLine = Math.max(endLine, u.end);
139
+ }
140
+ if (!Number.isFinite(line))
141
+ return { line: 1, endLine: Math.max(1, state.sourceLines.length) };
142
+ return { line, endLine: Math.max(line, endLine) };
143
+ }
144
+ export function moveActiveUnit(state, delta, extend) {
145
+ const last = Math.max(0, state.units.length - 1);
146
+ const next = Math.max(0, Math.min(last, state.activeUnit + delta));
53
147
  if (!extend)
54
- return { ...state, activeBlock: next, selectionAnchor: null };
55
- return { ...state, activeBlock: next, selectionAnchor: state.selectionAnchor ?? state.activeBlock };
148
+ return { ...state, activeUnit: next, selectionAnchor: null };
149
+ return { ...state, activeUnit: next, selectionAnchor: state.selectionAnchor ?? state.activeUnit };
56
150
  }
57
- /** Block indices overlapped by any existing comment's source range. A stale
58
- * draft range lying wholly past the last block (the file shrank between draft
59
- * save and reopen) still gets a marker on its clamped block, so every comment
151
+ /** Unit indices overlapped by any existing comment's source range. A stale
152
+ * draft range lying wholly past the last unit (the file shrank between draft
153
+ * save and reopen) still gets a marker on its clamped unit, so every comment
60
154
  * is visible somewhere in the document. */
61
- export function commentedBlockSet(state) {
155
+ export function commentedUnitSet(state) {
62
156
  const out = new Set();
63
157
  for (const c of state.comments) {
64
158
  let hit = false;
65
- state.blocks.forEach((b, i) => {
66
- if (b.start <= c.endLine && b.end >= c.line) {
159
+ state.units.forEach((u, i) => {
160
+ if (u.start <= c.endLine && u.end >= c.line) {
67
161
  out.add(i);
68
162
  hit = true;
69
163
  }
70
164
  });
71
165
  if (!hit)
72
- out.add(blockIndexForLine(state.blocks, c.line));
166
+ out.add(unitIndexForLine(state.units, c.line));
73
167
  }
74
168
  return out;
75
169
  }
76
- /** First/last rendered-row indices produced by blocks `lo..hi`, or null when
77
- * no row maps into that range. */
78
- export function anchorRowRange(rows, lo, hi) {
79
- let first = -1;
80
- let last = -1;
81
- for (let r = 0; r < rows.length; r++) {
82
- const b = rows[r];
83
- if (b !== null && b >= lo && b <= hi) {
84
- if (first === -1)
85
- first = r;
86
- last = r;
87
- }
88
- }
89
- return first === -1 ? null : { first, last };
170
+ /** First/last rendered-row indices spanned by units `lo..hi`, or null when
171
+ * the indices fall outside the unit list. */
172
+ export function anchorRowRange(units, lo, hi) {
173
+ const a = units[lo];
174
+ const b = units[hi];
175
+ if (a === undefined || b === undefined)
176
+ return null;
177
+ return { first: a.firstRow, last: b.lastRow };
90
178
  }
91
179
  /** Minimal scroll adjustment that keeps rows `first..last` visible with
92
180
  * `margin` rows of context (the margin yields whenever honoring it would push
@@ -105,10 +193,10 @@ export function scrollToReveal(scroll, first, last, bodyHeight, total, margin =
105
193
  next = Math.min(last + margin - (bodyHeight - 1), first);
106
194
  return Math.max(0, Math.min(next, maxScroll));
107
195
  }
108
- /** Auto-scroll so the active block (the moving edge of a selection) is
196
+ /** Auto-scroll so the active unit (the moving edge of a selection) is
109
197
  * visible. Free-scrolling (`u`/`d`) is untouched until the next anchor move. */
110
198
  export function ensureAnchorVisible(state, doc, bodyHeight) {
111
- const range = anchorRowRange(doc.rows, state.activeBlock, state.activeBlock);
199
+ const range = anchorRowRange(state.units, state.activeUnit, state.activeUnit);
112
200
  if (range === null)
113
201
  return state;
114
202
  const scroll = scrollToReveal(state.scroll, range.first, range.last, bodyHeight, doc.lines.length);
@@ -126,11 +214,10 @@ export function openComposeEdit(state, index) {
126
214
  if (comment === undefined)
127
215
  return state;
128
216
  const buffer = comment.comment;
129
- const lo = blockIndexForLine(state.blocks, comment.line);
130
- const hi = blockIndexForLine(state.blocks, comment.endLine);
217
+ const { lo, hi } = unitRangeForSpan(state.units, comment.line, comment.endLine);
131
218
  return {
132
219
  ...state,
133
- activeBlock: hi,
220
+ activeUnit: hi,
134
221
  selectionAnchor: lo === hi ? null : lo,
135
222
  mode: 'compose',
136
223
  compose: { buffer, cursor: [...buffer].length, editingId: comment.id, returnMode: 'list', anchor: { line: comment.line, endLine: comment.endLine } },
@@ -321,7 +408,7 @@ export function renderReviewFrame(state, fileLabel, doc, cols, rows) {
321
408
  }
322
409
  else if (state.mode === 'help') {
323
410
  footer.push(' Keys:');
324
- footer.push(` ${DIM}j/k${RESET} move anchor block ${DIM}shift+j/k${RESET} extend selection`);
411
+ footer.push(` ${DIM}j/k${RESET} move anchor ${DIM}shift+j/k${RESET} extend selection`);
325
412
  footer.push(` ${DIM}u/d, pgup/pgdn${RESET} scroll document`);
326
413
  footer.push(` ${DIM}space c${RESET} compose comment ${DIM}space l${RESET} list comments`);
327
414
  footer.push(` ${DIM}space u${RESET} undo last comment ${DIM}space s${RESET} submit review`);
@@ -331,15 +418,15 @@ export function renderReviewFrame(state, fileLabel, doc, cols, rows) {
331
418
  footer.push(` ${DIM}esc / ?${RESET} close`);
332
419
  }
333
420
  else {
334
- footer.push(` ${DIM}j/k${RESET} block ${DIM}shift-j/k${RESET} extend ${DIM}u/d${RESET} scroll ${DIM}space c${RESET} comment ` +
421
+ footer.push(` ${DIM}j/k${RESET} move ${DIM}shift-j/k${RESET} extend ${DIM}u/d${RESET} scroll ${DIM}space c${RESET} comment ` +
335
422
  `${DIM}space l${RESET} list ${DIM}space u${RESET} undo ${DIM}space s${RESET} submit ${DIM}space w${RESET} browser ${DIM}?${RESET} help ${DIM}esc${RESET} close`);
336
423
  }
337
424
  const reserved = header.length + footer.length;
338
425
  const bodyHeight = Math.max(1, rows - reserved);
339
426
  const maxScroll = Math.max(0, doc.lines.length - bodyHeight);
340
427
  const scroll = Math.max(0, Math.min(state.scroll, maxScroll));
341
- const { lo, hi } = selectedBlockBounds(state);
342
- const commented = commentedBlockSet(state);
428
+ const { lo, hi } = selectedUnitBounds(state);
429
+ const commented = commentedUnitSet(state);
343
430
  const body = [];
344
431
  for (let i = 0; i < bodyHeight; i++) {
345
432
  const abs = scroll + i;
@@ -348,10 +435,10 @@ export function renderReviewFrame(state, fileLabel, doc, cols, rows) {
348
435
  continue;
349
436
  }
350
437
  const row = doc.lines[abs];
351
- const b = doc.rows[abs] ?? null;
352
- if (b !== null && b >= lo && b <= hi)
438
+ const u = state.rowUnits[abs] ?? null;
439
+ if (u !== null && u >= lo && u <= hi)
353
440
  body.push(` ${CYAN}▌${RESET} ${tintRow(row, docW)}`);
354
- else if (b !== null && commented.has(b))
441
+ else if (u !== null && commented.has(u))
355
442
  body.push(` ${YELLOW}▎${RESET} ${row}`);
356
443
  else
357
444
  body.push(` ${row}`);
@@ -375,8 +462,9 @@ function diskDraftResult(absFile, outPath) {
375
462
  /**
376
463
  * Open a Markdown file in humanloop's own terminal review surface: the
377
464
  * document renders via termrender (Mermaid included), the anchor is a
378
- * highlighted block in the rendered document itself (gutter bar + tint via
379
- * termrender's row→source map), and the human explicitly submits a proposal.
465
+ * highlighted leaf unit a bullet, table row, code line, paragraph — in the
466
+ * rendered document itself (gutter bar + tint via termrender's per-row source
467
+ * spans), and the human explicitly submits a proposal.
380
468
  * `space w` hands the review off to the browser surface (same park/take-back
381
469
  * semantics as the Neovim path); the draft round-trips between surfaces via
382
470
  * `opts.output`. Never edits the source file. Autosaves the comment draft to
@@ -450,7 +538,7 @@ function runTerminalReviewSession(absFile, content, outPath, fileLabel, opts) {
450
538
  setupTerminal();
451
539
  let { cols, rows } = getTerminalSize();
452
540
  let doc = renderMarkdownWithMap(content, renderWidthForCols(cols));
453
- let state = initReviewState(sourceLines, doc.blocks, draft?.comments ?? [], draft?.version ?? 0);
541
+ let state = initReviewState(sourceLines, deriveAnchorUnits(doc), draft?.comments ?? [], draft?.version ?? 0);
454
542
  let prevFrame = [];
455
543
  let spaceArmed = false;
456
544
  let settled = false;
@@ -488,17 +576,20 @@ function runTerminalReviewSession(absFile, content, outPath, fileLabel, opts) {
488
576
  const onResize = () => {
489
577
  ({ cols, rows } = getTerminalSize());
490
578
  doc = renderMarkdownWithMap(content, renderWidthForCols(cols));
491
- // Blocks derive from the source, not the width, so a same-renderer
492
- // re-render keeps the count — but a mid-session renderer→fallback
493
- // transition can reshape the block list, so clamp the indices. Committed
494
- // comments are untouched either way (their source lines are frozen).
495
- const blocks = doc.blocks;
496
- const lastIdx = Math.max(0, blocks.length - 1);
579
+ // Unit SOURCE ranges are width-independent under the same renderer (only
580
+ // their rendered-row bounds move), but a mid-session renderer→fallback
581
+ // transition can reshape the list so remap the anchor by its source
582
+ // line rather than trusting the old index. Committed comments are
583
+ // untouched either way (their source lines are frozen).
584
+ const prevActive = state.units[state.activeUnit];
585
+ const prevSel = state.selectionAnchor !== null ? state.units[state.selectionAnchor] : undefined;
586
+ const { units, rowUnits } = deriveAnchorUnits(doc);
497
587
  state = {
498
588
  ...state,
499
- blocks,
500
- activeBlock: Math.min(state.activeBlock, lastIdx),
501
- selectionAnchor: state.selectionAnchor === null ? null : Math.min(state.selectionAnchor, lastIdx),
589
+ units,
590
+ rowUnits,
591
+ activeUnit: prevActive !== undefined ? remapUnitIndex(units, prevActive) : 0,
592
+ selectionAnchor: prevSel !== undefined ? remapUnitIndex(units, prevSel) : null,
502
593
  };
503
594
  state = ensureAnchorVisible(state, doc, bodyH());
504
595
  paint(true);
@@ -665,19 +756,19 @@ function runTerminalReviewSession(absFile, content, outPath, fileLabel, opts) {
665
756
  return;
666
757
  }
667
758
  if (input === 'j' || key.downArrow) {
668
- state = moveActiveBlock(state, 1, false);
759
+ state = moveActiveUnit(state, 1, false);
669
760
  state = ensureAnchorVisible(state, doc, bodyH());
670
761
  }
671
762
  else if (input === 'k' || key.upArrow) {
672
- state = moveActiveBlock(state, -1, false);
763
+ state = moveActiveUnit(state, -1, false);
673
764
  state = ensureAnchorVisible(state, doc, bodyH());
674
765
  }
675
766
  else if (input === 'J') {
676
- state = moveActiveBlock(state, 1, true);
767
+ state = moveActiveUnit(state, 1, true);
677
768
  state = ensureAnchorVisible(state, doc, bodyH());
678
769
  }
679
770
  else if (input === 'K') {
680
- state = moveActiveBlock(state, -1, true);
771
+ state = moveActiveUnit(state, -1, true);
681
772
  state = ensureAnchorVisible(state, doc, bodyH());
682
773
  }
683
774
  else if (input === 'u' || key.pageUp)
@@ -22,6 +22,10 @@ export interface RenderedDoc {
22
22
  lines: string[];
23
23
  /** Per-row index into `blocks`; null for the blank separator rows between blocks. */
24
24
  rows: (number | null)[];
25
+ /** Per-row finest 1-indexed inclusive source-line range the renderer knows
26
+ * (a bullet, a table row, a code line…); null for separator rows and rows
27
+ * of unmapped blocks. Same length as `lines`. */
28
+ spans: ([number, number] | null)[];
25
29
  /** Per top-level block: 1-indexed inclusive source-line bounds. Never empty. */
26
30
  blocks: {
27
31
  start: number;
@@ -505,9 +505,9 @@ function parseRenderedDoc(out, source) {
505
505
  return null;
506
506
  }
507
507
  const p = parsed;
508
- if (!Array.isArray(p.lines) || !Array.isArray(p.rows) || !Array.isArray(p.blocks))
508
+ if (!Array.isArray(p.lines) || !Array.isArray(p.rows) || !Array.isArray(p.spans) || !Array.isArray(p.blocks))
509
509
  return null;
510
- if (p.rows.length !== p.lines.length)
510
+ if (p.rows.length !== p.lines.length || p.spans.length !== p.lines.length)
511
511
  return null;
512
512
  if (!p.lines.every((l) => typeof l === 'string'))
513
513
  return null;
@@ -535,11 +535,42 @@ function parseRenderedDoc(out, source) {
535
535
  }
536
536
  if (blocks.length === 0)
537
537
  blocks.push({ start: 1, end: totalSource });
538
- return { lines: p.lines, rows: p.rows, blocks };
538
+ const spans = [];
539
+ for (let r = 0; r < p.spans.length; r++) {
540
+ const raw = p.spans[r];
541
+ if (raw === null) {
542
+ spans.push(null);
543
+ continue;
544
+ }
545
+ // Same strictness as rows: a span is [start, end], 1-indexed inclusive
546
+ // integers in order, inside the source — these values flow straight into
547
+ // a recorded comment's line/endLine, so an out-of-range endpoint is tool
548
+ // fault to reject, never something to clamp into the wrong line.
549
+ if (!Array.isArray(raw) || raw.length !== 2)
550
+ return null;
551
+ const [s, e] = raw;
552
+ if (!Number.isInteger(s) || !Number.isInteger(e))
553
+ return null;
554
+ if (s < 1 || e < s || e > totalSource)
555
+ return null;
556
+ // Relational contract: a separator row (rows[r] === null) carries no
557
+ // span, and a leaf span stays inside its owning block's source range. A
558
+ // map that disagrees with its own rows/blocks would let a comment on a
559
+ // visible row record against unrelated source text.
560
+ const rowBlock = p.rows[r];
561
+ if (rowBlock === null)
562
+ return null;
563
+ const owner = blocks[rowBlock];
564
+ if (s < owner.start || e > owner.end)
565
+ return null;
566
+ spans.push([s, e]);
567
+ }
568
+ return { lines: p.lines, rows: p.rows, spans, blocks };
539
569
  }
540
570
  /** Renderer-free mapped render: group consecutive non-blank source lines into
541
571
  * paragraph blocks and word-wrap each — the same shape as the termrender map,
542
- * with degraded (plaintext) rendering. */
572
+ * with degraded (plaintext) rendering. Each source line is wrapped on its own
573
+ * and spans exactly itself, so leaf anchoring degrades to true line-by-line. */
543
574
  function fallbackDocWithMap(md, width) {
544
575
  const src = sanitize(md).split('\n');
545
576
  const blocks = [];
@@ -560,17 +591,24 @@ function fallbackDocWithMap(md, width) {
560
591
  blocks.push({ start: 1, end: Math.max(1, src.length) });
561
592
  const lines = [];
562
593
  const rows = [];
594
+ const spans = [];
563
595
  blocks.forEach((b, bi) => {
564
596
  if (bi > 0) {
565
597
  lines.push('');
566
598
  rows.push(null);
599
+ spans.push(null);
567
600
  }
568
- for (const l of wrap(src.slice(b.start - 1, b.end).join('\n'), width)) {
569
- lines.push(l);
570
- rows.push(bi);
601
+ // wrap() treats each '\n'-separated line as its own paragraph, so wrapping
602
+ // line-by-line emits the exact rows the joined-block wrap produced.
603
+ for (let ln = b.start; ln <= b.end; ln++) {
604
+ for (const l of wrap(src[ln - 1] ?? '', width)) {
605
+ lines.push(l);
606
+ rows.push(bi);
607
+ spans.push([ln, ln]);
608
+ }
571
609
  }
572
610
  });
573
- return { lines, rows, blocks };
611
+ return { lines, rows, spans, blocks };
574
612
  }
575
613
  const _mapCache = new Map();
576
614
  /** Render markdown with a row→source-line map via the pinned binary
@@ -1 +1 @@
1
- export declare const TERMRENDER_VERSION = "4.11.0";
1
+ export declare const TERMRENDER_VERSION = "4.12.0";
@@ -1 +1 @@
1
- export const TERMRENDER_VERSION = '4.11.0';
1
+ export const TERMRENDER_VERSION = '4.12.0';
@@ -1 +1 @@
1
- import{m as e,t}from"./mermaid-parser.core-BbWtntfd.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-COFaHe7g.js";import"./chunk-WYO6CB5R-NSErcIKL.js";import"./chunk-VAUOI2AC-CtE8-0Em.js";import{n as i,r as a,t as o}from"./chunk-MOJQB5TN-CNuZ6pa2.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
1
+ import{m as e,t}from"./mermaid-parser.core-DvKEagUi.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-Di6WPHCL.js";import"./chunk-WYO6CB5R-CzhFb-MZ.js";import"./chunk-VAUOI2AC-Bq5B95aK.js";import{n as i,r as a,t as o}from"./chunk-MOJQB5TN-CFi0PbZk.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
@@ -1 +1 @@
1
- import{n as e,t}from"./path-BWPyau1x.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-RLVSx5kB.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
1
+ import{n as e,t}from"./path-BWPyau1x.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-DFjfKcIt.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
@@ -0,0 +1 @@
1
+ import"./chunk-KEIR6QF5-BfrZ3jm6.js";import{M as e}from"./mermaid-parser.core-DvKEagUi.js";export{e as createArchitectureServices};