lispgram 0.10.0

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.
@@ -0,0 +1,390 @@
1
+ # Lispgram layout language
2
+
3
+ This document describes the layout surface that Lispgram accepts today. It is intentionally small. The normal Lispgram graph language remains the primary authoring surface; `$layout` is an optional correction and template layer.
4
+
5
+ The design rule is:
6
+
7
+ ```text
8
+ write ordinary Lispgram first
9
+ add $layout only when the inferred layout needs a visual nudge
10
+ ```
11
+
12
+ ## 1. Relationship to the Lispgram core
13
+
14
+ The core Lispgram syntax is still enough for many diagrams:
15
+
16
+ ```lisp
17
+ (lispgram
18
+ (P{Parent} A B C)
19
+ (-> f A B)
20
+ (-> g B C)
21
+ (-> meta f g))
22
+ ```
23
+
24
+ From this small syntax the renderer infers:
25
+
26
+ - visual containment from tree forms such as `(P A B C)`;
27
+ - ordinary routes from arrows such as `(-> f A B)`;
28
+ - self loops from ordinary self-arrows such as `(-> loop A A)`;
29
+ - arrows between arrows from ordinary arrows such as `(-> meta f g)`;
30
+ - curved lanes for repeated or anti-parallel endpoint pairs;
31
+ - containment-scoped fallback rows/ranks;
32
+ - locality for implicit targets that are introduced only by arrow references.
33
+
34
+ `$layout` and legacy `$metalayout` forms are preserved as layout metadata. They do not enter semantic core facts.
35
+
36
+ ## 2. Basic shape
37
+
38
+ A layout block is written inside a Lispgram document:
39
+
40
+ ```lisp
41
+ (lispgram
42
+ (P A B C)
43
+ (-> f A B)
44
+
45
+ ($layout
46
+ (same-row [A B C])
47
+ (left-of A B)))
48
+ ```
49
+
50
+ Legacy `$metalayout` is still accepted for the older arrow-shaped syntax:
51
+
52
+ ```lisp
53
+ ($metalayout
54
+ (-> $samerow [A B C])
55
+ (-> $leftof A B))
56
+ ```
57
+
58
+ New code should prefer `$layout`.
59
+
60
+ ## 3. Strengths
61
+
62
+ Most relative constraints accept an optional strength as their final positional argument:
63
+
64
+ ```lisp
65
+ (same-row [A B C] strong)
66
+ (left-of A B required)
67
+ (same-x [X P] medium)
68
+ ```
69
+
70
+ Implemented strength names are:
71
+
72
+ ```text
73
+ required > strong > medium > weak
74
+ ```
75
+
76
+ The solver also has a small numeric epsilon tolerance, so sub-pixel differences do not cause endless projection churn. Required constraints are still the strongest constraints; epsilon only controls when a nearly-satisfied numeric equation stops moving.
77
+
78
+ ## 4. Relative positioning forms
79
+
80
+ ### `same-row`
81
+
82
+ Aligns the vertical centers of nodes/containers.
83
+
84
+ ```lisp
85
+ (same-row [A B C])
86
+ (same-row [A B C] strong)
87
+ ```
88
+
89
+ Equivalent older spelling:
90
+
91
+ ```lisp
92
+ (-> $samerow [A B C])
93
+ ```
94
+
95
+ ### `same-column` / `same-col`
96
+
97
+ Aligns the horizontal centers of nodes/containers and performs initial vertical packing so the aligned objects do not collapse on top of each other.
98
+
99
+ ```lisp
100
+ (same-column [A B C])
101
+ (same-col [A B C])
102
+ ```
103
+
104
+ Equivalent older spellings include `$samecol`, `$samecolumn`, `$same-col`, and `$same-column`.
105
+
106
+ ### `same-x`
107
+
108
+ A softer x-alignment form. It aligns horizontal centers but defaults to `strong` instead of `required`.
109
+
110
+ ```lisp
111
+ (same-x [X P])
112
+ ```
113
+
114
+ ### `left-of`
115
+
116
+ Places the first object left of the second object.
117
+
118
+ ```lisp
119
+ (left-of A B)
120
+ (left-of A B required)
121
+ ```
122
+
123
+ Equivalent older spellings include `leftof` and `$leftof`.
124
+
125
+ ### `above`
126
+
127
+ Places one object above another object.
128
+
129
+ ```lisp
130
+ (above X P)
131
+ ```
132
+
133
+ The first argument may also be a vector in some template-lowered cases, but author-facing uses should usually keep it singular.
134
+
135
+ ### `below`
136
+
137
+ Places one or more movers below an anchor.
138
+
139
+ ```lisp
140
+ (below [A B C] P)
141
+ (below A P)
142
+ ```
143
+
144
+ ### `center-over` / `center-x-over`
145
+
146
+ Horizontally centers an object over the average center of target objects.
147
+
148
+ ```lisp
149
+ (center-over P [A B])
150
+ (center-x-over Product [A B C] strong)
151
+ ```
152
+
153
+ This is useful for product/coproduct-like fan diagrams, but most authors should use a template view instead.
154
+
155
+ ## 5. Route endpoint references
156
+
157
+ Most route directives accept endpoints. A bare id refers to a node/container by id.
158
+
159
+ ```lisp
160
+ (route h :from A :to B)
161
+ ```
162
+
163
+ The following endpoint constructors are also available:
164
+
165
+ ```lisp
166
+ (node A) ;; force a node endpoint
167
+ (container C) ;; force a container endpoint
168
+ (boundary C left) ;; selected boundary side of a node/container/island
169
+ (boundary C right 0.25) ;; side plus optional normalized side position
170
+ (route f) ;; route midpoint of f
171
+ (arrow f) ;; alias of route endpoint
172
+ (mid f) ;; route midpoint
173
+ (start f) ;; route start anchor
174
+ (end f) ;; route end anchor
175
+ (label f) ;; label anchor
176
+ ```
177
+
178
+ `(-> meta f g)` does not need `$layout`: arrow-to-arrow routes are inferred automatically and anchor to the final visible geometry of `f` and `g`.
179
+
180
+ ## 6. Route directives
181
+
182
+ ### `route`
183
+
184
+ Overrides the visual endpoints or role of an existing arrow.
185
+
186
+ ```lisp
187
+ (route h :from A :to B)
188
+ (route h :from (mid f) :to (mid g) :role route-arrow)
189
+ (route h :from A :to B :shape straight :label h)
190
+ ```
191
+
192
+ When `route` is used, the automatic rank pressure from the arrow's original semantic endpoints is suppressed for that arrow. This prevents the old semantic direction from fighting the explicit visual route.
193
+
194
+ ### `parallel-pair`
195
+
196
+ Draws a set of arrows as global parallel lanes between the same visual endpoints.
197
+
198
+ ```lisp
199
+ (parallel-pair [f g h] :from A :to B)
200
+ ```
201
+
202
+ Despite the historical name, this can handle more than two arrows. The engine also infers parallel and anti-parallel lanes from ordinary Lispgram arrows where possible, so use this only when the automatic lane grouping needs to be overridden.
203
+
204
+ ### `attach-at-boundary`
205
+
206
+ Places an external source subtree outside a boundary side, then routes the arrow through that side-port.
207
+
208
+ ```lisp
209
+ (attach-at-boundary h
210
+ :from ReviewThread
211
+ :to S
212
+ :boundary CoproductBox
213
+ :side left)
214
+ ```
215
+
216
+ Supported sides are `left`, `right`, `top`, and `bottom`.
217
+
218
+ This directive is both a placement hint and a route directive. It should be used for hierarchy-route-style diagrams where something external connects into a container/island boundary.
219
+
220
+ ### `parallel-to-boundary`
221
+
222
+ Places a route alongside a selected boundary without making its endpoints members of that boundary owner.
223
+
224
+ ```lisp
225
+ (parallel-to-boundary q
226
+ :from M
227
+ :to N
228
+ :boundary C
229
+ :side left)
230
+ ```
231
+
232
+ ## 7. Self loops
233
+
234
+ Self loops are not a `$layout` directive. They are ordinary arrows:
235
+
236
+ ```lisp
237
+ (lispgram
238
+ (A)
239
+ (-> loop A A))
240
+ ```
241
+
242
+ `$layout (self-loop ...)` and `$layout (loop ...)` intentionally error. This keeps loops in the small core language.
243
+
244
+ ## 8. Template / view directives
245
+
246
+ Templates are written as layout views:
247
+
248
+ ```lisp
249
+ ($layout
250
+ (view product
251
+ :product P
252
+ :factors [A B]
253
+ :test-object X
254
+ :mediator u
255
+ :projections [pi1 pi2]
256
+ :cone-legs [f g]
257
+ :container C))
258
+ ```
259
+
260
+ `view` and `template` are aliases. Templates emit ordinary relative constraints, route directives, and an island/layout view. They do not directly assign final coordinates.
261
+
262
+ Common keyword conventions:
263
+
264
+ - `:id` names the layout island. If omitted, the engine generates a template-specific id.
265
+ - `:container` links the view to a visual container shell when safe.
266
+ - `:mode full` asks the template to include optional outer/cone-leg routes where supported.
267
+ - Supplying `:cone-legs` for product/coproduct automatically selects full mode.
268
+
269
+ ### Product
270
+
271
+ ```lisp
272
+ (view product
273
+ :product P
274
+ :factors [A B]
275
+ :test-object X
276
+ :mediator u
277
+ :projections [pi1 pi2]
278
+ :cone-legs [f g]
279
+ :container C)
280
+ ```
281
+
282
+ Visual convention:
283
+
284
+ ```text
285
+ X above P
286
+ P centered over factors
287
+ factors in a row below P
288
+ projections fan downward
289
+ mediator is centered
290
+ ```
291
+
292
+ Aliases: `product`, `product-cone`.
293
+
294
+ ### Coproduct
295
+
296
+ ```lisp
297
+ (view coproduct
298
+ :coproduct S
299
+ :summands [A B]
300
+ :test-object X
301
+ :mediator u
302
+ :injections [i1 i2]
303
+ :cone-legs [f g]
304
+ :container CΣ)
305
+ ```
306
+
307
+ Aliases: `coproduct`, `sum`, `sum-type`.
308
+
309
+ ### Equalizer
310
+
311
+ ```lisp
312
+ (view equalizer
313
+ :equalizer E
314
+ :source A
315
+ :target B
316
+ :inclusion e
317
+ :parallel [f g])
318
+ ```
319
+
320
+ ### Pullback / pushout
321
+
322
+ ```lisp
323
+ (view pullback
324
+ :corners [TL TR BL BR]
325
+ :arrows [top left bottom right])
326
+
327
+ (view pushout
328
+ :corners [TL TR BL BR]
329
+ :arrows [top left bottom right])
330
+ ```
331
+
332
+ The corner order is top-left, top-right, bottom-left, bottom-right.
333
+
334
+ ### Exponential
335
+
336
+ ```lisp
337
+ (view exponential
338
+ :exponential BA
339
+ :source A
340
+ :target B
341
+ :product AxBA
342
+ :evaluation eval)
343
+ ```
344
+
345
+ ### Hasse / ranked rows
346
+
347
+ ```lisp
348
+ (view hasse
349
+ :rows [[Bottom] [A B] [Top]])
350
+ ```
351
+
352
+ The current surface lowering preserves rows and claims the island. Cover arrows can still be ordinary Lispgram arrows or explicit `route` directives.
353
+
354
+ ## 9. NCF round trip
355
+
356
+ `toNCF()` emits layout metadata as a top-level `(layout ...)` block, and public `toNCFDoc()` can read raw NCF back into `doc.layoutForms`. Layout metadata remains outside semantic core. The lower-level `parseNCF()` helper exists inside the implementation but is not part of the minimal public npm export surface.
357
+
358
+ A simplified NCF shape looks like:
359
+
360
+ ```lisp
361
+ (cy
362
+ (nodes ...)
363
+ (edges ...)
364
+ (layout
365
+ (same-row [A B C])
366
+ (view product :product P :factors [A B])))
367
+ ```
368
+
369
+ ## 10. Recommended authoring style
370
+
371
+ Prefer this:
372
+
373
+ ```lisp
374
+ (lispgram
375
+ (P{Parent} A B C)
376
+ (-> f A B)
377
+ (-> g B C)
378
+ (-> meta f g))
379
+ ```
380
+
381
+ Add this only when needed:
382
+
383
+ ```lisp
384
+ ($layout
385
+ (same-row [A B C])
386
+ (attach-at-boundary h :from External :to P :boundary C :side left)
387
+ (view product :product P :factors [A B]))
388
+ ```
389
+
390
+ Avoid using `$layout` to restate obvious graph facts. The engine should infer containers, self-loops, arrow-to-arrow routes, parallel lanes, and many ordinary ranks from the small core syntax.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.