wyvern-diagrams 0.4.1.0 → 0.4.2.0
raw patch · 9 files changed
+178/−73 lines, 9 filesdep −textdep −unordered-containersPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: text, unordered-containers
API changes (from Hackage documentation)
- Blocks: render :: [[Block]] -> Diagram B
- Blocks: render' :: [[Block]] -> Diagram B
+ Blocks: getAllIdentifiers :: Block -> [ID]
+ Blocks: getAllIdentifiers' :: [Block] -> [ID]
+ Blocks: renderDiagram :: [[Block]] -> Diagram B
+ Blocks: renderDiagram' :: [[Block]] -> Diagram B
+ Blocks: validateBlocks :: [[Block]] -> Either [[Block]] ([String], [ID])
+ Blocks: validateBlocks' :: [Block] -> Either [Block] ([String], [ID])
+ Blocks: validateSingleBlock :: Block -> [ID] -> (Bool, String)
Files
- CHANGELOG.md +10/−1
- diagrams/temp.svg +1/−1
- diagrams/temp.txt +41/−5
- src/app/Main.hs +23/−16
- src/lib/Blocks.hs +83/−35
- src/lib/Constants.hs +0/−2
- src/lib/HelperDiagrams.hs +14/−7
- src/lib/ID.hs +3/−1
- wyvern-diagrams.cabal +3/−5
CHANGELOG.md view
@@ -1,4 +1,13 @@-## [0.4.1.0](https://github.com/PiotrJustyna/wyvern/tree/0.4.0.1) (2026-03-13)+## [0.4.2.0](https://github.com/PiotrJustyna/wyvern/tree/0.4.2.0) (2026-03-27)++Fixed bugs:++* [#63](https://github.com/PiotrJustyna/wyvern/issues/63) - clean up warnings+* [#66](https://github.com/PiotrJustyna/wyvern/issues/66) - remove unused dependency: unordered-containers+* [#67](https://github.com/PiotrJustyna/wyvern/issues/67) - connections overlapping+* [#68](https://github.com/PiotrJustyna/wyvern/issues/68) - gamma connection routing + validation++## [0.4.1.0](https://github.com/PiotrJustyna/wyvern/tree/0.4.1.0) (2026-03-13) Fixed bug [#64](https://github.com/PiotrJustyna/wyvern/issues/64) - incorrect action token rendering.
diagrams/temp.svg view
@@ -1,3 +1,3 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg font-size="1" viewBox="0.0 0.0 1920.0 1080.0" stroke="rgb(0,0,0)" xmlns="http://www.w3.org/2000/svg" width="1920.0000" stroke-opacity="1" height="1080.0000" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink"><defs></defs><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.36610394919274"><path d="M 960.0000,900.0000 v -720.0000 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.36610394919274"><path d="M 1824.0000,900.0000 h 0.0000 c 0.0000,-99.4113 -80.5887,-180.0000 -180.0000 -180.0000h -1368.0000 c -99.4113,-0.0000 -180.0000,80.5887 -180.0000 180.0000h 0.0000 c -0.0000,99.4113 80.5887,180.0000 180.0000 180.0000h 1368.0000 c 99.4113,0.0000 180.0000,-80.5887 180.0000 -180.0000Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="90.0px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.46441579677096"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,960.0000,900.0000)" stroke="none" dominant-baseline="middle" text-anchor="middle">end</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.36610394919274"><path d="M 1824.0000,180.0000 h 0.0000 c 0.0000,-99.4113 -80.5887,-180.0000 -180.0000 -180.0000h -1368.0000 c -99.4113,-0.0000 -180.0000,80.5887 -180.0000 180.0000h 0.0000 c -0.0000,99.4113 80.5887,180.0000 180.0000 180.0000h 1368.0000 c 99.4113,0.0000 180.0000,-80.5887 180.0000 -180.0000Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="90.0px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.46441579677096"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,960.0000,180.0000)" stroke="none" dominant-baseline="middle" text-anchor="middle">start</text></g></svg>+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg font-size="1" viewBox="0.0 0.0 1920.0 1080.0" stroke="rgb(0,0,0)" xmlns="http://www.w3.org/2000/svg" width="1920.0000" stroke-opacity="1" height="1080.0000" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink"><defs></defs><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1114.5316,477.7880 l -8.6203,4.9770 l 8.6203,4.9770 Z"/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 507.0968,721.6590 v 159.2627 h 746.5438 v -398.1567 h -139.4939 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1413.1491,79.6313 l -8.6203,4.9770 l 8.6203,4.9770 Z"/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1701.5668,323.5023 v 159.2627 h 159.2627 v -398.1567 h -448.0654 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,1030.2304 v 49.7696 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 199.6335,79.6313 l 8.6203,-4.9770 l -8.6203,-4.9770 Z"/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,1080.0000 h -149.3088 v -1005.3456 h 140.6884 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,74.6544 h 1194.4700 v 24.8848 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1402.9493,223.9631 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1402.9493,323.5023 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1402.9493,532.5346 v -209.0323 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1522.3963,532.5346 h 0.0000 c 0.0000,-13.7435 -11.1413,-24.8848 -24.8848 -24.8848h -189.1244 c -13.7435,-0.0000 -24.8848,11.1413 -24.8848 24.8848h 0.0000 c -0.0000,13.7435 11.1413,24.8848 24.8848 24.8848h 189.1244 c 13.7435,0.0000 24.8848,-11.1413 24.8848 -24.8848Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1402.9493,532.5346)" stroke="none" dominant-baseline="middle" text-anchor="middle">end</text></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1701.5668,423.0415 v -99.5392 h -298.6175 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1402.9493,432.9954 v -9.9539 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1402.9493,423.0415 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1821.0138,447.9263 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1701.5668,423.0415)" stroke="none" dominant-baseline="middle" text-anchor="middle">action 2</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1522.3963,447.9263 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1402.9493,423.0415)" stroke="none" dominant-baseline="middle" text-anchor="middle">action 1</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1537.3272,313.5484)" stroke="none" dominant-baseline="middle" text-anchor="middle">no</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1383.0415,363.3180)" stroke="none" dominant-baseline="middle" text-anchor="middle">yes</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1293.4562,348.3871 l -9.9539,-24.8848 l 9.9539,-24.8848 h 218.9862 l 9.9539,24.8848 l -9.9539,24.8848 h -218.9862 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1402.9493,323.5023)" stroke="none" dominant-baseline="middle" text-anchor="middle">question - headline 2</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1522.3963,248.8479 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1402.9493,223.9631)" stroke="none" dominant-baseline="middle" text-anchor="middle">action - headline 2</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1283.5023,149.3088 v -49.7696 h 238.8940 v 49.7696 l -119.4470,9.9539 l -119.4470,-9.9539 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1402.9493,124.4240)" stroke="none" dominant-baseline="middle" text-anchor="middle">headline 2</text></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,124.4240 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,223.9631 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,622.1198 v -398.1567 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,721.6590 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,930.6912 v -209.0323 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,1030.2304 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 89.0323,1055.1152 v -49.7696 l 119.4470,-9.9539 l 119.4470,9.9539 v 49.7696 h -238.8940 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,1030.2304)" stroke="none" dominant-baseline="middle" text-anchor="middle">h2</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 327.9263,955.5760 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,930.6912)" stroke="none" dominant-baseline="middle" text-anchor="middle">action 4</text></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 507.0968,821.1982 v -99.5392 h -298.6175 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,831.1521 v -9.9539 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,821.1982 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 626.5438,846.0829 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,507.0968,821.1982)" stroke="none" dominant-baseline="middle" text-anchor="middle">action 3</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 327.9263,846.0829 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,821.1982)" stroke="none" dominant-baseline="middle" text-anchor="middle">action 2</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,342.8571,711.7051)" stroke="none" dominant-baseline="middle" text-anchor="middle">no</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,188.5714,761.4747)" stroke="none" dominant-baseline="middle" text-anchor="middle">yes</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 98.9862,746.5438 l -9.9539,-24.8848 l 9.9539,-24.8848 h 218.9862 l 9.9539,24.8848 l -9.9539,24.8848 h -218.9862 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,721.6590)" stroke="none" dominant-baseline="middle" text-anchor="middle">question 1</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 327.9263,647.0046 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,622.1198)" stroke="none" dominant-baseline="middle" text-anchor="middle">action 1</text></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,572.3502 h 597.2350 v -49.7696 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 805.7143,323.5023 v -99.5392 h -597.2350 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,522.5806 v -199.0783 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,323.5023 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 805.7143,423.0415 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 805.7143,572.3502 h 298.6175 v -49.7696 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1104.3318,522.5806 v -99.5392 h -298.6175 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 805.7143,522.5806 h 0.0000 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 805.7143,522.5806 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 1223.7788,547.4654 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,1104.3318,522.5806)" stroke="none" dominant-baseline="middle" text-anchor="middle">unknown action</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 925.1613,547.4654 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,805.7143,522.5806)" stroke="none" dominant-baseline="middle" text-anchor="middle">unknown action</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,940.0922,413.0876)" stroke="none" dominant-baseline="middle" text-anchor="middle">no</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,785.8065,462.8571)" stroke="none" dominant-baseline="middle" text-anchor="middle">yes</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 696.2212,447.9263 l -9.9539,-24.8848 l 9.9539,-24.8848 h 218.9862 l 9.9539,24.8848 l -9.9539,24.8848 h -218.9862 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,805.7143,423.0415)" stroke="none" dominant-baseline="middle" text-anchor="middle">question 0b</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 925.1613,348.3871 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,805.7143,323.5023)" stroke="none" dominant-baseline="middle" text-anchor="middle">action b</text></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,423.0415 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,572.3502 h 298.6175 v -49.7696 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 507.0968,522.5806 v -99.5392 h -298.6175 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,522.5806 h 0.0000 "/></g><g stroke-linejoin="miter" fill-opacity="0.0" fill="rgb(0,0,0)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 208.4793,522.5806 v -99.5392 "/></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 626.5438,547.4654 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,507.0968,522.5806)" stroke="none" dominant-baseline="middle" text-anchor="middle">unknown action</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 327.9263,547.4654 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,522.5806)" stroke="none" dominant-baseline="middle" text-anchor="middle">unknown action</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,342.8571,413.0876)" stroke="none" dominant-baseline="middle" text-anchor="middle">no</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,188.5714,462.8571)" stroke="none" dominant-baseline="middle" text-anchor="middle">yes</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 98.9862,447.9263 l -9.9539,-24.8848 l 9.9539,-24.8848 h 218.9862 l 9.9539,24.8848 l -9.9539,24.8848 h -218.9862 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,423.0415)" stroke="none" dominant-baseline="middle" text-anchor="middle">question 0a</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 327.9263,348.3871 l -0.0000,-49.7696 h -238.8940 l -0.0000,49.7696 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,323.5023)" stroke="none" dominant-baseline="middle" text-anchor="middle">action a</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,342.8571,214.0092)" stroke="none" dominant-baseline="middle" text-anchor="middle">no</text></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,188.5714,263.7788)" stroke="none" dominant-baseline="middle" text-anchor="middle">yes</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 98.9862,248.8479 l -9.9539,-24.8848 l 9.9539,-24.8848 h 218.9862 l 9.9539,24.8848 l -9.9539,24.8848 h -218.9862 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,223.9631)" stroke="none" dominant-baseline="middle" text-anchor="middle">question 0</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 89.0323,149.3088 v -49.7696 h 238.8940 v 49.7696 l -119.4470,9.9539 l -119.4470,-9.9539 Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,124.4240)" stroke="none" dominant-baseline="middle" text-anchor="middle">headline 1</text></g><g stroke-linejoin="miter" fill-opacity="1.0" fill="rgb(237,237,244)" stroke="rgb(160,194,222)" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="1.3949163792389583"><path d="M 327.9263,24.8848 h 0.0000 c 0.0000,-13.7435 -11.1413,-24.8848 -24.8848 -24.8848h -189.1244 c -13.7435,-0.0000 -24.8848,11.1413 -24.8848 24.8848h 0.0000 c -0.0000,13.7435 11.1413,24.8848 24.8848 24.8848h 189.1244 c 13.7435,0.0000 24.8848,-11.1413 24.8848 -24.8848Z"/></g><g stroke-linejoin="miter" fill-opacity="1.0" font-size="12.442396313364055px" fill="rgb(6,71,128)" stroke="rgb(0,0,0)" font-weight="300" font-family="helvetica" stroke-linecap="butt" stroke-miterlimit="10.0" stroke-opacity="1.0" stroke-width="5.579665516955833"><text transform="matrix(1.0000,0.0000,0.0000,1.0000,208.4793,24.8848)" stroke="none" dominant-baseline="middle" text-anchor="middle">start</text></g></svg>
diagrams/temp.txt view
@@ -1,9 +1,45 @@-"action 1"-"question 1"+h1 "headline 1" {- 123 456"action 2"+ 0 "question 0"+ {+ 0a "action a"+ 0aq "question 0a"+ {+ 0aqa1 "unknown action"+ }+ {+ 0aqa2 "unknown action"+ }+ }+ {+ 0b "action b"+ 0bq "question 0b"+ {+ 0bqa1 "unknown action"+ }+ {+ 0bqa2 "unknown action"+ }+ }+ 1 "action 1"+ q1 "question 1"+ {+ 123 "action 2"+ }+ {+ "action 3" 0bqa2+ }+ 4 "action 4"+ h2 }+h2 "headline 2" {- "action 3"+ "action - headline 2"+ "question - headline 2"+ {+ "action 1"+ }+ {+ "action 2" h2+ } }-"action 4"
src/app/Main.hs view
@@ -1,6 +1,6 @@ module Main where -import Blocks (render)+import Blocks (renderDiagram, validateBlocks) import Constants (svgOptions) import Diagrams.Backend.SVG (renderSVG') import InputArguments (inputPath, outputPath, parseInput)@@ -8,29 +8,36 @@ import Options.Applicative (execParser, fullDesc, header, helper, info, (<**>)) import Parser (ParseResult (..), diagram) -main :: IO ()+main :: IO Int main = do input <- execParser options print input fileContent <- readFile $ inputPath input - -- lexer v1/v2- -- let tokens = alexScanTokens fileContent-- -- putStrLn "tokens:"- -- print tokens-- -- lexer v3 let lexingResult = runAlex fileContent lexAll case lexingResult of- Left lexingError -> do- putStrLn $ "Wyvern failed with the following error: " <> lexingError- Right tokens -> do- -- print tokens- case diagram tokens 1 of- ParseOk d -> renderSVG' (outputPath input) svgOptions (Blocks.render d)- ParseFail s -> error s+ Left lexingError ->+ do+ putStrLn $ "Wyvern failed with the following error: " <> lexingError+ return 1+ Right tokens ->+ do+ case diagram tokens 1 of+ ParseOk blocks -> do+ case validateBlocks blocks of+ Left validBlocks ->+ do+ renderSVG' (outputPath input) svgOptions (Blocks.renderDiagram validBlocks)+ return 0+ Right (errors, ids) ->+ do+ putStrLn "Diagram validation failed with the following error(s):"+ print errors+ putStrLn "Available block identifiers to be used as gamma connections destinations:"+ print ids+ return 1+ ParseFail s -> error s where options = info
src/lib/Blocks.hs view
@@ -1,14 +1,10 @@ module Blocks where -import Constants (defaultBoundingBoxHeight, defaultBoundingBoxWidth, heightRatio, widthRatio)-import Data.HashSet (HashSet, insert, member)-import Data.List (groupBy, sortBy, sortOn)+import Constants (defaultBoundingBoxHeight, defaultBoundingBoxWidth) import Data.Map (Map, empty, insert, lookup)-import Data.Ord (comparing) import Diagrams.Backend.SVG (B)-import Diagrams.Prelude (Diagram, Point (..), V2 (..), p2, position, r2, translate, (#))-import GHC.Float-import HelperDiagrams (renderConnection, renderGammaConnection, renderLowerBetaConnections, renderSideBetaConnection, renderText, renderUpperBetaConnections, wyvernAddress, wyvernHeadline, wyvernQuestion, wyvernRect, wyvernRoundedRect)+import Diagrams.Prelude (Diagram, Point (..), V2 (..), p2, position)+import HelperDiagrams (renderConnection, renderGammaConnection, renderLowerBetaConnections, renderSideBetaConnection, renderUpperBetaConnections, wyvernAddress, wyvernHeadline, wyvernQuestion, wyvernRect, wyvernRoundedRect) import ID data Block@@ -25,7 +21,7 @@ foldl ( \accu x -> case x of- Fork id content l r rId -> Fork id content (reverse' l) (reverse' r) rId : accu+ Fork i content l r rId -> Fork i content (reverse' l) (reverse' r) rId : accu _ -> x : accu ) []@@ -55,6 +51,17 @@ getIdentifier (Address i _) = i getIdentifier (Fork i _ _ _ _) = i +getAllIdentifiers' :: [Block] -> [ID]+getAllIdentifiers' = foldr (\singleBlock accu -> getAllIdentifiers singleBlock <> accu) []++getAllIdentifiers :: Block -> [ID]+getAllIdentifiers (Fork (Just i) _ l r _) = getAllIdentifiers' l <> getAllIdentifiers' r <> [i]+getAllIdentifiers (Fork Nothing _ l r _) = getAllIdentifiers' l <> getAllIdentifiers' r+getAllIdentifiers b =+ case getIdentifier b of+ Just i -> [i]+ Nothing -> []+ renderSingleBlock :: Block -> Point V2 Double ->@@ -62,16 +69,16 @@ [(Point V2 Double, Double, Double, ID)] -> Double -> (Diagram B, Map ID (Point V2 Double), [(Point V2 Double, Double, Double, ID)], Double, Double, Double, Double)-renderSingleBlock fork@(Fork i c l r gCId) o@(P (V2 oX oY)) ds gCs globalMaxWidth =+renderSingleBlock (Fork _i c l r gCId) o@(P (V2 oX oY)) ds gCs globalMaxWidth = let (gCW, gCH) = case gCId of Nothing -> (0.0, 0.0) Just _ -> (0.1, 0.1)- (dQ, wQ, hQ) = (position [(o, wyvernQuestion c)], oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)+ (dQ, _wQ, hQ) = (position [(o, wyvernQuestion c)], oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight) lX = oX lY = hQ rX = maxWL rY = hQ- (dL, dsL, gCsL, wL, hL, maxWL, minHL) = renderSingleSkewer l (p2 (lX, lY)) ds gCs 0.0+ (dL, dsL, gCsL, _wL, _hL, maxWL, minHL) = renderSingleSkewer l (p2 (lX, lY)) ds gCs 0.0 (dR, dsR, gCsR, wR, hR, maxWR, minHR) = renderSingleSkewer r (p2 (rX, if null r then oY else rY)) dsL gCsL globalMaxWidth newMaxW = maxWR + gCW newMaxW' = max newMaxW globalMaxWidth@@ -96,11 +103,11 @@ newMaxW', newMinH )-renderSingleBlock StartTerminator o@(P (V2 oX oY)) ds gCs abc = (position [(o, wyvernRoundedRect $ getContent StartTerminator)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)-renderSingleBlock EndTerminator o@(P (V2 oX oY)) ds gCs abc = (position [(o, wyvernRoundedRect $ getContent EndTerminator)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)-renderSingleBlock (Headline _i c) o@(P (V2 oX oY)) ds gCs abc = (position [(o, wyvernHeadline c)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)-renderSingleBlock (Address _i c) o@(P (V2 oX oY)) ds gCs abc = (position [(o, wyvernAddress c)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)-renderSingleBlock b o@(P (V2 oX oY)) ds gCs abc = (position [(o, wyvernRect $ getContent b)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)+renderSingleBlock StartTerminator o@(P (V2 oX oY)) ds gCs _globalMaxWidth = (position [(o, wyvernRoundedRect $ getContent StartTerminator)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)+renderSingleBlock EndTerminator o@(P (V2 oX oY)) ds gCs _globalMaxWidth = (position [(o, wyvernRoundedRect $ getContent EndTerminator)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)+renderSingleBlock (Headline _i c) o@(P (V2 oX oY)) ds gCs _globalMaxWidth = (position [(o, wyvernHeadline c)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)+renderSingleBlock (Address _i c) o@(P (V2 oX oY)) ds gCs _globalMaxWidth = (position [(o, wyvernAddress c)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight)+renderSingleBlock b o@(P (V2 oX oY)) ds gCs _globalMaxWidth = (position [(o, wyvernRect $ getContent b)], ds, gCs, oX, oY, oX + defaultBoundingBoxWidth, oY - defaultBoundingBoxHeight) renderSingleSkewer :: [Block] ->@@ -109,19 +116,19 @@ [(Point V2 Double, Double, Double, ID)] -> Double -> (Diagram B, Map ID (Point V2 Double), [(Point V2 Double, Double, Double, ID)], Double, Double, Double, Double)-renderSingleSkewer [] o@(P (V2 oX oY)) ds gCs globalWidth =+renderSingleSkewer [] (P (V2 oX oY)) ds gCs globalWidth = let w = oX minD = oY localWidth = w + defaultBoundingBoxWidth localWidth' = max globalWidth localWidth in (mempty, ds, gCs, w, minD, localWidth', minD)-renderSingleSkewer [b] o@(P (V2 oX oY)) ds gCs globalWidth =+renderSingleSkewer [b] o@(P (V2 oX _oY)) ds gCs globalWidth = let ds' = updateDestinations (getIdentifier b) o ds- (d, ds'', gCs', w, h, maxW, minH) = renderSingleBlock b o ds' gCs globalWidth+ (d, ds'', gCs', _w, h, maxW, minH) = renderSingleBlock b o ds' gCs globalWidth in (d, ds'', gCs', oX, h, maxW, minH) renderSingleSkewer (b : bs) o@(P (V2 oX oY)) ds gCs globalWidth = let ds' = updateDestinations (getIdentifier b) o ds- (d, ds'', gCs', w, h, maxW, minH) = renderSingleBlock b o ds' gCs globalWidth+ (d, ds'', gCs', _w, _h, maxW, minH) = renderSingleBlock b o ds' gCs globalWidth (d', ds''', gCs'', w', h', maxW', minH') = renderSingleSkewer bs (p2 (oX, minH)) ds'' gCs' (maxW + 0.1) in (d <> d' <> renderConnection [p2 (oX, minH), p2 (oX, oY)], ds''', gCs'', w', h', max maxW maxW', minH') @@ -136,26 +143,27 @@ [[Block]] -> (Diagram B, Map ID (Point V2 Double), ([(Double, Double)], [(Double, Double, Double)], Double), [(Point V2 Double, Double, Double, ID)], Double, Double, Double, [[Block]]) renderAllSkewers' rD ds bCs gCs w h maxH [] = (rD, ds, bCs, gCs, w, h, maxH, [])-renderAllSkewers' accuRD accuDs accuBCs@(uBCs, lBCs, minD) accuGCs accuW accuH accuMaxH [b] =- let (rD, ds, gCs, w, h, maxW, maxH) = renderSingleSkewer b (p2 (accuW, accuH)) accuDs accuGCs accuW+renderAllSkewers' accuRD accuDs (uBCs, lBCs, minD) accuGCs accuW accuH _accuMaxH [b] =+ let (rD, ds, gCs, _w, _h, maxW, maxH) = renderSingleSkewer b (p2 (accuW, accuH)) accuDs accuGCs accuW in renderAllSkewers' (accuRD <> rD) ds (uBCs, lBCs, min minD maxH) gCs maxW accuH (min minD maxH) []-renderAllSkewers' accuRD accuDs (uBCs, lBCs, minD) accuGCs accuW accuH accuMaxH (b : bs) =- let (rD, ds, gCs, w, h, maxW, maxH) = renderSingleSkewer b (p2 (accuW, accuH)) accuDs accuGCs accuW+renderAllSkewers' accuRD accuDs (uBCs, lBCs, minD) accuGCs accuW accuH _accuMaxH (b : bs) =+ let (rD, ds, gCs, _w, h, maxW, maxH) = renderSingleSkewer b (p2 (accuW, accuH)) accuDs accuGCs accuW in renderAllSkewers' (accuRD <> rD) ds ((accuW, maxW) : uBCs, (accuW, maxW, h) : lBCs, min minD maxH) gCs maxW accuH (min minD maxH) bs renderAllSkewers :: [[Block]] -> (Diagram B, Map ID (Point V2 Double), ([(Double, Double)], [(Double, Double, Double)], Double), [(Point V2 Double, Double, Double, ID)], Double, Double, Double, [[Block]])+renderAllSkewers [] = error "no skewers provided" renderAllSkewers blocks@(b : bs) = let manyBlocks = length blocks > 2- (rD, ds, (uBCs, lBCs, minD), gCs, w, h, maxH, _) = renderAllSkewers' mempty Data.Map.empty ([], [], 0.0) [] 0.0 0.0 0.0 [b]+ (rD, ds, (uBCs, lBCs, minD), gCs, w, _h, maxH, _) = renderAllSkewers' mempty Data.Map.empty ([], [], 0.0) [] 0.0 0.0 0.0 [b] uBCs' = if null bs then uBCs else (0.0, w) : uBCs lBCs' = if null bs then lBCs else (0.0, w, maxH) : lBCs (rD', ds', (uBCs'', lBCs'', minD'), gCs', w', h', maxH', _) = renderAllSkewers' rD ds (uBCs', lBCs', minD) gCs w (negate defaultBoundingBoxHeight) maxH bs in (rD', ds', (uBCs'', lBCs'', minD'), gCs', w', h', if manyBlocks then maxH' else maxH, b : bs) -render' :: [[Block]] -> Diagram B-render' [] = mempty-render' bs =- let (rD', ds', (uBCs, lBCs, minD), gCs', w', h', maxH', _) = renderAllSkewers bs+renderDiagram' :: [[Block]] -> Diagram B+renderDiagram' [] = mempty+renderDiagram' bs =+ let (rD', ds', (uBCs, lBCs, _minD), gCs', _w', _h', maxH', _) = renderAllSkewers bs bCs = case length bs of 1 -> mempty _ ->@@ -172,9 +180,49 @@ (rD' <> bCs) gCs' -render :: [[Block]] -> Diagram B-render [] = mempty-render [b] = render' $ Blocks.reverse [(EndTerminator : b) <> [StartTerminator]]-render bs =- let bs' = tail bs- in render' . Blocks.reverse $ ((EndTerminator : head bs) : init bs') <> [last bs' <> [StartTerminator]]+renderDiagram :: [[Block]] -> Diagram B+renderDiagram [] = mempty+renderDiagram [b] = renderDiagram' $ Blocks.reverse [(EndTerminator : b) <> [StartTerminator]]+renderDiagram (b : bs) = renderDiagram' . Blocks.reverse $ ((EndTerminator : b) : init bs) <> [last bs <> [StartTerminator]]++validateSingleBlock :: Block -> [ID] -> (Bool, String)+validateSingleBlock (Fork (Just i) _ _ _ (Just gCId)) ids = if gCId == i || gCId `elem` ids then (True, "") else (False, "Gamma connection ID: " <> show gCId <> " does not exist in the collection of block identifiers.")+validateSingleBlock (Fork Nothing _ _ _ (Just gCId)) ids = if gCId `elem` ids then (True, "") else (False, "Gamma connection ID: " <> show gCId <> " does not exist in the collection of block identifiers.")+validateSingleBlock (Fork _ _ _ _ Nothing) _ = (True, "")+validateSingleBlock _ _ = (True, "")++validateBlocks' :: [Block] -> Either [Block] ([String], [ID])+validateBlocks' [] = Left []+validateBlocks' [b] = Left [b]+validateBlocks' bs =+ let (errors, ids) =+ foldr+ ( \singleBlock (accuErrors, accuIds) ->+ let (isValid, errorMessage) = validateSingleBlock singleBlock accuIds+ in (if isValid then accuErrors else errorMessage : accuErrors, getAllIdentifiers singleBlock <> accuIds)+ )+ ([], [])+ bs+ in case errors of+ [] -> Left bs+ _ -> Right (errors, ids)++validateBlocks :: [[Block]] -> Either [[Block]] ([String], [ID])+validateBlocks [] = Left []+validateBlocks (b : []) =+ case validateBlocks' b of+ Left b' -> Left [b']+ Right errors -> Right errors+validateBlocks bs =+ let validationResult@(allErrors, allIds) =+ foldl+ ( \accu@(accuErrors, accuIds) b ->+ case validateBlocks' b of+ Left _ -> accu+ Right (errors, ids) -> (errors <> accuErrors, ids <> accuIds)+ )+ ([], [])+ bs+ in case allErrors of+ [] -> Left bs+ _ -> Right validationResult
src/lib/Constants.hs view
@@ -1,7 +1,6 @@ module Constants where import Data.Colour.SRGB (sRGB)-import Data.Text (empty) import Diagrams.Backend.SVG ( B, Options (SVGOptions),@@ -50,7 +49,6 @@ svgOptions = SVGOptions { _size = mkSizeSpec $ V2 (Just 1920) (Just 1080),- _idPrefix = empty, _svgDefinitions = Nothing, _svgAttributes = [], _generateDoctype = True
src/lib/HelperDiagrams.hs view
@@ -128,12 +128,19 @@ renderConnection :: [Point V2 Double] -> Diagram B renderConnection coordinates = fromVertices coordinates # wyvernStyle +-- 2026-03-25 PJ:+-- ##############+-- TODO:++-- * we need a max x for the destination block++-- we only have the max x for the origin block renderGammaConnection :: Point V2 Double -> Point V2 Double -> Double -> Double -> Diagram B renderGammaConnection gO@(P (V2 gOX gOY)) gD@(P (V2 gDX gDY)) maxX minY =- let gD'@(P (V2 gDX' gDY')) = p2 (gDX + (0.1 * sqrt 3.0 / 2.0) + 0.012, gDY + defaultBoundingBoxHeight * 0.5)+ let gD'@(P (V2 gDX' gDY')) = p2 (gDX + (0.1 * sqrt 3.0 / 2.0) + 0.012, gDY + defaultBoundingBoxHeight * 0.5 - 0.1) gammaMidpoint1 = p2 (gOX, minY)- gammaMidpoint2 = p2 (maxX - defaultBoundingBoxWidth * 0.5, minY)- gammaMidpoint3 = p2 (maxX - defaultBoundingBoxWidth * 0.5, gDY')+ gammaMidpoint2 = p2 (if gDX > gOX then gDX + defaultBoundingBoxWidth * 0.5 else maxX - defaultBoundingBoxWidth * 0.5, minY)+ gammaMidpoint3 = p2 (if gDX > gOX then gDX + defaultBoundingBoxWidth * 0.5 else maxX - defaultBoundingBoxWidth * 0.5, gDY') coordinates = [gO, gammaMidpoint1, gammaMidpoint2, gammaMidpoint3, gD'] in renderConnection coordinates <> position [(p2 (gDX' - 0.025, gDY'), rotateBy (1 / 4) $ triangle 0.1 # wyvernStyle)] @@ -145,7 +152,7 @@ p2 (uBCb, maxD + defaultBoundingBoxHeight * 0.5), p2 (uBCb, maxD + defaultBoundingBoxHeight * heightRatio * 0.5) ]-renderUpperBetaConnections (uBC@(uBCa, uBCb) : uBCs) maxD =+renderUpperBetaConnections ((uBCa, uBCb) : uBCs) maxD = renderConnection [ p2 (uBCa, maxD + defaultBoundingBoxHeight * 0.5), p2 (uBCb, maxD + defaultBoundingBoxHeight * 0.5),@@ -154,7 +161,7 @@ <> renderUpperBetaConnections uBCs maxD renderSideBetaConnection :: Point V2 Double -> Point V2 Double -> Diagram B-renderSideBetaConnection a@(P (V2 aX aY)) b@(P (V2 bX bY)) =+renderSideBetaConnection a@(P (V2 aX aY)) (P (V2 bX bY)) = renderConnection [ a, p2 (aX - defaultBoundingBoxWidth * 0.5, aY),@@ -165,12 +172,12 @@ renderLowerBetaConnections' :: [(Double, Double, Double)] -> Double -> Diagram B renderLowerBetaConnections' [] _ = mempty-renderLowerBetaConnections' (lBC@(lBCa, lBCb, lBCc) : lBCs) minD =+renderLowerBetaConnections' ((lBCa, lBCb, lBCc) : lBCs) minD = renderConnection [p2 (lBCa, lBCc + defaultBoundingBoxHeight), p2 (lBCa, minD), p2 (lBCb, minD)] <> renderLowerBetaConnections' lBCs minD renderLowerBetaConnections :: [(Double, Double, Double)] -> Double -> Diagram B renderLowerBetaConnections [] _ = mempty-renderLowerBetaConnections (lBC@(lBCa, lBCb, lBCc) : lBCs) minD =+renderLowerBetaConnections ((lBCa, _lBCb, lBCc) : lBCs) minD = renderConnection [p2 (lBCa, lBCc + defaultBoundingBoxHeight), p2 (lBCa, minD)] <> renderLowerBetaConnections' lBCs minD
src/lib/ID.hs view
@@ -2,7 +2,6 @@ newtype ID = ID String- deriving (Show) instance Eq ID where (==) (ID a) (ID b) = a == b@@ -15,3 +14,6 @@ (<=) (ID a) (ID b) = a <= b min (ID a) (ID b) = ID $ min a b max (ID a) (ID b) = ID $ max a b++instance Show ID where+ show (ID x) = show x
wyvern-diagrams.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.4 name: wyvern-diagrams-version: 0.4.1.0+version: 0.4.2.0 synopsis: Simple flowchart diagrams. Inspired by DRAKON. description: Wyvern combines syntax and rendering engine for simple, DRAKON-like flowcharts.@@ -38,8 +38,6 @@ base >= 4.19.2.0 && < 5, -- MIT colour >= 2.3.6 && < 3,- -- BSD-2-Clause- text >= 2.1.2 && < 3, -- BSD-3-Clause diagrams-lib >= 1.5.1 && < 2, -- BSD-3-Clause@@ -47,11 +45,11 @@ -- BSD-3-Clause containers >= 0.7 && < 1, -- BSD-3-Clause+ -- Used in Parser. MissingH >= 1.6.0 && < 2, -- BSD-3-Clause+ -- Used in Lexer. array >= 0.5.8 && < 1,- -- BSD-3-Clause- unordered-containers >= 0.2.21 && < 1, -- BSD-3-Clause optparse-applicative >= 0.19.0 && < 1 default-language: Haskell2010