- commit
- eff59d537ebc92256a780bc22576f50d4b2d79f1
- parent
- 4267864e5541c2591bee683269a7f49f6035b1a0
- author
- Dami <dami.etoile@gmail.com>
@@ -391,7 +391,7 @@ export const diagramTypes = [
391391 format: 'Tabular Recipe Notation text',392392 summary: 'TRN stands for Tabular Recipe Notation. It shows how ingredients and intermediate outcomes combine into one or more final results.',393393 use: 'Use TRN for recipes, crafting trees, assembly instructions, and other nested transformations.',394- syntax: ['Optionally begin with `.layout combined` or `.layout individual`; the default is `combined`.', 'Declare each leaf value with `ingredient`.', 'Declare a meaningful final or reusable result with an `outcome` block.', 'Keep incidental conversions, such as ore to bars, as steps inside the outcome that consumes them.', 'Add a full-width preparation row with `instruction`.', 'Add a quoted display label after an identifier when needed.', 'Each `+` adds an input row from top to bottom.', 'Each `->` adds an operation column from left to right.', 'Add `portion` after an outcome label or identifier when the result has a useful quantity.', 'Use `{portion}` in an action to embed that outcome quantity.', 'Start comments with `#`; OCR importers should record uncertain text in comments instead of guessing.'],394+ syntax: ['Optionally begin with `.layout combined` or `.layout individual`; the default is `combined`.', 'Declare each leaf value with `ingredient`.', 'Declare a meaningful final or reusable result with an `outcome` block.', 'Keep incidental conversions, such as ore to bars, as steps inside the outcome that consumes them.', 'Add a full-width preparation row with `instruction`.', 'Add a quoted display label after an identifier when needed.', 'Each `+` queues an input for the next `->` action.', 'Combined layout places prerequisite outcomes before direct ingredients in stable FIFO order.', 'Each `->` adds an operation column from left to right.', 'Add `portion` after an outcome label or identifier when the result has a useful quantity.', 'Use `{portion}` in an action to embed that outcome quantity.', 'Start comments with `#`; OCR importers should record uncertain text in comments instead of guessing.'],395395 language: 'text',396396 example: [397397 '.layout combined',@@ -413,7 +413,7 @@ export const diagramTypes = [
413413 '}',414414 ],415415 styleSummary: 'TRN colors complete relationship zones as branches. Adjacent zones receive different normalized colors, while ingredients run downward and operations run right.',416- sourceStyle: ['Use `.layout combined` for one merged table or `.layout individual` for dependency-positioned recipe tables.', 'Order `+` lines as the ingredient rows should appear from top to bottom.', 'Order `->` lines as operations should proceed from left to right.', 'Use outcomes for meaningful reusable or final results; keep incidental conversions inside the consuming outcome.', 'Use short action labels because operation text is vertical.'],416+ sourceStyle: ['Use `.layout combined` for one merged table or `.layout individual` for dependency-positioned recipe tables.', 'Combined layout places prerequisite outcomes before direct ingredients and preserves source order within each FIFO group.', 'Order `->` lines as operations should proceed from left to right.', 'Use outcomes for meaningful reusable or final results; keep incidental conversions inside the consuming outcome.', 'Use short action labels because operation text is vertical.'],417417 rendererOptions: [],418418 limitations: ['The source selects one layout; the SVG does not embed an interactive layout toggle.'],419419 origin: {@@ -28,7 +28,8 @@ The source format is **Tabular Recipe Notation text**. Enter the source in the d
2828 - Keep incidental conversions, such as ore to bars, as steps inside the outcome that consumes them.2929 - Add a full-width preparation row with `instruction`.3030 - Add a quoted display label after an identifier when needed.31-- Each `+` adds an input row from top to bottom.31+- Each `+` queues an input for the next `->` action.32+- Combined layout places prerequisite outcomes before direct ingredients in stable FIFO order.3233 - Each `->` adds an operation column from left to right.3334 - Add `portion` after an outcome label or identifier when the result has a useful quantity.3435 - Use `{portion}` in an action to embed that outcome quantity.@@ -15,7 +15,7 @@ Start with the [general presentation settings](/style/presentation). Edit shared
1515 ## Source controls1616 1717 - Use `.layout combined` for one merged table or `.layout individual` for dependency-positioned recipe tables.18-- Order `+` lines as the ingredient rows should appear from top to bottom.18+- Combined layout places prerequisite outcomes before direct ingredients and preserves source order within each FIFO group.1919 - Order `->` lines as operations should proceed from left to right.2020 - Use outcomes for meaningful reusable or final results; keep incidental conversions inside the consuming outcome.2121 - Use short action labels because operation text is vertical.@@ -2822,7 +2822,8 @@ The source format is **Tabular Recipe Notation text**. Enter the source in the d
28222822 - Keep incidental conversions, such as ore to bars, as steps inside the outcome that consumes them.28232823 - Add a full-width preparation row with `instruction`.28242824 - Add a quoted display label after an identifier when needed.2825-- Each `+` adds an input row from top to bottom.2825+- Each `+` queues an input for the next `->` action.2826+- Combined layout places prerequisite outcomes before direct ingredients in stable FIFO order.28262827 - Each `->` adds an operation column from left to right.28272828 - Add `portion` after an outcome label or identifier when the result has a useful quantity.28282829 - Use `{portion}` in an action to embed that outcome quantity.@@ -2885,7 +2886,7 @@ Start with the [general presentation settings](/style/presentation). Edit shared
28852886 ## Source controls28862887 28872888 - Use `.layout combined` for one merged table or `.layout individual` for dependency-positioned recipe tables.2888-- Order `+` lines as the ingredient rows should appear from top to bottom.2889+- Combined layout places prerequisite outcomes before direct ingredients and preserves source order within each FIFO group.28892890 - Order `->` lines as operations should proceed from left to right.28902891 - Use outcomes for meaningful reusable or final results; keep incidental conversions inside the consuming outcome.28912892 - Use short action labels because operation text is vertical.@@ -182,7 +182,7 @@ test('applies D2, PlantUML, Svgbob, and neutral SVG family roles', () => {
182182 test('normalizes TRN table structure and relationship zones', () => {183183 const trn = canonicalizeSvg(184184 '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 40"><rect class="trn-canvas" width="80" height="40" fill="#fbf8dc"></rect><text class="trn-title" fill="#111827">Bread</text><rect class="trn-table-surface" y="10" width="80" height="30" fill="white"></rect><path class="trn-zone-shape trn-branch-4" fill="white" stroke="#65a268"></path><text class="trn-operation-label" fill="#111827">mix</text></svg>',185- metadata, 'trn', 'diagramzip-trn@13',185+ metadata, 'trn', 'diagramzip-trn@14',186186 )187187 188188 assert.match(trn, /data-dz-profile="trn-semantic-4"/)@@ -108,7 +108,7 @@ const versions: Record<EngineId, string> = {
108108 ditaa: 'ditaa-ascii+svgbob@0.7.6/edge-wasm-1',109109 symbolator: 'symbolator@1.2.2/python-translation-1',110110 tikz: '@planktimerr/tikzjax@1.0.63',111- trn: 'diagramzip-trn@13',111+ trn: 'diagramzip-trn@14',112112 umlet: 'diagramzip-umlet-svg@1',113113 }114114 @@ -5,6 +5,6 @@
55 "compatibility_date": "2026-08-20",66 "compatibility_flags": ["nodejs_compat"],77 "observability": { "enabled": true, "logs": { "head_sampling_rate": 1 } },8- "vars": { "RENDERER_BUILD": "diagramzip-trn-13" },8+ "vars": { "RENDERER_BUILD": "diagramzip-trn-14" },99 "routes": [{ "pattern": "trn.render.diagram.zip", "custom_domain": true }]1010 }@@ -4,7 +4,7 @@ import { parseTrn } from '../languages/trn'
44 import { renderTrn } from '../languages/trn-renderer'55 import { edgeFailure, edgeResult } from './types'66 7-const VERSION = 'diagramzip-trn@13'7+const VERSION = 'diagramzip-trn@14'88 99 function validateOptions(options: Record<string, string>): void {1010 for (const name of Object.keys(options)) {@@ -73,6 +73,15 @@ function actionText(item: StageLayout): string {
7373 return item.stage.action.replaceAll('{portion}', item.outcome.portion)7474 }7575 76+function fifoInputs(document: TrnDocument, inputs: TrnInput[]): TrnInput[] {77+ const outcomes: TrnInput[] = []78+ const ingredients: TrnInput[] = []79+ for (const input of inputs) {80+ (document.outcomes.has(input.id) ? outcomes : ingredients).push(input)81+ }82+ return [...outcomes, ...ingredients]83+}84+7685 function layoutTree(document: TrnDocument): Layout {7786 const layout: Layout = { leaves: [], stages: [], rows: 0, columns: 0 }7887 let nextRow = 0@@ -95,7 +104,7 @@ function layoutTree(document: TrnDocument): Layout {
95104 let dependencyColumn = previousColumn96105 const inputs: Array<{ startRow: number; endRow: number; column: number }> = []97106 98- for (const input of stage.inputs) {107+ for (const input of fifoInputs(document, stage.inputs)) {99108 const child = document.outcomes.get(input.id)100109 const placed = child === undefined ? leaf(input) : outcome(child)101110 inputs.push(placed)@@ -159,4 +159,28 @@ outcome marshmallows {
159159 expect(result.body).toContain('data-outcome-id="marshmallows" data-column="6" data-cell-count="12" data-arm-count="1"')160160 expect(result.body).toContain('height="196"')161161 })162+163+ it('places prerequisite outcomes before direct ingredients in FIFO order', async () => {164+ const source = `ingredient remaining_water "remaining 2½ c lukewarm water"165+ingredient starter_water "½ c lukewarm water"166+ingredient yeast "2 pkt yeast"167+168+outcome activated_yeast {169+ + starter_water170+ + yeast171+ -> sprinkle yeast over water172+}173+174+outcome bagels portion 16 bagels {175+ + remaining_water176+ + activated_yeast177+ -> combine178+}`179+ const result = await trnAdapter.render(request(source), new AbortController().signal)180+ const rows = [...result.body.matchAll(/class="trn-ingredient" data-value-id="([^"]+)"/g)]181+ .map(match => match[1])182+183+ expect(rows).toEqual(['starter_water', 'yeast', 'remaining_water'])184+ expect(result.body).toContain('data-outcome-id="bagels" data-column="2" data-cell-count="4" data-arm-count="1"')185+ })162186 })@@ -158,7 +158,7 @@ const VERSION_PATTERNS = Object.freeze({
158158 diagramsnet: /diagrams\.net@29\.6\.1/,159159 excalidraw: /@excalidraw\/excalidraw@0\.18\.1/,160160 tikz: /@planktimerr\/tikzjax@1\.0\.63/,161- trn: /diagramzip-trn@13/,161+ trn: /diagramzip-trn@14/,162162 })163163 164164 export function normalizationFor(engine, rendererVersion = '') {