@slxu/graphsx 0.1.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.
- package/LICENSE +21 -0
- package/README.md +588 -0
- package/docs/assets/basic-graph.svg +15 -0
- package/docs/assets/plot-heart.svg +15 -0
- package/docs/assets/tensor-repeat.svg +15 -0
- package/package.json +56 -0
- package/src/codemirror.css +66 -0
- package/src/codemirror.js +225 -0
- package/src/document.js +71 -0
- package/src/errors.js +7 -0
- package/src/index.js +42 -0
- package/src/literals.js +436 -0
- package/src/markdown.css +24 -0
- package/src/markdown.js +111 -0
- package/src/markup.js +219 -0
- package/src/parser.js +1463 -0
- package/src/plot-math.js +459 -0
- package/src/plot-renderer.js +1025 -0
- package/src/plot.js +842 -0
- package/src/renderer.js +987 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg viewBox="-18 -18 466 370" width="466" height="370" xmlns="http://www.w3.org/2000/svg"><style>
|
|
2
|
+
.shape { fill: #ffffff; stroke: #26312d; stroke-width: 2; }
|
|
3
|
+
.node-label { font: 700 14px ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #1e2724; pointer-events: none; }
|
|
4
|
+
.leg-label { font: 11px ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #52605a; pointer-events: none; }
|
|
5
|
+
.edge { fill: none; stroke: #2d6cdf; stroke-width: 2.5; }
|
|
6
|
+
.path { fill: none; stroke: #111111; stroke-width: 2; }
|
|
7
|
+
.leg-dot { fill: #16846f; stroke: #ffffff; stroke-width: 2; }
|
|
8
|
+
.plot-frame, .plot-box { fill: none; stroke: #26312d; stroke-width: 1.8; }
|
|
9
|
+
.plot-axis { stroke: #26312d; stroke-width: 1.8; }
|
|
10
|
+
.plot-tick { stroke: #26312d; stroke-width: 1.3; }
|
|
11
|
+
.plot-grid { stroke: #d8ded8; stroke-width: 1; }
|
|
12
|
+
.plot-line, .plot-curve { fill: none; stroke: #2563eb; stroke-width: 2; }
|
|
13
|
+
.plot-line-marker { fill: #ffffff; stroke: #2563eb; stroke-width: 2; }
|
|
14
|
+
.plot-axis-label, .plot-tick-label, .plot-label { font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #1e2724; }
|
|
15
|
+
</style><defs><clipPath id="graphsx-plot-clip-1"><rect x="46" y="30" width="346" height="260"></rect></clipPath></defs><g class="plot-frame-layer"><rect class="plot-frame" x="0" y="0" width="430" height="330" fill="none" stroke="#cbd5d0" stroke-width="1"></rect></g><g class="plot-axes"><rect class="plot-box" x="46" y="30" width="346" height="260" fill="none" stroke="#26312d" stroke-width="1.5"></rect><line class="plot-axis plot-axis-x" stroke="#26312d" stroke-width="1.5" x1="46" y1="290" x2="392" y2="290"></line><line class="plot-grid plot-grid-x" stroke="#d8ded8" stroke-width="1" x1="74.83333333333333" y1="30" x2="74.83333333333333" y2="290"></line><line class="plot-tick plot-tick-x" stroke="#26312d" stroke-width="1" x1="74.83333333333333" y1="290" x2="74.83333333333333" y2="296"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="74.83333333333333" y="304" text-anchor="middle" dominant-baseline="hanging">-15</text><line class="plot-grid plot-grid-x" stroke="#d8ded8" stroke-width="1" x1="122.88888888888889" y1="30" x2="122.88888888888889" y2="290"></line><line class="plot-tick plot-tick-x" stroke="#26312d" stroke-width="1" x1="122.88888888888889" y1="290" x2="122.88888888888889" y2="296"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="122.88888888888889" y="304" text-anchor="middle" dominant-baseline="hanging">-10</text><line class="plot-grid plot-grid-x" stroke="#d8ded8" stroke-width="1" x1="170.94444444444446" y1="30" x2="170.94444444444446" y2="290"></line><line class="plot-tick plot-tick-x" stroke="#26312d" stroke-width="1" x1="170.94444444444446" y1="290" x2="170.94444444444446" y2="296"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="170.94444444444446" y="304" text-anchor="middle" dominant-baseline="hanging">-5</text><line class="plot-grid plot-grid-x" stroke="#d8ded8" stroke-width="1" x1="219" y1="30" x2="219" y2="290"></line><line class="plot-tick plot-tick-x" stroke="#26312d" stroke-width="1" x1="219" y1="290" x2="219" y2="296"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="219" y="304" text-anchor="middle" dominant-baseline="hanging">0</text><line class="plot-grid plot-grid-x" stroke="#d8ded8" stroke-width="1" x1="267.05555555555554" y1="30" x2="267.05555555555554" y2="290"></line><line class="plot-tick plot-tick-x" stroke="#26312d" stroke-width="1" x1="267.05555555555554" y1="290" x2="267.05555555555554" y2="296"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="267.05555555555554" y="304" text-anchor="middle" dominant-baseline="hanging">5</text><line class="plot-grid plot-grid-x" stroke="#d8ded8" stroke-width="1" x1="315.11111111111114" y1="30" x2="315.11111111111114" y2="290"></line><line class="plot-tick plot-tick-x" stroke="#26312d" stroke-width="1" x1="315.11111111111114" y1="290" x2="315.11111111111114" y2="296"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="315.11111111111114" y="304" text-anchor="middle" dominant-baseline="hanging">10</text><line class="plot-grid plot-grid-x" stroke="#d8ded8" stroke-width="1" x1="363.16666666666663" y1="30" x2="363.16666666666663" y2="290"></line><line class="plot-tick plot-tick-x" stroke="#26312d" stroke-width="1" x1="363.16666666666663" y1="290" x2="363.16666666666663" y2="296"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="363.16666666666663" y="304" text-anchor="middle" dominant-baseline="hanging">15</text><text class="plot-axis-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="219" y="330" text-anchor="middle">x</text><line class="plot-axis plot-axis-y" stroke="#26312d" stroke-width="1.5" x1="46" y1="30" x2="46" y2="290"></line><line class="plot-grid plot-grid-y" stroke="#d8ded8" stroke-width="1" x1="46" y1="265.625" x2="392" y2="265.625"></line><line class="plot-tick plot-tick-y" stroke="#26312d" stroke-width="1" x1="46" y1="265.625" x2="40" y2="265.625"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="32" y="265.625" text-anchor="end" dominant-baseline="middle">-15</text><line class="plot-grid plot-grid-y" stroke="#d8ded8" stroke-width="1" x1="46" y1="225" x2="392" y2="225"></line><line class="plot-tick plot-tick-y" stroke="#26312d" stroke-width="1" x1="46" y1="225" x2="40" y2="225"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="32" y="225" text-anchor="end" dominant-baseline="middle">-10</text><line class="plot-grid plot-grid-y" stroke="#d8ded8" stroke-width="1" x1="46" y1="184.375" x2="392" y2="184.375"></line><line class="plot-tick plot-tick-y" stroke="#26312d" stroke-width="1" x1="46" y1="184.375" x2="40" y2="184.375"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="32" y="184.375" text-anchor="end" dominant-baseline="middle">-5</text><line class="plot-grid plot-grid-y" stroke="#d8ded8" stroke-width="1" x1="46" y1="143.75" x2="392" y2="143.75"></line><line class="plot-tick plot-tick-y" stroke="#26312d" stroke-width="1" x1="46" y1="143.75" x2="40" y2="143.75"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="32" y="143.75" text-anchor="end" dominant-baseline="middle">0</text><line class="plot-grid plot-grid-y" stroke="#d8ded8" stroke-width="1" x1="46" y1="103.125" x2="392" y2="103.125"></line><line class="plot-tick plot-tick-y" stroke="#26312d" stroke-width="1" x1="46" y1="103.125" x2="40" y2="103.125"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="32" y="103.125" text-anchor="end" dominant-baseline="middle">5</text><line class="plot-grid plot-grid-y" stroke="#d8ded8" stroke-width="1" x1="46" y1="62.5" x2="392" y2="62.5"></line><line class="plot-tick plot-tick-y" stroke="#26312d" stroke-width="1" x1="46" y1="62.5" x2="40" y2="62.5"></line><text class="plot-tick-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="32" y="62.5" text-anchor="end" dominant-baseline="middle">10</text><text class="plot-axis-label" fill="#111111" font-size="12" font-family="ui-sans-serif, system-ui, sans-serif" x="6" y="160" text-anchor="middle" transform="rotate(-90 6 160)">y</text></g><g class="plot-data" clip-path="url(#graphsx-plot-clip-1)"><g class="plot-line"><path class="plot-line" fill="none" stroke="#e11d48" stroke-width="2.6" d="M 219 103.125 L 219.00082429624882 103.0739945095811 L 219.00659134058247 102.92116279870797 L 219.0222287430902 102.66705846489674 L 219.05263388005736 102.31260189474642 L 219.10265888241665 101.85907686002446 L 219.17709575029565 101.30812577209542 L 219.2806616351535 100.66174361449453 L 219.4179843305328 99.92227057895204 L 219.5935880118811 99.09238343556692 L 219.81187926520576 98.17508567308107 L 220.0771334435311 97.17369645029814 L 220.39348138922054 96.09183840460037 L 220.7648965592183 94.9334243682172 L 221.1951825891518 93.70264304737978 L 221.68796133102575 92.40394372371955 L 222.24666139793163 91.04202004123789 L 222.87450724779669 89.62179294585138 L 223.5745088367093 88.14839284790222 L 224.3494518707856 86.62714108108895 L 225.20188868388945 85.06353073401615 L 226.13412976679197 83.46320693296249 L 227.14823597155788 81.83194665651979 L 228.2460114130811 80.17563816445193 L 229.4289970877709 78.50026012445082 L 230.69846522740676 76.81186052143002 L 232.05541440415348 75.1165354345799 L 233.5005654006527 73.42040776762323 L 235.03435785699628 71.72960601754374 L 236.6569477042417 70.05024316652228 L 238.3682053919578 68.38839578090872 L 240.16771491509795 66.75008339978183 L 242.0547736432899 65.14124829401788 L 244.0283929534167 63.56773567480576 L 246.08729966414376 62.03527442822303 L 248.2299382688347 60.54945844983601 L 250.45447396109122 59.11572865031789 L 252.75879644496558 57.739355699811995 L 255.14052451972472 56.42542357521086 L 257.59701142690756 55.178813970699565 L 260.1253509453103 54.004191627840356 L 262.72238421746727 52.905990637169225 L 265.3847072891758 51.88840175876385 L 268.1086793416414 50.95536080453911 L 270.89043159390553 50.110538120156036 L 273.7258768513672 49.35732919941901 L 276.6107196744195 48.69884645890113 L 279.54046713951357 48.137912195309525 L 282.5104401633164 47.677052742799674 L 285.51578535907845 47.31849384210037 L 288.5514873928489 47.06415722793932 L 291.6123818057959 46.91565843588961 L 294.69316826759626 46.87430582441692 L 297.7884242246673 46.94110080261589 L 300.89261890591627 47.11673924890911 L 304.00012764769275 47.40161410086807 L 307.10524649874367 47.795819091320084 L 310.20220706519024 48.29915360106159 L 313.2851915548798 48.91112859381238 L 316.3483479799095 49.630973594556934 L 319.3858054756741 50.45764466813023 L 322.39168969446445 51.3898333508493 L 325.3601382314294 52.42597648417603 L 328.28531604061845 53.564266895843645 L 331.1614307988419 54.802664870602825 L 333.9827481752231 56.13891034975555 L 336.7436069645696 57.570535795960154 L 339.43843404305744 59.094879657420734 L 342.0617591052064 60.70910036352436 L 344.60822914171916 62.410190782273304 L 347.0726226184631 64.19499306847811 L 349.4498633176914 66.06021383063876 L 351.7350338035224 68.00243954374614 L 353.92338847472394 70.01815213488982 L 356.01036616898017 72.10374466855157 L 357.9916022840468 74.25553705880958 L 359.86294038252305 76.46979173635481 L 361.62044324838683 78.7427291992403 L 363.2604033649394 81.07054337762557 L 364.77935278539655 83.44941674444215 L 366.1740723690254 85.87553510588089 L 367.44160035747086 88.34510200787133 L 368.5792402677218 90.85435269728148 L 369.58456808004775 93.39956757939768 L 370.4554387011673 95.97708511632646 L 371.18999168490194 98.58331411429035 L 371.78665619460594 101.21474535133476 L 372.2441551937472 103.86796250071899 L 372.56150885312917 106.53965230919954 L 372.73803716539874 109.22661399351776 L 372.77336175965996 111.92576782264885 L 372.6674069112105 114.63416285773675 L 372.4203997436274 117.3489838261082 L 372.0328696226479 120.06755711030334 L 371.5056467435097 122.78735583766249 L 370.83985991562906 125.50600406063919 L 370.0369335507023 128.22128002265308 L 369.09858386249914 130.93111850892305 L 368.02681428878657 133.63361228631356 L 366.8239101479516 136.32701264076002 L 365.4924325449986 139.00972902529122 L 364.0352115436525 141.68032783601754 L 362.45533862331865 144.3375303376803 L 360.75615844160757 146.98020976444272 L 358.9412599250467 149.60738762552194 L 357.0144667124348 152.21822924900542 L 354.97982697708136 154.81203860073242 L 352.8416026558702 157.388252418451 L 350.6042581147154 159.94643370455572 L 348.27244828152544 162.4862646235623 L 345.85100627924885 165.00753885307103 L 343.3449305929446 167.5101534392952 L 340.7593718060998 169.9941002102778 L 338.0996189425937 172.4594568016788 L 335.3710854517881 174.90637735147985 L 332.57929487520084 177.33508292111634 L 329.7298662340864 179.74585170140813 L 326.8284991780132 182.1390090622101 L 323.8809589351744 184.51491750495074 L 320.89306110571346 186.87396657716027 L 317.8706563397648 189.21656280772362 L 314.81961494222486 191.54311972092157 L 311.7458114464641 193.85404798635358 L 308.65510919926356 196.14974576058086 L 305.5533449992299 198.43058927478322 L 302.44631383077984 200.69692372091384 L 299.33975373552244 202.94905448675593 L 296.2393308624752 205.1872387879623 L 293.15062473805745 207.41167774259273 L 290.07911379618486 209.62250893088122 L 287.03016120807087 211.81979947996905 L 284.00900105050687 214.00353971015795 L 281.02072485045164 216.17363737588119 L 278.0702685427204 218.3299125310757 L 275.1623998764158 220.47209304499407 L 272.30170630450334 222.59981079072605 L 269.49258338959316 224.71259852484258 L 266.7392237575643 226.80988747263314 L 264.045606629148 228.89100562941897 L 261.4154879579935 230.955176784394 L 258.8523912020557 233.00152026940813 L 256.3595987533994 235.02905143107384 L 253.94014404969076 237.0366828205744 L 251.5968043887627 239.02322609160024 L 249.33209446570115 240.98739459295402 L 247.14826064989742 242.92780663857684 L 245.04727601747317 244.8429894340609 L 243.03083615239197 246.7313836351646 L 241.10035572745377 248.5913485104351 L 239.25696587420873 250.42116767680545 L 237.50151234865328 252.21905537396742 L 235.8345544973692 253.98316324046027 L 234.25636502655905 255.71158755175838 L 232.76693057421267 257.4023768782123 L 231.36595308342166 259.05354011850403 L 230.0528519726489 260.66305486232886 L 228.82676709655584 262.22887603433 L 227.68656248881314 263.7489447698824 L 226.63083087615485 265.22119747217437 L 225.6578989508146 266.64357499915525 L 224.765833386381 268.01403192832595 L 223.9524475800648 269.33054584703564 L 223.2153091023591 270.5911266159235 L 222.5517478331249 271.79382555340067 L 221.95886476123894 272.93674448960815 L 221.43354142310795 274.0180446391048 L 220.9724499535921 275.03595524263227 L 220.5720637211883 275.988781929664 L 220.22866851771334 276.8749147550652 L 219.9383742711946 277.6928358650621 L 219.6971272492335 278.4411267498297 L 219.50072271875305 279.11847504234925 L 219.34481802678033 279.7236808257408 L 219.22494606575415 280.25566241403976 L 219.13652908578604 280.71346157432777 L 219.07489281534527 281.0962481612512 L 219.03528085098873 281.4033241382314 L 219.0128692760115 281.6341269630812 L 219.00278146726484 281.7882323192723 L 219.00010304886766 281.86535617772876 L 218.99989695113234 281.86535617772876 L 218.99721853273516 281.7882323192723 L 218.98713072398849 281.6341269630812 L 218.96471914901127 281.4033241382314 L 218.92510718465473 281.09624816125125 L 218.86347091421396 280.71346157432777 L 218.77505393424585 280.2556624140398 L 218.65518197321967 279.7236808257408 L 218.499277281247 279.11847504234925 L 218.30287275076654 278.4411267498298 L 218.0616257288054 277.6928358650621 L 217.77133148228666 276.8749147550652 L 217.4279362788117 275.988781929664 L 217.02755004640795 275.0359552426323 L 216.56645857689207 274.01804463910486 L 216.04113523876111 272.9367444896082 L 215.4482521668751 271.7938255534007 L 214.78469089764096 270.5911266159236 L 214.04755241993522 269.3305458470357 L 213.23416661361904 268.014031928326 L 212.34210104918543 266.6435749991553 L 211.36916912384518 265.22119747217437 L 210.31343751118695 263.7489447698824 L 209.1732329034442 262.2288760343301 L 207.9471480273512 260.663054862329 L 206.63404691657834 259.0535401185041 L 205.23306942578742 257.4023768782124 L 203.74363497344103 255.71158755175847 L 202.16544550263092 253.98316324046039 L 200.4984876513468 252.21905537396748 L 198.74303412579135 250.4211676768055 L 196.89964427254628 248.59134851043518 L 194.9691638476081 246.7313836351647 L 192.95272398252692 244.84298943406102 L 190.85173935010266 242.92780663857693 L 188.66790553429902 240.98739459295416 L 186.40319561123738 239.02322609160032 L 184.05985595030938 237.03668282057453 L 181.6404012466007 235.02905143107387 L 179.14760879794449 233.00152026940825 L 176.5845120420066 230.9551767843941 L 173.95439337085213 228.89100562941906 L 171.26077624243587 226.80988747263322 L 168.50741661040695 224.7125985248427 L 165.69829369549683 222.59981079072614 L 162.83760012358434 220.47209304499418 L 159.92973145727976 218.32991253107585 L 156.97927514954847 216.17363737588127 L 153.9909989494933 214.0035397101581 L 150.9698387919293 211.81979947996913 L 147.92088620381531 209.62250893088137 L 144.84937526194275 207.41167774259287 L 141.7606691375249 205.18723878796231 L 138.66024626447773 202.94905448675598 L 135.55368616922027 200.69692372091396 L 132.44665500077028 198.43058927478336 L 129.3448908007366 196.14974576058103 L 126.25418855353605 193.8540479863537 L 123.18038505777527 191.54311972092165 L 120.12934366023542 189.21656280772376 L 117.10693889428669 186.87396657716045 L 114.11904106482568 184.51491750495086 L 111.17150082198692 182.13900906221022 L 108.27013376591366 179.7458517014082 L 105.42070512479935 177.3350829211165 L 102.628914548212 174.90637735147993 L 99.90038105740643 172.45945680167893 L 97.2406281939003 169.9941002102779 L 94.65506940705552 167.51015343929535 L 92.14899372075128 165.0075388530712 L 89.72755171847464 162.48626462356236 L 87.39574188528476 159.94643370455583 L 85.15839734412991 157.38825241845112 L 83.02017302291875 154.8120386007326 L 80.98553328756529 152.2182292490055 L 79.05874007495336 149.60738762552205 L 77.24384155839249 146.98020976444283 L 75.54466137668152 144.3375303376805 L 73.96478845634756 141.68032783601774 L 72.50756745500148 139.00972902529128 L 71.17608985204842 136.32701264076013 L 69.97318571121349 133.63361228631368 L 68.90141613750095 130.93111850892322 L 67.9630664492978 128.22128002265313 L 67.16014008437094 125.5060040606393 L 66.49435325649034 122.78735583766263 L 65.96713037735212 120.06755711030351 L 65.57960025637266 117.3489838261084 L 65.33259308878951 114.63416285773684 L 65.22663824034004 111.92576782264896 L 65.26196283460129 109.22661399351787 L 65.4384911468708 106.53965230919971 L 65.75584480625281 103.86796250071907 L 66.21334380539408 101.21474535133487 L 66.81000831509805 98.58331411429046 L 67.54456129883262 95.97708511632663 L 68.41543191995227 93.39956757939774 L 69.42075973227824 90.85435269728157 L 70.55839964252911 88.34510200787147 L 71.82592763097449 85.87553510588108 L 73.22064721460336 83.44941674444229 L 74.73959663506055 81.07054337762563 L 76.37955675161318 78.74272919924042 L 78.13705961747687 76.46979173635489 L 80.00839771595314 74.2555370588097 L 81.98963383101977 72.10374466855163 L 84.07661152527598 70.01815213488987 L 86.26496619647749 68.00243954374628 L 88.55013668230845 66.06021383063887 L 90.92737738153679 64.19499306847828 L 93.39177085828078 62.41019078227336 L 95.93824089479347 60.70910036352441 L 98.56156595694242 59.09487965742079 L 101.25639303543022 57.57053579596024 L 104.01725182477686 56.138910349755605 L 106.83856920115804 54.80266487060288 L 109.71468395938142 53.5642668958437 L 112.63986176857041 52.42597648417609 L 115.6083103055355 51.38983335084933 L 118.6141945243258 50.45764466813023 L 121.65165202009034 49.63097359455699 L 124.71480844512004 48.911128593812435 L 127.79779293480958 48.29915360106162 L 130.89475350125622 47.795819091320084 L 133.99987235230716 47.40161410086807 L 137.10738109408362 47.11673924890911 L 140.21157577533248 46.94110080261589 L 143.30683173240368 46.87430582441689 L 146.38761819420398 46.915658435889554 L 149.44851260715092 47.06415722793932 L 152.48421464092138 47.31849384210037 L 155.4895598366834 47.67705274279962 L 158.45953286048632 48.13791219530947 L 161.38928032558033 48.69884645890113 L 164.27412314863267 49.357329199418956 L 167.10956840609418 50.11053812015598 L 169.89132065835855 50.955360804539055 L 172.6152927108241 51.88840175876382 L 175.2776157825326 52.90599063716914 L 177.87464905468954 54.00419162784027 L 180.40298857309224 55.17881397069948 L 182.85947548027522 56.42542357521077 L 185.24120355503428 57.739355699811966 L 187.5455260389086 59.11572865031778 L 189.77006173116516 60.549458449835896 L 191.9127003358562 62.035274428223005 L 193.97160704658324 63.56773567480565 L 195.94522635670998 65.14124829401783 L 197.83228508490197 66.75008339978177 L 199.63179460804216 68.3883957809087 L 201.3430522957582 70.0502431665222 L 202.96564214300363 71.72960601754369 L 204.49943459934724 73.42040776762315 L 205.94458559584643 75.11653543457979 L 207.3015347725932 76.81186052142994 L 208.5710029122291 78.50026012445076 L 209.75398858691884 80.17563816445181 L 210.85176402844206 81.83194665651968 L 211.86587023320797 83.46320693296246 L 212.79811131611052 85.06353073401607 L 213.65054812921437 86.6271410810889 L 214.42549116329062 88.14839284790213 L 215.12549275220326 89.6217929458513 L 215.75333860206834 91.04202004123786 L 216.31203866897422 92.4039437237195 L 216.80481741084816 93.70264304737972 L 217.23510344078164 94.93342436821715 L 217.60651861077946 96.09183840460034 L 217.9228665564689 97.17369645029811 L 218.18812073479424 98.17508567308099 L 218.40641198811892 99.09238343556686 L 218.5820156694672 99.92227057895201 L 218.71933836484646 100.66174361449453 L 218.82290424970432 101.3081257720954 L 218.89734111758335 101.85907686002443 L 218.94736611994264 102.3126018947464 L 218.97777125690982 102.66705846489674 L 218.9934086594175 102.92116279870797 L 218.99917570375115 103.0739945095811 L 219 103.125"></path></g></g><g class="plot-annotations"></g><g class="plot-labels"></g><g class="plot-legends"></g></svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg viewBox="62 62 378 126" width="378" height="126" xmlns="http://www.w3.org/2000/svg"><style>
|
|
2
|
+
.shape { fill: #ffffff; stroke: #26312d; stroke-width: 2; }
|
|
3
|
+
.node-label { font: 700 14px ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #1e2724; pointer-events: none; }
|
|
4
|
+
.leg-label { font: 11px ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #52605a; pointer-events: none; }
|
|
5
|
+
.edge { fill: none; stroke: #2d6cdf; stroke-width: 2.5; }
|
|
6
|
+
.path { fill: none; stroke: #111111; stroke-width: 2; }
|
|
7
|
+
.leg-dot { fill: #16846f; stroke: #ffffff; stroke-width: 2; }
|
|
8
|
+
.plot-frame, .plot-box { fill: none; stroke: #26312d; stroke-width: 1.8; }
|
|
9
|
+
.plot-axis { stroke: #26312d; stroke-width: 1.8; }
|
|
10
|
+
.plot-tick { stroke: #26312d; stroke-width: 1.3; }
|
|
11
|
+
.plot-grid { stroke: #d8ded8; stroke-width: 1; }
|
|
12
|
+
.plot-line, .plot-curve { fill: none; stroke: #2563eb; stroke-width: 2; }
|
|
13
|
+
.plot-line-marker { fill: #ffffff; stroke: #2563eb; stroke-width: 2; }
|
|
14
|
+
.plot-axis-label, .plot-tick-label, .plot-label { font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #1e2724; }
|
|
15
|
+
</style><defs></defs><g><path class="edge" d="M 107 134 L 107 170" style="stroke: #111111; stroke-width: 2.5"></path><path class="edge" d="M 203 134 L 203 170" style="stroke: #111111; stroke-width: 2.5"></path><path class="edge" d="M 299 134 L 299 170" style="stroke: #111111; stroke-width: 2.5"></path><path class="edge" d="M 395 134 L 395 170" style="stroke: #111111; stroke-width: 2.5"></path><path class="edge" d="M 134 107 L 176 107" style="stroke: #111111; stroke-width: 2.5"></path><path class="edge" d="M 230 107 L 272 107" style="stroke: #111111; stroke-width: 2.5"></path><path class="edge" d="M 326 107 L 368 107" style="stroke: #111111; stroke-width: 2.5"></path></g><g></g><g><g><g><rect class="shape" x="80" y="80" width="54" height="54" rx="8" style="fill: #6aa4d8; stroke: #111111; stroke-width: 3"></rect><text class="node-label" x="107" y="111" text-anchor="middle">A0</text><g><circle class="leg-dot" cx="80" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="134" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="107" cy="134" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g></g><g><circle class="leg-dot" cx="80" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="134" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="107" cy="134" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g></g><g></g><g><g><rect class="shape" x="176" y="80" width="54" height="54" rx="8" style="fill: #6aa4d8; stroke: #111111; stroke-width: 3"></rect><text class="node-label" x="203" y="111" text-anchor="middle">A1</text><g><circle class="leg-dot" cx="176" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="230" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="203" cy="134" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g></g><g><circle class="leg-dot" cx="176" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="230" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="203" cy="134" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g></g><g></g><g><g><rect class="shape" x="272" y="80" width="54" height="54" rx="8" style="fill: #6aa4d8; stroke: #111111; stroke-width: 3"></rect><text class="node-label" x="299" y="111" text-anchor="middle">A2</text><g><circle class="leg-dot" cx="272" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="326" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="299" cy="134" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g></g><g><circle class="leg-dot" cx="272" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="326" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="299" cy="134" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g></g><g></g><g><g><rect class="shape" x="368" y="80" width="54" height="54" rx="8" style="fill: #6aa4d8; stroke: #111111; stroke-width: 3"></rect><text class="node-label" x="395" y="111" text-anchor="middle">A3</text><g><circle class="leg-dot" cx="368" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="422" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="395" cy="134" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g></g><g><circle class="leg-dot" cx="368" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="422" cy="107" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g><g><circle class="leg-dot" cx="395" cy="134" r="0" style="fill: transparent; stroke: transparent; stroke-width: 0"></circle></g></g><g></g></g></svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@slxu/graphsx",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A small React-like inline graph DSL parser and model builder.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./codemirror": "./src/codemirror.js",
|
|
10
|
+
"./codemirror.css": "./src/codemirror.css",
|
|
11
|
+
"./markdown.css": "./src/markdown.css"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src/index.js",
|
|
15
|
+
"src/errors.js",
|
|
16
|
+
"src/literals.js",
|
|
17
|
+
"src/markup.js",
|
|
18
|
+
"src/parser.js",
|
|
19
|
+
"src/plot.js",
|
|
20
|
+
"src/plot-math.js",
|
|
21
|
+
"src/plot-renderer.js",
|
|
22
|
+
"src/renderer.js",
|
|
23
|
+
"src/markdown.js",
|
|
24
|
+
"src/markdown.css",
|
|
25
|
+
"src/codemirror.js",
|
|
26
|
+
"src/codemirror.css",
|
|
27
|
+
"src/document.js",
|
|
28
|
+
"docs/assets/*.svg",
|
|
29
|
+
"README.md"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "vite build",
|
|
33
|
+
"build:pages": "vite build --base=/graphsx/",
|
|
34
|
+
"dev": "vite --host 127.0.0.1",
|
|
35
|
+
"generate:readme-assets": "node scripts/generate-readme-assets.js",
|
|
36
|
+
"playground": "vite --host 127.0.0.1",
|
|
37
|
+
"test": "node --test"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"graph",
|
|
41
|
+
"dsl",
|
|
42
|
+
"parser",
|
|
43
|
+
"diagram"
|
|
44
|
+
],
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"vite": "^7.0.0"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@codemirror/lang-javascript": "^6.2.5",
|
|
51
|
+
"@codemirror/lang-markdown": "^6.5.0",
|
|
52
|
+
"codemirror": "^6.0.2",
|
|
53
|
+
"katex": "^0.17.0",
|
|
54
|
+
"markdown-it": "^14.2.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
.graphsx-live-widget {
|
|
2
|
+
display: block;
|
|
3
|
+
width: fit-content;
|
|
4
|
+
max-width: 100%;
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
margin: 0 auto;
|
|
7
|
+
border: 1px solid transparent;
|
|
8
|
+
border-radius: 8px;
|
|
9
|
+
padding: 20px 6px;
|
|
10
|
+
overflow: auto;
|
|
11
|
+
cursor: text;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.graphsx-live-widget:hover {
|
|
15
|
+
border-color: #d8ded8;
|
|
16
|
+
background: #ffffff;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.graphsx-live-widget svg {
|
|
20
|
+
position: static;
|
|
21
|
+
max-width: 100%;
|
|
22
|
+
height: auto;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.graphsx-live-def {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
gap: 8px;
|
|
29
|
+
width: fit-content;
|
|
30
|
+
max-width: 100%;
|
|
31
|
+
box-sizing: border-box;
|
|
32
|
+
margin: 0;
|
|
33
|
+
border: 1px solid #d8ded8;
|
|
34
|
+
border-radius: 6px;
|
|
35
|
+
padding: 8px 9px;
|
|
36
|
+
color: #68736e;
|
|
37
|
+
background: #f7f8f5;
|
|
38
|
+
font: 12px/1.3 ui-sans-serif, system-ui, sans-serif;
|
|
39
|
+
cursor: text;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.graphsx-live-def:hover {
|
|
43
|
+
border-color: #b7c1bb;
|
|
44
|
+
color: #1e2724;
|
|
45
|
+
background: #ffffff;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.graphsx-live-def code {
|
|
49
|
+
border-radius: 4px;
|
|
50
|
+
padding: 2px 5px;
|
|
51
|
+
color: #1e2724;
|
|
52
|
+
background: #eef2ee;
|
|
53
|
+
font: 12px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.graphsx-live-error {
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
margin: 0;
|
|
59
|
+
border: 1px solid #f2b8b5;
|
|
60
|
+
border-radius: 6px;
|
|
61
|
+
padding: 12px;
|
|
62
|
+
color: #b42318;
|
|
63
|
+
background: #fff8f7;
|
|
64
|
+
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
|
|
65
|
+
white-space: pre-wrap;
|
|
66
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { StateField } from "@codemirror/state";
|
|
2
|
+
import { Decoration, EditorView, WidgetType } from "@codemirror/view";
|
|
3
|
+
import { GRAPHSX_DEFS_FENCE, GRAPHSX_FENCE, parseFenceInfo, parseGraphWithLibraries } from "./markdown.js";
|
|
4
|
+
import { renderGraphSXDocument } from "./document.js";
|
|
5
|
+
|
|
6
|
+
export function graphsxCodeMirrorLivePreview(options = {}) {
|
|
7
|
+
const config = {
|
|
8
|
+
katex: options.katex,
|
|
9
|
+
renderOptions: {
|
|
10
|
+
minWidth: 0,
|
|
11
|
+
minHeight: 0,
|
|
12
|
+
viewportPadding: 24,
|
|
13
|
+
...options.renderOptions
|
|
14
|
+
},
|
|
15
|
+
classNames: {
|
|
16
|
+
graph: "graphsx-live-widget",
|
|
17
|
+
definition: "graphsx-live-def",
|
|
18
|
+
error: "graphsx-live-error",
|
|
19
|
+
...options.classNames
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return StateField.define({
|
|
24
|
+
create(state) {
|
|
25
|
+
return buildLiveMarkdownDecorations(state.doc.toString(), state.selection, config);
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
update(value, transaction) {
|
|
29
|
+
return transaction.docChanged || transaction.selection
|
|
30
|
+
? buildLiveMarkdownDecorations(transaction.state.doc.toString(), transaction.state.selection, config)
|
|
31
|
+
: value;
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
provide(field) {
|
|
35
|
+
return EditorView.decorations.from(field);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function buildLiveMarkdownDecorations(source, selection, config) {
|
|
41
|
+
const blocks = findGraphSXFences(source);
|
|
42
|
+
const libraries = collectFenceLibraries(blocks);
|
|
43
|
+
const ranges = [];
|
|
44
|
+
|
|
45
|
+
for (const block of blocks) {
|
|
46
|
+
if (selectionTouchesBlock(selection, block)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (block.info.name === GRAPHSX_DEFS_FENCE) {
|
|
51
|
+
ranges.push(Decoration.replace({
|
|
52
|
+
block: true,
|
|
53
|
+
widget: new GraphSXDefinitionWidget(block, config)
|
|
54
|
+
}).range(block.from, block.to));
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (block.info.name === GRAPHSX_FENCE) {
|
|
59
|
+
ranges.push(Decoration.replace({
|
|
60
|
+
block: true,
|
|
61
|
+
widget: new GraphSXPreviewWidget(block, libraries, config)
|
|
62
|
+
}).range(block.from, block.to));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return Decoration.set(ranges, true);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
class GraphSXDefinitionWidget extends WidgetType {
|
|
70
|
+
constructor(block, config) {
|
|
71
|
+
super();
|
|
72
|
+
this.from = block.from;
|
|
73
|
+
this.name = block.info.attrs.name ?? block.info.attrs.id ?? block.info.args[0] ?? "default";
|
|
74
|
+
this.className = config.classNames.definition;
|
|
75
|
+
this.key = `${block.info.raw}\n${block.source}`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
eq(other) {
|
|
79
|
+
return other.key === this.key && other.name === this.name && other.className === this.className;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
toDOM(view) {
|
|
83
|
+
const element = document.createElement("button");
|
|
84
|
+
element.type = "button";
|
|
85
|
+
element.className = this.className;
|
|
86
|
+
element.title = "Click to edit this GraphSX library";
|
|
87
|
+
element.addEventListener("mousedown", (event) => {
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
view.dispatch({
|
|
90
|
+
selection: { anchor: this.from },
|
|
91
|
+
scrollIntoView: true
|
|
92
|
+
});
|
|
93
|
+
view.focus();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const label = document.createElement("span");
|
|
97
|
+
label.textContent = "GraphSX library";
|
|
98
|
+
const name = document.createElement("code");
|
|
99
|
+
name.textContent = this.name;
|
|
100
|
+
element.append(label, name);
|
|
101
|
+
return element;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
ignoreEvent() {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
class GraphSXPreviewWidget extends WidgetType {
|
|
110
|
+
constructor(block, libraries, config) {
|
|
111
|
+
super();
|
|
112
|
+
this.from = block.from;
|
|
113
|
+
this.source = block.source;
|
|
114
|
+
this.use = block.info.attrs.use ?? "";
|
|
115
|
+
this.libraryMap = new Map(libraries);
|
|
116
|
+
this.libraryKey = [...libraries.entries()].map(([name, library]) => `${name}:${library.source}`).join("\n---\n");
|
|
117
|
+
this.config = config;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
eq(other) {
|
|
121
|
+
return other.source === this.source
|
|
122
|
+
&& other.use === this.use
|
|
123
|
+
&& other.libraryKey === this.libraryKey
|
|
124
|
+
&& other.config === this.config;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
toDOM(view) {
|
|
128
|
+
const element = document.createElement("div");
|
|
129
|
+
element.className = this.config.classNames.graph;
|
|
130
|
+
element.title = "Click to edit this GraphSX block";
|
|
131
|
+
element.addEventListener("mousedown", (event) => {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
view.dispatch({
|
|
134
|
+
selection: { anchor: this.from },
|
|
135
|
+
scrollIntoView: true
|
|
136
|
+
});
|
|
137
|
+
view.focus();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const graph = parseGraphWithLibraries(this.source, this.libraryMap, this.use);
|
|
142
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
143
|
+
const size = renderGraphSXDocument(svg, graph, {
|
|
144
|
+
...this.config.renderOptions,
|
|
145
|
+
katex: this.config.katex
|
|
146
|
+
});
|
|
147
|
+
svg.setAttribute("width", size.width);
|
|
148
|
+
svg.setAttribute("height", size.height);
|
|
149
|
+
element.append(svg);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
element.className = this.config.classNames.error;
|
|
152
|
+
element.textContent = error.message;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return element;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
ignoreEvent() {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function findGraphSXFences(source) {
|
|
164
|
+
const blocks = [];
|
|
165
|
+
const lines = source.split(/(?<=\n)/);
|
|
166
|
+
let offset = 0;
|
|
167
|
+
let index = 0;
|
|
168
|
+
|
|
169
|
+
while (index < lines.length) {
|
|
170
|
+
const line = lines[index];
|
|
171
|
+
const match = line.match(/^```([^\r\n`]*)\r?\n?$/);
|
|
172
|
+
if (!match) {
|
|
173
|
+
offset += line.length;
|
|
174
|
+
index += 1;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const info = parseFenceInfo(match[1]);
|
|
179
|
+
const start = offset;
|
|
180
|
+
const contentStart = offset + line.length;
|
|
181
|
+
offset += line.length;
|
|
182
|
+
index += 1;
|
|
183
|
+
|
|
184
|
+
let contentEnd = offset;
|
|
185
|
+
while (index < lines.length && !/^```\s*(?:\r?\n)?$/.test(lines[index])) {
|
|
186
|
+
contentEnd += lines[index].length;
|
|
187
|
+
offset += lines[index].length;
|
|
188
|
+
index += 1;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (index >= lines.length) break;
|
|
192
|
+
|
|
193
|
+
const closingLine = lines[index];
|
|
194
|
+
const end = offset + closingLine.length;
|
|
195
|
+
const sourceText = source.slice(contentStart, contentEnd);
|
|
196
|
+
blocks.push({
|
|
197
|
+
from: start,
|
|
198
|
+
to: end,
|
|
199
|
+
source: sourceText.replace(/\r?\n$/, ""),
|
|
200
|
+
info: { ...info, raw: match[1].trim() }
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
offset = end;
|
|
204
|
+
index += 1;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return blocks.filter((block) => block.info.name === GRAPHSX_FENCE || block.info.name === GRAPHSX_DEFS_FENCE);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function collectFenceLibraries(blocks) {
|
|
211
|
+
const libraries = new Map();
|
|
212
|
+
|
|
213
|
+
for (const block of blocks) {
|
|
214
|
+
if (block.info.name !== GRAPHSX_DEFS_FENCE) continue;
|
|
215
|
+
const name = block.info.attrs.name ?? block.info.attrs.id ?? block.info.args[0] ?? "default";
|
|
216
|
+
libraries.set(name, { name, source: block.source });
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return libraries;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function selectionTouchesBlock(selection, block) {
|
|
223
|
+
if (!selection) return false;
|
|
224
|
+
return selection.ranges.some((range) => range.from <= block.to && range.to >= block.from);
|
|
225
|
+
}
|
package/src/document.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { buildGraphModel, parseGraph, parseMarkup } from "./parser.js";
|
|
2
|
+
import { buildPlotModel } from "./plot.js";
|
|
3
|
+
import { renderGraph, graphSummary } from "./renderer.js";
|
|
4
|
+
import { renderPlot, plotSummary } from "./plot-renderer.js";
|
|
5
|
+
import { GraphDslError } from "./errors.js";
|
|
6
|
+
|
|
7
|
+
export function parseGraphSXDocument(source, options = {}) {
|
|
8
|
+
const roots = parseMarkup(source).filter((node) => node.type === "element");
|
|
9
|
+
if (roots.length !== 1) {
|
|
10
|
+
throw new GraphDslError(`Expected exactly one top-level element, found ${roots.length}`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const root = roots[0];
|
|
14
|
+
if (root.name === "Graph") {
|
|
15
|
+
return options.libraries && options.use
|
|
16
|
+
? buildGraphWithLibraries(root, options.libraries, options.use)
|
|
17
|
+
: parseGraph(source);
|
|
18
|
+
}
|
|
19
|
+
if (root.name === "Plot") {
|
|
20
|
+
if (options.use) {
|
|
21
|
+
throw new GraphDslError(`Libraries are currently only supported for <Graph> documents`);
|
|
22
|
+
}
|
|
23
|
+
return buildPlotModel(root);
|
|
24
|
+
}
|
|
25
|
+
throw new GraphDslError(`Top-level element must be <Graph> or <Plot>`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function renderGraphSXDocument(svg, documentModel, options = {}) {
|
|
29
|
+
if (documentModel.type === "graph") {
|
|
30
|
+
return renderGraph(svg, documentModel, options);
|
|
31
|
+
}
|
|
32
|
+
if (documentModel.type === "plot") {
|
|
33
|
+
return renderPlot(svg, documentModel, options);
|
|
34
|
+
}
|
|
35
|
+
throw new GraphDslError(`Unknown document model type "${documentModel.type}"`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function graphSXDocumentSummary(documentModel) {
|
|
39
|
+
if (documentModel.type === "graph") return graphSummary(documentModel);
|
|
40
|
+
if (documentModel.type === "plot") return plotSummary(documentModel);
|
|
41
|
+
throw new GraphDslError(`Unknown document model type "${documentModel.type}"`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function buildGraphWithLibraries(graph, libraries, use) {
|
|
45
|
+
const defs = resolveUsedLibraries(libraries, use);
|
|
46
|
+
if (defs.length === 0) {
|
|
47
|
+
return buildGraphModel(graph);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return buildGraphModel({
|
|
51
|
+
...graph,
|
|
52
|
+
children: [
|
|
53
|
+
...defs.flatMap((item) => parseMarkup(item.source).filter((node) => node.type === "element")),
|
|
54
|
+
...graph.children
|
|
55
|
+
]
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resolveUsedLibraries(libraries, use) {
|
|
60
|
+
return splitUseList(use).map((name) => {
|
|
61
|
+
const library = libraries instanceof Map ? libraries.get(name) : libraries?.[name];
|
|
62
|
+
if (!library) {
|
|
63
|
+
throw new Error(`Unknown GraphSX library "${name}"`);
|
|
64
|
+
}
|
|
65
|
+
return typeof library === "string" ? { name, source: library } : library;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function splitUseList(use) {
|
|
70
|
+
return String(use).split(/[\s,]+/).map((name) => name.trim()).filter(Boolean);
|
|
71
|
+
}
|
package/src/errors.js
ADDED
package/src/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export {
|
|
2
|
+
parseGraph,
|
|
3
|
+
parseGraphs,
|
|
4
|
+
parseMarkup,
|
|
5
|
+
buildGraphModel,
|
|
6
|
+
GraphDslError
|
|
7
|
+
} from "./parser.js";
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
parsePlot,
|
|
11
|
+
parsePlots,
|
|
12
|
+
buildPlotModel
|
|
13
|
+
} from "./plot.js";
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
parseGraphSXDocument,
|
|
17
|
+
renderGraphSXDocument,
|
|
18
|
+
graphSXDocumentSummary
|
|
19
|
+
} from "./document.js";
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
renderGraph,
|
|
23
|
+
graphSummary,
|
|
24
|
+
flattenNodes,
|
|
25
|
+
flattenEdges,
|
|
26
|
+
flattenPaths,
|
|
27
|
+
edgePathData
|
|
28
|
+
} from "./renderer.js";
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
renderPlot,
|
|
32
|
+
plotSummary
|
|
33
|
+
} from "./plot-renderer.js";
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
GRAPHSX_FENCE,
|
|
37
|
+
GRAPHSX_DEFS_FENCE,
|
|
38
|
+
graphsxMarkdownIt,
|
|
39
|
+
parseFenceInfo,
|
|
40
|
+
parseGraphWithLibraries,
|
|
41
|
+
renderGraphSXBlocks
|
|
42
|
+
} from "./markdown.js";
|