My personal website, in gleam+lustre!
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Split out stuff


Signed-off-by: MLC Bloeiman <mar@strawmelonjuice.com>

+1277 -1052
+17
assets/svg/feed.svg
··· 1 + <svg 2 + class="size-[1.2em] p-0 m-1" 3 + version="1.1" 4 + viewBox="0 0 10 10" 5 + xmlns="http://www.w3.org/2000/svg" 6 + > 7 + <g fill="none" fill-rule="evenodd"> 8 + <g fill="currentColor" id="a" transform="translate(-65 -3644)"> 9 + <g id="b" transform="translate(56 160)"> 10 + <path 11 + d="m9.01 3492v1c0 .553.45 1 1 1h1c0-1.11-.899-2-2.01-2m-.0141-4.01v2c2.22 0 4.02 2.05 4.02 4.05h2.01c0-3.01-2.7-6.06-6.03-6.06m9.99 4.91c.0663.598-.402 1.15-1 1.15h-.942c0-4.01-4.03-8.06-8.05-8.06v-.94c0-.601.536-1.06 1.13-.991 4.65.518 8.34 4.21 8.86 8.85" 12 + id="c" 13 + ></path> 14 + </g> 15 + </g> 16 + </g> 17 + </svg>
+207 -122
assets/svg/icon_loc.svg
··· 1 1 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 2 <svg 3 - id="a" 4 - width="800px" 5 - height="800px" 6 - version="1.1" 7 - viewBox="0 0 512 512" 8 - sodipodi:docname="icon_loc.svg" 9 - inkscape:version="1.4.3 (0d15f75042, 2025-12-25)" 10 - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 11 - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 12 - xmlns="http://www.w3.org/2000/svg" 13 - xmlns:svg="http://www.w3.org/2000/svg"> 14 - <defs 15 - id="defs1" /> 16 - <sodipodi:namedview 17 - id="namedview1" 18 - pagecolor="#ffffff" 19 - bordercolor="#000000" 20 - borderopacity="0.25" 21 - inkscape:showpageshadow="2" 22 - inkscape:pageopacity="0.0" 23 - inkscape:pagecheckerboard="0" 24 - inkscape:deskcolor="#d1d1d1" 25 - inkscape:zoom="0.7731284" 26 - inkscape:cx="265.8032" 27 - inkscape:cy="321.42138" 28 - inkscape:window-width="1920" 29 - inkscape:window-height="1166" 30 - inkscape:window-x="0" 31 - inkscape:window-y="0" 32 - inkscape:window-maximized="1" 33 - inkscape:current-layer="a" /> 34 - <style 35 - type="text/css" 36 - id="style1">.st0{fill:#000000;}</style> 37 - <path 38 - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.506964px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" 39 - d="M 256.78398,462.36571 388.39196,228.2565" 40 - id="path1" 41 - inkscape:connector-type="polyline" 42 - inkscape:connector-curvature="0" /> 43 - <path 44 - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.506964px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" 45 - d="M 256.85976,461.70622 125.25178,227.59701" 46 - id="path1-5" 47 - inkscape:connector-type="polyline" 48 - inkscape:connector-curvature="0" /> 49 - <ellipse 50 - style="fill:none;stroke:#000000;stroke-width:0.6822" 51 - id="path2" 52 - ry="139.86961" 53 - rx="158.95628" 54 - cy="148.28415" 55 - cx="256.77777" /> 56 - <path 57 - style="fill:none;stroke:#000000;stroke-width:0.569393" 58 - id="path3" 59 - sodipodi:type="arc" 60 - sodipodi:cx="258.79782" 61 - sodipodi:cy="148.28879" 62 - sodipodi:rx="120.62109" 63 - sodipodi:ry="107.47599" 64 - sodipodi:start="0" 65 - sodipodi:end="6.275449" 66 - sodipodi:arc-type="arc" 67 - d="M 379.41891,148.28879 A 120.62109,107.47599 0 0 1 259.03111,255.76458 120.62109,107.47599 0 0 1 138.17763,148.70452 120.62109,107.47599 0 0 1 258.09795,40.814607 120.62109,107.47599 0 0 1 379.41531,147.45733" 68 - sodipodi:open="true" /> 69 - <path 70 - style="fill:none;stroke:#000000;stroke-width:0.64" 71 - d="m 378.95354,146.28945 c 0,0.40551 -0.40551,1.21654 0,1.21654 0.40551,0 0,-1.62205 0,-1.21654 0,1.62206 0,3.24412 0,4.86617" 72 - id="path4" /> 73 - <path 74 - style="fill:#000000;stroke:#000000;stroke-width:0.699163" 75 - d="m 301.68899,542.48755 c -54.79692,-97.47887 -99.73543,-177.53487 -99.86335,-177.90222 -0.12792,-0.36736 5.06337,4.62034 11.53619,11.08376 13.6409,13.62109 22.87055,21.20866 37.9874,31.22891 12.76926,8.46413 24.51825,14.95858 37.26355,20.59804 75.32833,33.33079 163.91802,31.23654 236.84628,-5.59903 26.70733,-13.48969 52.7522,-33.16537 70.65564,-53.37705 3.57801,-4.03931 6.61501,-7.23467 6.74888,-7.1008 0.28386,0.28386 -199.62804,356.21154 -200.77377,357.46216 -0.57558,0.62829 -25.92863,-43.91437 -100.40082,-176.39377 z" 76 - id="path5" 77 - transform="scale(0.64)" /> 78 - <path 79 - style="fill:#000000;stroke:#000000;stroke-width:0.322679;stroke-dasharray:none" 80 - d="m 247.6534,246.84562 c -22.5816,-1.88095 -43.20282,-8.62104 -61.2394,-20.01623 -8.6783,-5.4828 -19.06897,-14.42897 -25.08132,-21.59456 -6.26926,-7.47178 -12.73679,-18.20103 -15.96491,-26.48485 -8.49589,-21.8017 -7.48737,-45.7335 2.83368,-67.24147 7.8476,-16.353605 21.57487,-31.233804 38.88552,-42.151475 15.91816,-10.039439 34.83694,-16.535783 55.51922,-19.064234 3.72633,-0.455548 7.06627,-0.576335 15.98283,-0.578007 11.80668,-0.0023 14.36554,0.175411 23.21713,1.611639 24.83887,4.030269 47.71699,14.771209 64.88366,30.461923 16.62416,15.194859 26.64396,33.129444 30.18326,54.025464 0.83665,4.93946 1.02982,16.49045 0.36587,21.87616 -1.7955,14.56417 -6.86169,27.73478 -15.31924,39.82551 -4.49972,6.43271 -8.0578,10.55082 -13.81704,15.99186 -19.18393,18.12399 -44.55678,29.44654 -73.69908,32.88797 -4.96465,0.58628 -21.72962,0.86848 -26.75018,0.4503 z m 23.24857,-22.39739 c 12.09071,-1.19889 22.56443,-4.06694 33.61658,-9.20531 9.47135,-4.40344 16.50869,-9.16668 23.89935,-16.17635 11.59272,-10.99507 18.98609,-24.09603 21.70466,-38.46033 7.88691,-41.67252 -25.24144,-80.684089 -74.62993,-87.883386 -5.88675,-0.858103 -18.66756,-1.181391 -24.88464,-0.629453 -18.1804,1.614015 -35.40379,7.82227 -49.29044,17.766983 -24.85758,17.801386 -36.43563,45.029656 -30.68612,72.165026 4.73258,22.33591 21.29376,41.86246 45.10393,53.17998 4.88483,2.32189 6.41348,2.92621 11.89747,4.70357 7.01802,2.27453 17.32352,4.31907 24.22657,4.80638 4.40964,0.3113 14.65941,0.16753 19.04257,-0.26711 z" 81 - id="path6" /> 82 - <path 83 - style="fill:#000000;stroke:#000000;stroke-width:0.4416;stroke-dasharray:none" 84 - d="m 123.50022,221.49496 c 53.69575,97.99474 211.20327,97.99474 211.20327,97.99474 l 71.14687,-121.2629 -155.27021,77.85883 z" 85 - id="path14" /> 86 - <path 87 - style="fill:#000000;stroke:#000000;stroke-width:1.0123;stroke-dasharray:none" 88 - d="m 291.95229,387.32083 c -54.86943,-23.63506 -100.05886,-42.69215 -100.42097,-42.34909 -0.36211,0.34307 -2.88682,-2.86345 -5.61048,-7.1256 -13.54331,-21.19334 -24.70637,-49.64532 -28.87447,-73.5941 -2.89555,-16.63702 -2.92345,-48.1115 -0.0572,-64.54764 4.16836,-23.90316 15.60768,-53.56806 28.30052,-73.39005 C 236.11231,46.946275 338.16067,2.9322972 438.66198,17.033573 534.0034,30.410869 610.95066,89.945605 638.21362,171.42834 c 7.79805,23.30658 9.9311,38.78392 9.12923,66.24136 -0.73413,25.13787 -2.43856,34.76541 -10.21912,57.72329 l -4.64653,13.71041 -51.05268,25.53444 c -28.07898,14.04394 -51.36354,25.53445 -51.74347,25.53445 -0.37993,0 5.25357,-5.73038 12.5189,-12.73416 34.91095,-33.65425 51.27272,-70.76127 51.22147,-116.16566 C 593.32329,144.32696 521.9235,73.553938 424.36647,63.701533 377.44089,58.962462 328.69781,71.016397 289.4185,97.07353 c -15.35699,10.18753 -38.74943,33.86392 -48.86512,49.45827 -25.54053,39.37331 -32.40713,87.32534 -18.718,130.7148 27.62814,87.57098 126.88025,139.52317 227.03114,118.83644 6.2564,-1.29229 11.6045,-2.12043 11.88464,-1.84027 0.28014,0.28014 -15.13842,8.5062 -34.26346,18.28012 l -34.77282,17.77077 z" 89 - id="path15" 90 - transform="scale(0.64)" /> 91 - <path 92 - style="fill:#000000;stroke:#000000;stroke-width:1.0123;stroke-dasharray:none" 93 - d="" 94 - id="path16" 95 - transform="scale(0.64)" /> 96 - <path 97 - style="fill:#000000;stroke:#000000;stroke-width:1.0123;stroke-dasharray:none" 98 - d="m 372.70999,395.99113 c -59.13703,-9.19022 -113.22885,-46.00346 -137.45968,-93.55085 -5.55873,-10.90771 -4.51916,-12.45415 1.36422,-2.02938 15.0432,26.6551 42.86098,51.03402 75.79933,66.42895 29.83775,13.94575 49.16227,18.28758 85.90295,19.30066 23.36584,0.64429 29.52527,0.31954 44.27945,-2.33462 55.26069,-9.94094 102.22734,-39.66035 127.91731,-80.94311 9.7563,-15.67796 10.30122,-12.80258 0.74052,3.90739 -17.91672,31.31437 -43.89089,54.75623 -79.57164,71.81389 -36.19812,17.305 -79.17102,23.59244 -118.97246,17.40707 z" 99 - id="path17" 100 - transform="scale(0.64)" /> 101 - <path 102 - style="fill:#000000;stroke:#000000;stroke-width:1.0123;stroke-dasharray:none" 103 - d="m 387.21919,396.60264 c -34.41291,-2.28548 -70.5289,-15.7454 -100.87478,-37.59461 -11.52822,-8.30038 -37.67148,-34.14763 -37.67148,-37.24494 0,-0.89141 5.91842,4.08464 13.15205,11.05787 15.05819,14.51614 32.32712,26.29477 51.80873,35.3372 29.65951,13.76654 44.64195,16.88323 86.1502,17.92124 28.16603,0.70435 33.12323,0.46223 46.3084,-2.26185 41.71998,-8.61939 73.91347,-25.12147 101.50161,-52.02877 7.46386,-7.27966 13.57065,-12.55467 13.57065,-11.72225 0,2.87708 -18.5896,23.26361 -28.71571,31.49145 -40.90127,33.23381 -90.6647,48.66852 -145.22967,45.04466 z" 104 - id="path18" 105 - transform="scale(0.64)" /> 106 - <path 107 - style="fill:#000000;stroke:#000000;stroke-width:0.258216;stroke-dasharray:none" 108 - d="m 455.71981,398.14098 c 0.12289,-0.12289 1.45607,-0.9228 2.96263,-1.77758 3.19564,-1.81312 3.49291,-2.59108 1.09437,-2.86393 l -1.64482,-0.18712 3.32884,-0.90188 c 1.83086,-0.49603 6.24516,-1.88535 9.80956,-3.08737 3.5644,-1.20202 6.59564,-2.17639 6.73608,-2.16526 0.33815,0.0268 -21.72409,11.16024 -22.16706,11.18635 -0.18867,0.0111 -0.24249,-0.0803 -0.1196,-0.20321 z" 109 - id="path19" 110 - transform="scale(0.64)" /> 111 - <path 112 - style="fill:#000000;stroke:#000000;stroke-width:0.258216;stroke-dasharray:none" 113 - d="m 579.77587,285.06725 c -0.0789,-0.36019 0.10836,-1.2022 0.4161,-1.87113 0.43776,-0.95159 0.78872,-1.21624 1.61288,-1.21624 0.8666,0 1.05337,0.16157 1.05337,0.91121 0,1.82709 -0.65054,2.83106 -1.83443,2.83106 -0.74779,0 -1.15082,-0.21151 -1.24792,-0.6549 z" 114 - id="path20" 115 - transform="scale(0.64)" /> 116 - <path 117 - style="fill:#000000;stroke:#000000;stroke-width:0.258216;stroke-dasharray:none" 118 - d="m 522.23348,364.331 c 0,-0.81903 1.32078,-1.89236 2.32863,-1.89236 1.18698,0 0.75174,1.31701 -0.6573,1.98894 -1.65149,0.78754 -1.67133,0.78639 -1.67133,-0.0966 z" 119 - id="path21" 120 - transform="scale(0.64)" /> 121 - <path 122 - style="fill:#000000;stroke:#000000;stroke-width:0.4416;stroke-dasharray:none" 123 - d="m 146.79321,181.29589 c 168.74946,93.47089 170.63142,31.99339 170.63142,31.99339 l 70.88733,-84.06107 19.44696,68.37804 -217.05321,131.11017 -85.94303,-144.91125 62.10481,-138.638028 117.93643,-17.565 84.06107,39.52125 25.09286,82.806428 -28.85679,62.73214 -42.03053,51.44036 L 289.19517,230.22696 353.18196,193.215 367.61035,127.97357 351.92732,97.862138 317.42463,81.551782 281.03999,68.378035 h -46.42178 l -45.79447,20.701607 -23.83821,27.602148 -7.52785,32.62071 z" 124 - id="path22" /> 3 + id="a" 4 + width="800px" 5 + height="800px" 6 + version="1.1" 7 + viewBox="0 0 512 512" 8 + sodipodi:docname="icon_loc.svg" 9 + inkscape:version="1.4.3 (0d15f75042, 2025-12-25)" 10 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 11 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 12 + xmlns="http://www.w3.org/2000/svg" 13 + xmlns:svg="http://www.w3.org/2000/svg" 14 + > 15 + <defs id="defs1" /> 16 + <sodipodi:namedview 17 + id="namedview1" 18 + pagecolor="#ffffff" 19 + bordercolor="#000000" 20 + borderopacity="0.25" 21 + inkscape:showpageshadow="2" 22 + inkscape:pageopacity="0.0" 23 + inkscape:pagecheckerboard="0" 24 + inkscape:deskcolor="#d1d1d1" 25 + inkscape:zoom="0.7731284" 26 + inkscape:cx="265.8032" 27 + inkscape:cy="321.42138" 28 + inkscape:window-width="1920" 29 + inkscape:window-height="1166" 30 + inkscape:window-x="0" 31 + inkscape:window-y="0" 32 + inkscape:window-maximized="1" 33 + inkscape:current-layer="a" 34 + /> 35 + <style type="text/css" id="style1"> 36 + .st0 { 37 + fill: #000000; 38 + } 39 + </style> 40 + <path 41 + style=" 42 + fill: none; 43 + fill-rule: evenodd; 44 + stroke: #000000; 45 + stroke-width: 0.506964px; 46 + stroke-linecap: butt; 47 + stroke-linejoin: miter; 48 + stroke-opacity: 1; 49 + " 50 + d="M 256.78398,462.36571 388.39196,228.2565" 51 + id="path1" 52 + inkscape:connector-type="polyline" 53 + inkscape:connector-curvature="0" 54 + /> 55 + <path 56 + style=" 57 + fill: none; 58 + fill-rule: evenodd; 59 + stroke: #000000; 60 + stroke-width: 0.506964px; 61 + stroke-linecap: butt; 62 + stroke-linejoin: miter; 63 + stroke-opacity: 1; 64 + " 65 + d="M 256.85976,461.70622 125.25178,227.59701" 66 + id="path1-5" 67 + inkscape:connector-type="polyline" 68 + inkscape:connector-curvature="0" 69 + /> 70 + <ellipse 71 + style="fill: none; stroke: #000000; stroke-width: 0.6822" 72 + id="path2" 73 + ry="139.86961" 74 + rx="158.95628" 75 + cy="148.28415" 76 + cx="256.77777" 77 + /> 78 + <path 79 + style="fill: none; stroke: #000000; stroke-width: 0.569393" 80 + id="path3" 81 + sodipodi:type="arc" 82 + sodipodi:cx="258.79782" 83 + sodipodi:cy="148.28879" 84 + sodipodi:rx="120.62109" 85 + sodipodi:ry="107.47599" 86 + sodipodi:start="0" 87 + sodipodi:end="6.275449" 88 + sodipodi:arc-type="arc" 89 + d="M 379.41891,148.28879 A 120.62109,107.47599 0 0 1 259.03111,255.76458 120.62109,107.47599 0 0 1 138.17763,148.70452 120.62109,107.47599 0 0 1 258.09795,40.814607 120.62109,107.47599 0 0 1 379.41531,147.45733" 90 + sodipodi:open="true" 91 + /> 92 + <path 93 + style="fill: none; stroke: #000000; stroke-width: 0.64" 94 + d="m 378.95354,146.28945 c 0,0.40551 -0.40551,1.21654 0,1.21654 0.40551,0 0,-1.62205 0,-1.21654 0,1.62206 0,3.24412 0,4.86617" 95 + id="path4" 96 + /> 97 + <path 98 + style="fill: #000000; stroke: #000000; stroke-width: 0.699163" 99 + d="m 301.68899,542.48755 c -54.79692,-97.47887 -99.73543,-177.53487 -99.86335,-177.90222 -0.12792,-0.36736 5.06337,4.62034 11.53619,11.08376 13.6409,13.62109 22.87055,21.20866 37.9874,31.22891 12.76926,8.46413 24.51825,14.95858 37.26355,20.59804 75.32833,33.33079 163.91802,31.23654 236.84628,-5.59903 26.70733,-13.48969 52.7522,-33.16537 70.65564,-53.37705 3.57801,-4.03931 6.61501,-7.23467 6.74888,-7.1008 0.28386,0.28386 -199.62804,356.21154 -200.77377,357.46216 -0.57558,0.62829 -25.92863,-43.91437 -100.40082,-176.39377 z" 100 + id="path5" 101 + transform="scale(0.64)" 102 + /> 103 + <path 104 + style=" 105 + fill: #000000; 106 + stroke: #000000; 107 + stroke-width: 0.322679; 108 + stroke-dasharray: none; 109 + " 110 + d="m 247.6534,246.84562 c -22.5816,-1.88095 -43.20282,-8.62104 -61.2394,-20.01623 -8.6783,-5.4828 -19.06897,-14.42897 -25.08132,-21.59456 -6.26926,-7.47178 -12.73679,-18.20103 -15.96491,-26.48485 -8.49589,-21.8017 -7.48737,-45.7335 2.83368,-67.24147 7.8476,-16.353605 21.57487,-31.233804 38.88552,-42.151475 15.91816,-10.039439 34.83694,-16.535783 55.51922,-19.064234 3.72633,-0.455548 7.06627,-0.576335 15.98283,-0.578007 11.80668,-0.0023 14.36554,0.175411 23.21713,1.611639 24.83887,4.030269 47.71699,14.771209 64.88366,30.461923 16.62416,15.194859 26.64396,33.129444 30.18326,54.025464 0.83665,4.93946 1.02982,16.49045 0.36587,21.87616 -1.7955,14.56417 -6.86169,27.73478 -15.31924,39.82551 -4.49972,6.43271 -8.0578,10.55082 -13.81704,15.99186 -19.18393,18.12399 -44.55678,29.44654 -73.69908,32.88797 -4.96465,0.58628 -21.72962,0.86848 -26.75018,0.4503 z m 23.24857,-22.39739 c 12.09071,-1.19889 22.56443,-4.06694 33.61658,-9.20531 9.47135,-4.40344 16.50869,-9.16668 23.89935,-16.17635 11.59272,-10.99507 18.98609,-24.09603 21.70466,-38.46033 7.88691,-41.67252 -25.24144,-80.684089 -74.62993,-87.883386 -5.88675,-0.858103 -18.66756,-1.181391 -24.88464,-0.629453 -18.1804,1.614015 -35.40379,7.82227 -49.29044,17.766983 -24.85758,17.801386 -36.43563,45.029656 -30.68612,72.165026 4.73258,22.33591 21.29376,41.86246 45.10393,53.17998 4.88483,2.32189 6.41348,2.92621 11.89747,4.70357 7.01802,2.27453 17.32352,4.31907 24.22657,4.80638 4.40964,0.3113 14.65941,0.16753 19.04257,-0.26711 z" 111 + id="path6" 112 + /> 113 + <path 114 + style=" 115 + fill: #000000; 116 + stroke: #000000; 117 + stroke-width: 0.4416; 118 + stroke-dasharray: none; 119 + " 120 + d="m 123.50022,221.49496 c 53.69575,97.99474 211.20327,97.99474 211.20327,97.99474 l 71.14687,-121.2629 -155.27021,77.85883 z" 121 + id="path14" 122 + /> 123 + <path 124 + style=" 125 + fill: #000000; 126 + stroke: #000000; 127 + stroke-width: 1.0123; 128 + stroke-dasharray: none; 129 + " 130 + d="m 291.95229,387.32083 c -54.86943,-23.63506 -100.05886,-42.69215 -100.42097,-42.34909 -0.36211,0.34307 -2.88682,-2.86345 -5.61048,-7.1256 -13.54331,-21.19334 -24.70637,-49.64532 -28.87447,-73.5941 -2.89555,-16.63702 -2.92345,-48.1115 -0.0572,-64.54764 4.16836,-23.90316 15.60768,-53.56806 28.30052,-73.39005 C 236.11231,46.946275 338.16067,2.9322972 438.66198,17.033573 534.0034,30.410869 610.95066,89.945605 638.21362,171.42834 c 7.79805,23.30658 9.9311,38.78392 9.12923,66.24136 -0.73413,25.13787 -2.43856,34.76541 -10.21912,57.72329 l -4.64653,13.71041 -51.05268,25.53444 c -28.07898,14.04394 -51.36354,25.53445 -51.74347,25.53445 -0.37993,0 5.25357,-5.73038 12.5189,-12.73416 34.91095,-33.65425 51.27272,-70.76127 51.22147,-116.16566 C 593.32329,144.32696 521.9235,73.553938 424.36647,63.701533 377.44089,58.962462 328.69781,71.016397 289.4185,97.07353 c -15.35699,10.18753 -38.74943,33.86392 -48.86512,49.45827 -25.54053,39.37331 -32.40713,87.32534 -18.718,130.7148 27.62814,87.57098 126.88025,139.52317 227.03114,118.83644 6.2564,-1.29229 11.6045,-2.12043 11.88464,-1.84027 0.28014,0.28014 -15.13842,8.5062 -34.26346,18.28012 l -34.77282,17.77077 z" 131 + id="path15" 132 + transform="scale(0.64)" 133 + /> 134 + <path 135 + style=" 136 + fill: #000000; 137 + stroke: #000000; 138 + stroke-width: 1.0123; 139 + stroke-dasharray: none; 140 + " 141 + d="" 142 + id="path16" 143 + transform="scale(0.64)" 144 + /> 145 + <path 146 + style=" 147 + fill: #000000; 148 + stroke: #000000; 149 + stroke-width: 1.0123; 150 + stroke-dasharray: none; 151 + " 152 + d="m 372.70999,395.99113 c -59.13703,-9.19022 -113.22885,-46.00346 -137.45968,-93.55085 -5.55873,-10.90771 -4.51916,-12.45415 1.36422,-2.02938 15.0432,26.6551 42.86098,51.03402 75.79933,66.42895 29.83775,13.94575 49.16227,18.28758 85.90295,19.30066 23.36584,0.64429 29.52527,0.31954 44.27945,-2.33462 55.26069,-9.94094 102.22734,-39.66035 127.91731,-80.94311 9.7563,-15.67796 10.30122,-12.80258 0.74052,3.90739 -17.91672,31.31437 -43.89089,54.75623 -79.57164,71.81389 -36.19812,17.305 -79.17102,23.59244 -118.97246,17.40707 z" 153 + id="path17" 154 + transform="scale(0.64)" 155 + /> 156 + <path 157 + style=" 158 + fill: #000000; 159 + stroke: #000000; 160 + stroke-width: 1.0123; 161 + stroke-dasharray: none; 162 + " 163 + d="m 387.21919,396.60264 c -34.41291,-2.28548 -70.5289,-15.7454 -100.87478,-37.59461 -11.52822,-8.30038 -37.67148,-34.14763 -37.67148,-37.24494 0,-0.89141 5.91842,4.08464 13.15205,11.05787 15.05819,14.51614 32.32712,26.29477 51.80873,35.3372 29.65951,13.76654 44.64195,16.88323 86.1502,17.92124 28.16603,0.70435 33.12323,0.46223 46.3084,-2.26185 41.71998,-8.61939 73.91347,-25.12147 101.50161,-52.02877 7.46386,-7.27966 13.57065,-12.55467 13.57065,-11.72225 0,2.87708 -18.5896,23.26361 -28.71571,31.49145 -40.90127,33.23381 -90.6647,48.66852 -145.22967,45.04466 z" 164 + id="path18" 165 + transform="scale(0.64)" 166 + /> 167 + <path 168 + style=" 169 + fill: #000000; 170 + stroke: #000000; 171 + stroke-width: 0.258216; 172 + stroke-dasharray: none; 173 + " 174 + d="m 455.71981,398.14098 c 0.12289,-0.12289 1.45607,-0.9228 2.96263,-1.77758 3.19564,-1.81312 3.49291,-2.59108 1.09437,-2.86393 l -1.64482,-0.18712 3.32884,-0.90188 c 1.83086,-0.49603 6.24516,-1.88535 9.80956,-3.08737 3.5644,-1.20202 6.59564,-2.17639 6.73608,-2.16526 0.33815,0.0268 -21.72409,11.16024 -22.16706,11.18635 -0.18867,0.0111 -0.24249,-0.0803 -0.1196,-0.20321 z" 175 + id="path19" 176 + transform="scale(0.64)" 177 + /> 178 + <path 179 + style=" 180 + fill: #000000; 181 + stroke: #000000; 182 + stroke-width: 0.258216; 183 + stroke-dasharray: none; 184 + " 185 + d="m 579.77587,285.06725 c -0.0789,-0.36019 0.10836,-1.2022 0.4161,-1.87113 0.43776,-0.95159 0.78872,-1.21624 1.61288,-1.21624 0.8666,0 1.05337,0.16157 1.05337,0.91121 0,1.82709 -0.65054,2.83106 -1.83443,2.83106 -0.74779,0 -1.15082,-0.21151 -1.24792,-0.6549 z" 186 + id="path20" 187 + transform="scale(0.64)" 188 + /> 189 + <path 190 + style=" 191 + fill: #000000; 192 + stroke: #000000; 193 + stroke-width: 0.258216; 194 + stroke-dasharray: none; 195 + " 196 + d="m 522.23348,364.331 c 0,-0.81903 1.32078,-1.89236 2.32863,-1.89236 1.18698,0 0.75174,1.31701 -0.6573,1.98894 -1.65149,0.78754 -1.67133,0.78639 -1.67133,-0.0966 z" 197 + id="path21" 198 + transform="scale(0.64)" 199 + /> 200 + <path 201 + style=" 202 + fill: #000000; 203 + stroke: #000000; 204 + stroke-width: 0.4416; 205 + stroke-dasharray: none; 206 + " 207 + d="m 146.79321,181.29589 c 168.74946,93.47089 170.63142,31.99339 170.63142,31.99339 l 70.88733,-84.06107 19.44696,68.37804 -217.05321,131.11017 -85.94303,-144.91125 62.10481,-138.638028 117.93643,-17.565 84.06107,39.52125 25.09286,82.806428 -28.85679,62.73214 -42.03053,51.44036 L 289.19517,230.22696 353.18196,193.215 367.61035,127.97357 351.92732,97.862138 317.42463,81.551782 281.03999,68.378035 h -46.42178 l -45.79447,20.701607 -23.83821,27.602148 -7.52785,32.62071 z" 208 + id="path22" 209 + /> 125 210 </svg>
+18 -1
assets/svg/icon_mail.svg
··· 1 1 <?xml version="1.0" encoding="UTF-8"?> 2 - <svg id="a" width="800px" height="800px" version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><style type="text/css">.st0{fill:#000000;}</style><path class="st0" d="m0 64v384h512v-384h-512zm264 203c-2 1.69-4.95 2.66-8.1 2.66-3.15 0-6.1-.964-8.08-2.64l-200-155h416l-200 155zm-169-72.5 69.5 59-117 115v-208l47.1 34.3zm104 88.3 16.4 13.9c10.8 9.22 25.2 14.3 40.4 14.3 15.2 0 29.6-5.07 40.4-14.3l16.3-13.8 119 117h-352l119-117zm148-29.4 117-93.3v208l-117-115z"/></svg> 2 + <svg 3 + id="a" 4 + width="800px" 5 + height="800px" 6 + version="1.1" 7 + viewBox="0 0 512 512" 8 + xmlns="http://www.w3.org/2000/svg" 9 + > 10 + <style type="text/css"> 11 + .st0 { 12 + fill: #000000; 13 + } 14 + </style> 15 + <path 16 + class="st0" 17 + d="m0 64v384h512v-384h-512zm264 203c-2 1.69-4.95 2.66-8.1 2.66-3.15 0-6.1-.964-8.08-2.64l-200-155h416l-200 155zm-169-72.5 69.5 59-117 115v-208l47.1 34.3zm104 88.3 16.4 13.9c10.8 9.22 25.2 14.3 40.4 14.3 15.2 0 29.6-5.07 40.4-14.3l16.3-13.8 119 117h-352l119-117zm148-29.4 117-93.3v208l-117-115z" 18 + /> 19 + </svg>
+33 -1
assets/svg/icon_phone.svg
··· 1 1 <?xml version="1.0" encoding="UTF-8"?> 2 - <svg id="a" version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><style type="text/css">.st0{fill:#000000;}</style><path class="st0" d="m33 235c-.008-.016-.016-.024-.024-.04l-.016-.017.04.057z"/><path class="st0" d="m64.7 225c.024-.008.056-.017.08-.025l.373-.137-.453.162z"/><path class="st0" d="m501 141c-7.1-9.82-17.2-18.7-29.9-26.5v-.007c-.032-.017-.064-.041-.097-.057-.057-.032-.098-.073-.154-.105l-.008.008c-19.3-12.4-50.2-26.1-87.2-37.2-37.1-11-80.1-19.2-122-19.2-1.62 0-3.27.008-4.92.04-1.63-.025-3.27-.04-4.91-.04-42.4.016-85.3 8.18-122 19.2-37 11.1-67.9 24.8-87.2 37.2v-.008c-.025.016-.049.032-.081.049-.056.04-.122.073-.178.114l.008.007c-12.8 7.88-22.9 16.7-30 26.5-7.14 9.84-11.2 20.9-11.2 32.2-.041 12.6 5.23 24.7 14.2 34.7 6.37 9.01 12.6 18.1 18.8 27.2l.065.088c6.53 9.59 17.3 14.7 28.1 14.7 3.92 0 7.88-.68 11.7-2.01v.016l-.234.089.234-.089.049.865-.032-.865.251-.089c3.19-1.15 6.42-2.1 9.62-3.19l-.582 1.7-27.8 59.2c-10.4 22.2-15.8 46.5-15.8 71v15.6c.008 34.1 27.6 61.7 61.7 61.7h311c34.1-.008 61.7-27.6 61.7-61.7v-15.6c0-24.5-5.4-48.8-15.8-71l-27.8-59.2-.582-1.71c3.2 1.09 6.42 2.04 9.6 3.19 3.92 1.41 7.98 2.09 12 2.09 10.9.016 21.6-5.1 28.1-14.7l.032-.049c6.15-9.15 12.4-18.2 18.8-27.2 8.98-9.99 14.2-22.1 14.2-34.7.017-11.3-4.09-22.4-11.2-32.2zm-50 84c-1.17 0-2.37-.194-3.54-.614-19.2-6.94-38.7-12.8-58.4-17.7-2.21-.542-4.05-1.76-5.33-3.35-1.28-1.59-1.95-3.42-1.95-5.39.049-5.15.073-10.3.073-15.5 0-2.04 0-4.08-.008-6.13v.041c0-7.65-2.86-14.8-7.48-20.3-4.19-5.04-9.9-8.8-16.4-10.9-.251-.122-.429-.186-.599-.259-1.12-.437-1.49-.526-2.24-.752-2.51-.736-7.04-1.91-13.4-3.37-19-4.33-52.7-10.9-82-11-1.16 0-2.32.017-3.48.041-1.16-.024-2.31-.041-3.47-.041-21.5.017-45.2 3.6-64 7.19-9.35 1.8-17.4 3.61-23.2 5.01-2.9.704-5.22 1.31-6.92 1.78-.866.243-1.55.436-2.22.655l-1.23.428c-.178.073-.38.154-.647.275-6.58 2.11-12.3 5.88-16.5 10.9-4.61 5.54-7.46 12.7-7.47 20.3v-.032c-.008 1.8-.008 3.61-.008 5.41 0 5.39.024 10.8.081 16.2-.008 1.96-.68 3.81-1.96 5.41-1.29 1.58-3.13 2.81-5.33 3.35-19.7 4.83-39.2 10.7-58.4 17.6l-.064.025h-.016c-1.18.42-2.37.623-3.53.623-3.23-.017-6.01-1.48-7.57-3.76-6.34-9.42-12.8-18.8-19.4-28.1l-.468-.672-.55-.582c-6.1-6.68-8.35-12.7-8.39-18.8.016-5.28 1.83-11.1 6.53-17.6 4.67-6.5 12.3-13.5 23-20.1l.145-.088.114-.073c16.1-10.5 45.9-23.9 81.1-34.4 35.2-10.5 76.2-18.2 115-18.2 1.57 0 3.15.016 4.72.041h.421c1.54-.032 3.11-.041 4.69-.041 39.1-.016 80.1 7.68 115 18.2 35.2 10.5 65 23.9 81.1 34.4l.146.088.105.065c10.8 6.59 18.4 13.6 23.1 20.1 4.7 6.54 6.51 12.4 6.52 17.6-.04 6.02-2.28 12.1-8.38 18.8l-.55.591-.468.655c-6.58 9.28-13.1 18.6-19.4 28.1l.032-.049c-1.56 2.32-4.37 3.79-7.6 3.8zm-387 152c0-20.9 4.59-41.6 13.5-60.5l28.3-60.5 6.92-20.1c5.64-1.57 11.2-3.24 16.9-4.63 7.56-1.85 14.1-6.11 18.7-11.9 4.57-5.64 7.34-12.9 7.44-20.6h.032l.008-.324v-.323c-.057-5.31-.081-10.6-.081-16 0-1.78 0-3.56.008-5.33v-.032c0-1.42.518-2.97 1.76-4.46 1.22-1.48 3.11-2.78 5.56-3.42l9.29-2.41v-.105c7.3-1.76 18.5-4.23 31.2-6.4 15.9-2.73 34.1-4.97 49.5-4.97 1.08 0 2.14.016 3.18.032l.299.008h.258c1.05-.024 2.13-.04 3.21-.04 18.7-.016 41.5 3.31 59.2 6.74 8.61 1.66 16 3.32 21.4 4.62v.097l9.29 2.42c2.45.639 4.36 1.95 5.59 3.44 1.23 1.5 1.75 3.03 1.75 4.45v.04c.008 2.01.008 4.04.008 6.05 0 5.09-.024 10.2-.073 15.2v.218c-.008 7.88 2.82 15.3 7.47 21 4.66 5.77 11.2 10 18.7 11.9 5.67 1.39 11.3 3.06 16.9 4.63l6.92 20.1 28.3 60.5c8.88 18.9 13.5 39.6 13.5 60.5v15.6c-.008 10.2-4.11 19.4-10.8 26.1-6.71 6.7-15.9 10.8-26.1 10.8h-311c-10.2-.008-19.4-4.11-26.1-10.8-6.7-6.71-10.8-15.9-10.8-26.1v-15.6zm9.46-129v-.025c.073-.024.146-.032.219-.056l-.219.081z"/><rect class="st0" x="178" y="345" width="38.9" height="38.9"/><rect class="st0" x="178" y="292" width="38.9" height="38.9"/><rect class="st0" x="178" y="238" width="38.9" height="38.9"/><rect class="st0" x="237" y="345" width="38.9" height="38.9"/><rect class="st0" x="237" y="292" width="38.9" height="38.9"/><rect class="st0" x="237" y="238" width="38.9" height="38.9"/><rect class="st0" x="295" y="345" width="38.9" height="38.9"/><rect class="st0" x="295" y="292" width="38.9" height="38.9"/><rect class="st0" x="295" y="238" width="38.9" height="38.9"/></svg> 2 + <svg 3 + id="a" 4 + version="1.1" 5 + viewBox="0 0 512 512" 6 + xmlns="http://www.w3.org/2000/svg" 7 + > 8 + <style type="text/css"> 9 + .st0 { 10 + fill: currentColor; 11 + } 12 + </style> 13 + <path 14 + class="st0" 15 + d="m33 235c-.008-.016-.016-.024-.024-.04l-.016-.017.04.057z" 16 + /> 17 + <path 18 + class="st0" 19 + d="m64.7 225c.024-.008.056-.017.08-.025l.373-.137-.453.162z" 20 + /> 21 + <path 22 + class="st0" 23 + d="m501 141c-7.1-9.82-17.2-18.7-29.9-26.5v-.007c-.032-.017-.064-.041-.097-.057-.057-.032-.098-.073-.154-.105l-.008.008c-19.3-12.4-50.2-26.1-87.2-37.2-37.1-11-80.1-19.2-122-19.2-1.62 0-3.27.008-4.92.04-1.63-.025-3.27-.04-4.91-.04-42.4.016-85.3 8.18-122 19.2-37 11.1-67.9 24.8-87.2 37.2v-.008c-.025.016-.049.032-.081.049-.056.04-.122.073-.178.114l.008.007c-12.8 7.88-22.9 16.7-30 26.5-7.14 9.84-11.2 20.9-11.2 32.2-.041 12.6 5.23 24.7 14.2 34.7 6.37 9.01 12.6 18.1 18.8 27.2l.065.088c6.53 9.59 17.3 14.7 28.1 14.7 3.92 0 7.88-.68 11.7-2.01v.016l-.234.089.234-.089.049.865-.032-.865.251-.089c3.19-1.15 6.42-2.1 9.62-3.19l-.582 1.7-27.8 59.2c-10.4 22.2-15.8 46.5-15.8 71v15.6c.008 34.1 27.6 61.7 61.7 61.7h311c34.1-.008 61.7-27.6 61.7-61.7v-15.6c0-24.5-5.4-48.8-15.8-71l-27.8-59.2-.582-1.71c3.2 1.09 6.42 2.04 9.6 3.19 3.92 1.41 7.98 2.09 12 2.09 10.9.016 21.6-5.1 28.1-14.7l.032-.049c6.15-9.15 12.4-18.2 18.8-27.2 8.98-9.99 14.2-22.1 14.2-34.7.017-11.3-4.09-22.4-11.2-32.2zm-50 84c-1.17 0-2.37-.194-3.54-.614-19.2-6.94-38.7-12.8-58.4-17.7-2.21-.542-4.05-1.76-5.33-3.35-1.28-1.59-1.95-3.42-1.95-5.39.049-5.15.073-10.3.073-15.5 0-2.04 0-4.08-.008-6.13v.041c0-7.65-2.86-14.8-7.48-20.3-4.19-5.04-9.9-8.8-16.4-10.9-.251-.122-.429-.186-.599-.259-1.12-.437-1.49-.526-2.24-.752-2.51-.736-7.04-1.91-13.4-3.37-19-4.33-52.7-10.9-82-11-1.16 0-2.32.017-3.48.041-1.16-.024-2.31-.041-3.47-.041-21.5.017-45.2 3.6-64 7.19-9.35 1.8-17.4 3.61-23.2 5.01-2.9.704-5.22 1.31-6.92 1.78-.866.243-1.55.436-2.22.655l-1.23.428c-.178.073-.38.154-.647.275-6.58 2.11-12.3 5.88-16.5 10.9-4.61 5.54-7.46 12.7-7.47 20.3v-.032c-.008 1.8-.008 3.61-.008 5.41 0 5.39.024 10.8.081 16.2-.008 1.96-.68 3.81-1.96 5.41-1.29 1.58-3.13 2.81-5.33 3.35-19.7 4.83-39.2 10.7-58.4 17.6l-.064.025h-.016c-1.18.42-2.37.623-3.53.623-3.23-.017-6.01-1.48-7.57-3.76-6.34-9.42-12.8-18.8-19.4-28.1l-.468-.672-.55-.582c-6.1-6.68-8.35-12.7-8.39-18.8.016-5.28 1.83-11.1 6.53-17.6 4.67-6.5 12.3-13.5 23-20.1l.145-.088.114-.073c16.1-10.5 45.9-23.9 81.1-34.4 35.2-10.5 76.2-18.2 115-18.2 1.57 0 3.15.016 4.72.041h.421c1.54-.032 3.11-.041 4.69-.041 39.1-.016 80.1 7.68 115 18.2 35.2 10.5 65 23.9 81.1 34.4l.146.088.105.065c10.8 6.59 18.4 13.6 23.1 20.1 4.7 6.54 6.51 12.4 6.52 17.6-.04 6.02-2.28 12.1-8.38 18.8l-.55.591-.468.655c-6.58 9.28-13.1 18.6-19.4 28.1l.032-.049c-1.56 2.32-4.37 3.79-7.6 3.8zm-387 152c0-20.9 4.59-41.6 13.5-60.5l28.3-60.5 6.92-20.1c5.64-1.57 11.2-3.24 16.9-4.63 7.56-1.85 14.1-6.11 18.7-11.9 4.57-5.64 7.34-12.9 7.44-20.6h.032l.008-.324v-.323c-.057-5.31-.081-10.6-.081-16 0-1.78 0-3.56.008-5.33v-.032c0-1.42.518-2.97 1.76-4.46 1.22-1.48 3.11-2.78 5.56-3.42l9.29-2.41v-.105c7.3-1.76 18.5-4.23 31.2-6.4 15.9-2.73 34.1-4.97 49.5-4.97 1.08 0 2.14.016 3.18.032l.299.008h.258c1.05-.024 2.13-.04 3.21-.04 18.7-.016 41.5 3.31 59.2 6.74 8.61 1.66 16 3.32 21.4 4.62v.097l9.29 2.42c2.45.639 4.36 1.95 5.59 3.44 1.23 1.5 1.75 3.03 1.75 4.45v.04c.008 2.01.008 4.04.008 6.05 0 5.09-.024 10.2-.073 15.2v.218c-.008 7.88 2.82 15.3 7.47 21 4.66 5.77 11.2 10 18.7 11.9 5.67 1.39 11.3 3.06 16.9 4.63l6.92 20.1 28.3 60.5c8.88 18.9 13.5 39.6 13.5 60.5v15.6c-.008 10.2-4.11 19.4-10.8 26.1-6.71 6.7-15.9 10.8-26.1 10.8h-311c-10.2-.008-19.4-4.11-26.1-10.8-6.7-6.71-10.8-15.9-10.8-26.1v-15.6zm9.46-129v-.025c.073-.024.146-.032.219-.056l-.219.081z" 24 + /> 25 + <rect class="st0" x="178" y="345" width="38.9" height="38.9" /> 26 + <rect class="st0" x="178" y="292" width="38.9" height="38.9" /> 27 + <rect class="st0" x="178" y="238" width="38.9" height="38.9" /> 28 + <rect class="st0" x="237" y="345" width="38.9" height="38.9" /> 29 + <rect class="st0" x="237" y="292" width="38.9" height="38.9" /> 30 + <rect class="st0" x="237" y="238" width="38.9" height="38.9" /> 31 + <rect class="st0" x="295" y="345" width="38.9" height="38.9" /> 32 + <rect class="st0" x="295" y="292" width="38.9" height="38.9" /> 33 + <rect class="st0" x="295" y="238" width="38.9" height="38.9" /> 34 + </svg>
+12 -1
assets/svg/icon_www.svg
··· 1 1 <?xml version="1.0" encoding="UTF-8"?> 2 - <svg id="a" width="800px" height="800px" version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><style type="text/css">.st0{fill:#000000;}</style><path class="st0" d="m256 .006c-141 .007-256 115-256 256 .012 141 115 256 256 256 141-.008 256-115 256-256-.008-141-115-256-256-256zm-158 97.6c23.3-23.3 51.8-41.5 83.5-52.7-15.2 18.4-27.8 41.9-37.8 69.1h-60.5c4.68-5.7 9.62-11.2 14.8-16.4zm-32 40.4h70c-9.01 31.9-14.4 67.8-15.4 106h-87.9c2.05-38.8 14-74.9 33.3-106zm0 236c-19.3-31.1-31.2-67.2-33.3-106h88c.961 38.1 6.21 74.1 15.2 106h-69.9zm32 40.4c-5.21-5.21-10.2-10.7-14.8-16.4h60.6c4.28 11.8 9.02 22.9 14.3 33.2 6.95 13.4 14.8 25.5 23.3 35.9-31.7-11.2-60.1-29.4-83.4-52.7zm146 65.3c-3.75-.196-7.47-.477-11.2-.86-5.89-2.64-11.7-6.25-17.5-11-17.6-14.4-34-38.7-46.4-69.8h75.1v81.7zm0-106h-83.4c-9.48-31.2-15.3-67.3-16.3-106h99.8v106zm0-130h-99.7c1.01-38.7 6.88-74.8 16.4-106h83.3v106zm0-130h-75c3.11-7.79 6.37-15.3 9.93-22.2 10.6-20.6 23.2-36.9 36.4-47.7 5.78-4.71 11.6-8.32 17.5-11 3.7-.382 7.42-.664 11.2-.859v81.7zm202 24c19.3 31.1 31.2 67.2 33.3 106h-88c-.961-38.1-6.21-74.1-15.2-106h69.9zm-32-40.4c5.21 5.21 10.2 10.7 14.8 16.4h-60.6c-4.28-11.8-9.02-22.9-14.3-33.2-6.95-13.4-14.8-25.5-23.3-35.9 31.7 11.3 60.1 29.4 83.4 52.7zm-146-65.3c3.75.195 7.47.484 11.2.859 5.89 2.65 11.7 6.25 17.5 11 17.6 14.4 34 38.7 46.4 69.8h-75.1v-81.7zm0 106h83.4c9.48 31.2 15.3 67.3 16.3 106h-99.8v-106zm0 130h99.7c-1.01 38.7-6.87 74.8-16.4 106h-83.3v-106zm28.7 200c-5.78 4.71-11.6 8.31-17.5 11-3.69.375-7.41.664-11.2.86v-81.7h75c-3.11 7.79-6.37 15.3-9.93 22.2-10.6 20.6-23.2 36.9-36.4 47.7zm118-53.5c-23.3 23.3-51.8 41.5-83.5 52.7 15.2-18.4 27.8-41.9 37.8-69.1h60.5c-4.68 5.7-9.62 11.2-14.8 16.4zm32-40.4h-70c9.01-31.9 14.4-67.8 15.4-106h87.9c-2.05 38.8-14 74.9-33.3 106z"/></svg> 2 + <svg 3 + width="16px" 4 + height="16px" 5 + version="1.1" 6 + viewBox="0 0 512 512" 7 + xmlns="http://www.w3.org/2000/svg" 8 + > 9 + <path 10 + fill="currentColor" 11 + d="m256 .006c-141 .007-256 115-256 256 .012 141 115 256 256 256 141-.008 256-115 256-256-.008-141-115-256-256-256zm-158 97.6c23.3-23.3 51.8-41.5 83.5-52.7-15.2 18.4-27.8 41.9-37.8 69.1h-60.5c4.68-5.7 9.62-11.2 14.8-16.4zm-32 40.4h70c-9.01 31.9-14.4 67.8-15.4 106h-87.9c2.05-38.8 14-74.9 33.3-106zm0 236c-19.3-31.1-31.2-67.2-33.3-106h88c.961 38.1 6.21 74.1 15.2 106h-69.9zm32 40.4c-5.21-5.21-10.2-10.7-14.8-16.4h60.6c4.28 11.8 9.02 22.9 14.3 33.2 6.95 13.4 14.8 25.5 23.3 35.9-31.7-11.2-60.1-29.4-83.4-52.7zm146 65.3c-3.75-.196-7.47-.477-11.2-.86-5.89-2.64-11.7-6.25-17.5-11-17.6-14.4-34-38.7-46.4-69.8h75.1v81.7zm0-106h-83.4c-9.48-31.2-15.3-67.3-16.3-106h99.8v106zm0-130h-99.7c1.01-38.7 6.88-74.8 16.4-106h83.3v106zm0-130h-75c3.11-7.79 6.37-15.3 9.93-22.2 10.6-20.6 23.2-36.9 36.4-47.7 5.78-4.71 11.6-8.32 17.5-11 3.7-.382 7.42-.664 11.2-.859v81.7zm202 24c19.3 31.1 31.2 67.2 33.3 106h-88c-.961-38.1-6.21-74.1-15.2-106h69.9zm-32-40.4c5.21 5.21 10.2 10.7 14.8 16.4h-60.6c-4.28-11.8-9.02-22.9-14.3-33.2-6.95-13.4-14.8-25.5-23.3-35.9 31.7 11.3 60.1 29.4 83.4 52.7zm-146-65.3c3.75.195 7.47.484 11.2.859 5.89 2.65 11.7 6.25 17.5 11 17.6 14.4 34 38.7 46.4 69.8h-75.1v-81.7zm0 106h83.4c9.48 31.2 15.3 67.3 16.3 106h-99.8v-106zm0 130h99.7c-1.01 38.7-6.87 74.8-16.4 106h-83.3v-106zm28.7 200c-5.78 4.71-11.6 8.31-17.5 11-3.69.375-7.41.664-11.2.86v-81.7h75c-3.11 7.79-6.37 15.3-9.93 22.2-10.6 20.6-23.2 36.9-36.4 47.7zm118-53.5c-23.3 23.3-51.8 41.5-83.5 52.7 15.2-18.4 27.8-41.9 37.8-69.1h60.5c-4.68 5.7-9.62 11.2-14.8 16.4zm32-40.4h-70c9.01-31.9 14.4-67.8 15.4-106h87.9c-2.05 38.8-14 74.9-33.3 106z" 12 + /> 13 + </svg>
+25
assets/svg/links.svg
··· 1 + <svg 2 + fill="currentColor" 3 + height="24" 4 + version="1.1" 5 + viewBox="0 0 15.36 15.36" 6 + width="24" 7 + xmlns="http://www.w3.org/2000/svg" 8 + > 9 + <g transform="matrix(.03 0 0 .03 -.00016582 -.00038274)"> 10 + <g fill-rule="evenodd"> 11 + <path 12 + d="m503.47 132.27-123.73-123.73a29.17 29.17 0 0 0-41.234 0l-123.73 123.73a29.15 29.15 0 0 0 0 41.265l20.6 20.6 123.73-123.73 82.5 82.5-123.73 123.73 20.633 20.632a29.169 29.169 0 0 0 41.234 0l123.73-123.73a29.207 29.207 0 0 0 1e-3 -41.265z" 13 + data-name="Path 51" 14 + ></path> 15 + <path 16 + d="m276.63 317.87-123.73 123.73-82.5-82.5 123.73-123.73-20.633-20.632a29.167 29.167 0 0 0-41.233 0l-123.73 123.73a29.208 29.208 0 0 0 0 41.265l123.73 123.73a29.169 29.169 0 0 0 41.233 0l123.73-123.73a29.152 29.152 0 0 0 0-41.265z" 17 + data-name="Path 52" 18 + ></path> 19 + <path 20 + d="m173.5 338.47a29.153 29.153 0 0 0 41.266 0l123.73-123.73a29.157 29.157 0 0 0-41.265-41.2l-123.74 123.73a29.133 29.133 0 0 0 0 41.203z" 21 + data-name="Path 53" 22 + ></path> 23 + </g> 24 + </g> 25 + </svg>
+17
assets/svg/map.svg
··· 1 + <svg 2 + fill="none" 3 + height="24" 4 + stroke="currentColor" 5 + stroke-linecap="round" 6 + stroke-linejoin="round" 7 + stroke-width="2" 8 + viewBox="0 0 24 24" 9 + width="24" 10 + xmlns="http://www.w3.org/2000/svg" 11 + > 12 + <path d="M3 5c2-1 5-1 8 0s6 1 8 0"></path> 13 + <path d="M3 19c2 1 5 1 8 0s6-1 8 0"></path> 14 + <path d="M3 5v14M21 5v14"></path> 15 + <path d="M16 5l5 5"></path> 16 + <path d="M7 10c2-2 4 2 6 0s4-2 6 0"></path> 17 + </svg>
+14
assets/svg/menu.svg
··· 1 + <svg 2 + class="h-5 w-5" 3 + fill="none" 4 + stroke="currentColor" 5 + viewBox="0 0 24 24" 6 + xmlns="http://www.w3.org/2000/svg" 7 + > 8 + <path 9 + d="M4 6h16M4 12h16M4 18h7" 10 + stroke-linecap="round" 11 + stroke-linejoin="round" 12 + stroke-width="2" 13 + ></path> 14 + </svg>
+2 -1
dev/homepage/prepare.gleam
··· 14 14 import gleam/time/calendar 15 15 import gleam/time/timestamp 16 16 import glentities 17 - import homepage.{Entry} 17 + import homepage 18 + import homepage/stuff.{Entry} 18 19 import simplifile 19 20 import webls/rss 20 21
+64 -741
src/homepage.gleam
··· 1 - import gleam/io 2 - 3 1 /// Post data ------------------------------------------------------------------- 4 2 /// 5 3 /// Some special tags: ··· 589 587 ), 590 588 ] 591 589 592 - // The site itself 590 + // The imports 593 591 594 592 import chilp 595 593 import chilp/widget 596 - import gleam/dict.{type Dict} 594 + import gleam/dict 597 595 import gleam/function 598 596 import gleam/int 597 + import gleam/io 599 598 import gleam/list 600 599 import gleam/option.{type Option, None, Some} 601 600 import gleam/pair ··· 608 607 import gleam/uri.{type Uri} 609 608 import homepage/djotparse 610 609 import homepage/from_prebuild/data 610 + import homepage/stuff.{ 611 + type Badge, type Entry, type FeedEntry, type Model, type Msg, 612 + type NormalizedPost, type Post, type Route, AllAndEverything, Badge, Category, 613 + CommentsDisable, CuriculumVitae, Djot, Entry, FeedEntry, File, HTML, Index, 614 + Inline, Links, Lustre, MastodonStatusLink, Me, Model, NormalizedPost, NotFound, 615 + PersonalStartPage, Plain, Portfolio, Post, PostById, Posts, Sitemap, Tagged, 616 + UserNavigatedTo, 617 + } 618 + import homepage/stuff/prestyled_elements.{ 619 + codeforges_links, leading, paragraph, socials, subsubtitle, subtitle, title, 620 + } 611 621 import homepage/view/cv 622 + import homepage/view/not_found 612 623 import lustre 613 624 import lustre/attribute.{type Attribute, attribute} 614 625 import lustre/effect.{type Effect} 615 626 import lustre/element.{type Element} 616 627 import lustre/element/html 617 - import lustre/element/svg 618 628 import modem 619 629 630 + // The site itself 631 + 620 632 pub fn main() { 621 633 let assert Ok(_) = widget.register() 622 634 let app = lustre.application(init, update, view) ··· 625 637 Nil 626 638 } 627 639 628 - // Some types for your consideration 629 - 630 - pub type Entry { 631 - Entry(route: Route, title: String, last_updated: calendar.Date, parent: Route) 632 - } 633 - 634 - pub type FeedEntry { 635 - FeedEntry( 636 - /// Id, used to determine permalink. 637 - id: Int, 638 - /// Description 639 - description: String, 640 - entry: Entry, 641 - ) 642 - } 643 - 644 - type Badge { 645 - Badge( 646 - clickable_url: String, 647 - img_url: String, 648 - img_alt: String, 649 - img_title: String, 650 - text_badge: String, 651 - ) 652 - } 653 - 654 - type Model { 655 - Model( 656 - posts: Dict(Int, NormalizedPost), 657 - aliases: Dict(String, Int), 658 - route: Route, 659 - ) 660 - } 661 - 662 - type Post { 663 - Post( 664 - id: Int, 665 - category: String, 666 - title: String, 667 - summary: String, 668 - published: calendar.Date, 669 - revised: Option(calendar.Date), 670 - body: Body, 671 - tags: List(String), 672 - aliases: List(String), 673 - comments: MastodonComments, 674 - ) 675 - } 676 - 677 - type MastodonComments { 678 - /// example https://[pony.social]/@strawmelonjuice/[115911235653686237]. 679 - MastodonStatusLink(instance: String, id: String) 680 - CommentsDisable 681 - } 682 - 683 - type NormalizedPost { 684 - NormalizedPost( 685 - id: Int, 686 - category: String, 687 - title: String, 688 - published: calendar.Date, 689 - revised: Option(calendar.Date), 690 - summary: String, 691 - body: Element(Msg), 692 - tags: List(String), 693 - comments: MastodonComments, 694 - ) 695 - } 696 - 697 - type Body { 698 - Lustre(Element(Msg)) 699 - File(markup: Markup, path: String) 700 - Inline(markup: Markup, string: String) 701 - } 702 - 703 - pub type Markup { 704 - Djot 705 - Plain 706 - HTML 707 - } 708 - 709 - type Msg { 710 - UserNavigatedTo(route: Route) 711 - } 712 - 713 - pub type Route { 714 - Index 715 - Posts 716 - PostById(id: Int) 717 - Me 718 - Portfolio 719 - NotFound(uri: Uri) 720 - AllAndEverything 721 - Sitemap 722 - Category(String) 723 - Tagged(String) 724 - Links 725 - PersonalStartPage 726 - CuriculumVitae(in_dutch: Bool) 727 - } 728 - 729 640 pub fn posts_entries() -> List(FeedEntry) { 730 641 posts() 731 642 |> list.map(fn(post) { ··· 745 656 }) 746 657 } 747 658 748 - fn render_badge(badge: Badge) -> Element(msg) { 659 + fn render_badge(badge: Badge) -> Element(Msg) { 749 660 let img = 750 661 html.img([ 751 662 attribute.src(badge.img_url), ··· 978 889 } 979 890 } 980 891 981 - pub fn to_url(route: Route) -> String { 982 - case route { 983 - Index -> "/" 984 - Me -> "/me" 985 - Posts -> "/posts" 986 - PostById(post_id) -> { 987 - let slug = { 988 - let m = list.find(posts(), fn(p) { p.id == post_id }) 989 - case m { 990 - Error(Nil) -> int.to_string(post_id) 991 - Ok(p) -> { 992 - case p.aliases { 993 - [] -> int.to_string(post_id) 994 - [alias, ..] -> alias 995 - } 996 - } 997 - } 998 - } 999 - "/post/" <> slug 1000 - } 1001 - Portfolio -> "/me/portfolio" 1002 - Links -> "/me/links" 1003 - AllAndEverything -> "/everything" 1004 - PersonalStartPage -> "/startpage" 1005 - NotFound(_) -> "/404" 1006 - Tagged(v) -> "/posts/tagged/" <> v 1007 - Category(c) -> "/posts/category/" <> c 1008 - Sitemap -> "/sitemap" 1009 - CuriculumVitae(False) -> "/cv/en" 1010 - CuriculumVitae(True) -> "/cv/nl" 1011 - } 1012 - } 1013 - 1014 - fn href(route: Route) -> Attribute(Msg) { 1015 - attribute.href(to_url(route)) 1016 - } 1017 - 1018 892 fn init(_) -> #(Model, Effect(Msg)) { 893 + let raw_posts = posts() 1019 894 let aliases = 1020 895 list.map(posts(), fn(post) { 1021 896 list.map(post.aliases, fn(alias) { #(post.id, alias) }) ··· 1028 903 posts() 1029 904 |> list.map(fn(post) { #(post.id, post |> post_normalize) }) 1030 905 |> dict.from_list 1031 - 906 + let base_model = Model(raw_posts:, route: Index, posts:, aliases:) 1032 907 let route = case modem.initial_uri() { 1033 - Ok(uri) -> parse_route(uri, Model(Index, posts:, aliases:)) 908 + Ok(uri) -> parse_route(uri, base_model) 1034 909 Error(_) -> Index 1035 910 } 1036 - let model = Model(route:, posts:, aliases:) 911 + let model = Model(..base_model, route:) 1037 912 1038 913 let effect = 1039 914 [ ··· 1158 1033 view_portfolio() 1159 1034 |> into_altered_main(string.replace(_, "max-w-2xl", "max-w-6xl")) 1160 1035 Sitemap -> view_sitemap() |> into_main_with_badges 1161 - NotFound(_) -> view_not_found() |> into_main_with_badges 1036 + NotFound(_) -> not_found.view() |> into_main_with_badges 1162 1037 AllAndEverything -> view_all_and_everything(model) |> into_main 1163 1038 PersonalStartPage -> view_personal_start_page() |> into_main_with_badges 1164 - CuriculumVitae(in_dutch) -> cv.view(in_dutch) 1039 + CuriculumVitae(in_dutch) -> cv.view(model, in_dutch) 1165 1040 } 1166 1041 }, 1167 1042 ··· 1244 1119 attribute("tabindex", "0"), 1245 1120 ], 1246 1121 [ 1247 - // Menu button svg 1248 - svg.svg( 1249 - [ 1250 - attribute("stroke", "currentColor"), 1251 - attribute("viewBox", "0 0 24 24"), 1252 - attribute("fill", "none"), 1253 - attribute.class("h-5 w-5"), 1254 - attribute("xmlns", "http://www.w3.org/2000/svg"), 1255 - ], 1256 - [ 1257 - svg.path([ 1258 - attribute("d", "M4 6h16M4 12h16M4 18h7"), 1259 - attribute("stroke-width", "2"), 1260 - attribute("stroke-linejoin", "round"), 1261 - attribute("stroke-linecap", "round"), 1262 - ]), 1263 - ], 1264 - ), 1122 + html.img([ 1123 + attribute.class("h-5 w-5"), 1124 + attribute.src("/svg/menu.svg"), 1125 + ]), 1265 1126 ], 1266 1127 ), 1267 1128 ··· 1286 1147 attribute.class("btn btn-ghost btn-circle"), 1287 1148 ], 1288 1149 [ 1289 - svg.svg( 1290 - [ 1291 - attribute("stroke-linejoin", "round"), 1292 - attribute("stroke-linecap", "round"), 1293 - attribute("stroke-width", "2"), 1294 - attribute("stroke", "currentColor"), 1295 - attribute("fill", "none"), 1296 - attribute("viewBox", "0 0 24 24"), 1297 - attribute("height", "24"), 1298 - attribute("width", "24"), 1299 - attribute("xmlns", "http://www.w3.org/2000/svg"), 1300 - ], 1301 - [ 1302 - svg.path([attribute("d", "M3 5c2-1 5-1 8 0s6 1 8 0")]), 1303 - svg.path([attribute("d", "M3 19c2 1 5 1 8 0s6-1 8 0")]), 1304 - svg.path([attribute("d", "M3 5v14M21 5v14")]), 1305 - svg.path([attribute("d", "M16 5l5 5")]), 1306 - svg.path([attribute("d", "M7 10c2-2 4 2 6 0s4-2 6 0")]), 1307 - ], 1308 - ), 1150 + html.img([attribute.src("/svg/map.svg")]), 1309 1151 ], 1310 1152 ), 1311 1153 ]), ··· 1333 1175 attribute.class("btn btn-ghost btn-circle"), 1334 1176 ], 1335 1177 [ 1336 - svg.svg( 1337 - [ 1338 - attribute("xmlns", "http://www.w3.org/2000/svg"), 1339 - attribute("viewBox", "0 0 15.36 15.36"), 1340 - attribute("version", "1.1"), 1341 - attribute("fill", "currentColor"), 1342 - attribute("height", "24"), 1343 - attribute("width", "24"), 1344 - ], 1345 - [ 1346 - svg.g( 1347 - [ 1348 - attribute( 1349 - "transform", 1350 - "matrix(.03 0 0 .03 -.00016582 -.00038274)", 1351 - ), 1352 - attribute.id("_40_Hyperlink"), 1353 - ], 1354 - [ 1355 - svg.g([attribute("fill-rule", "evenodd")], [ 1356 - svg.path([ 1357 - attribute("data-name", "Path 51"), 1358 - attribute( 1359 - "d", 1360 - "m503.47 132.27-123.73-123.73a29.17 29.17 0 0 0-41.234 0l-123.73 123.73a29.15 29.15 0 0 0 0 41.265l20.6 20.6 123.73-123.73 82.5 82.5-123.73 123.73 20.633 20.632a29.169 29.169 0 0 0 41.234 0l123.73-123.73a29.207 29.207 0 0 0 1e-3 -41.265z", 1361 - ), 1362 - ]), 1363 - svg.path([ 1364 - attribute("data-name", "Path 52"), 1365 - attribute( 1366 - "d", 1367 - "m276.63 317.87-123.73 123.73-82.5-82.5 123.73-123.73-20.633-20.632a29.167 29.167 0 0 0-41.233 0l-123.73 123.73a29.208 29.208 0 0 0 0 41.265l123.73 123.73a29.169 29.169 0 0 0 41.233 0l123.73-123.73a29.152 29.152 0 0 0 0-41.265z", 1368 - ), 1369 - ]), 1370 - svg.path([ 1371 - attribute("data-name", "Path 53"), 1372 - attribute( 1373 - "d", 1374 - "m173.5 338.47a29.153 29.153 0 0 0 41.266 0l123.73-123.73a29.157 29.157 0 0 0-41.265-41.2l-123.74 123.73a29.133 29.133 0 0 0 0 41.203z", 1375 - ), 1376 - ]), 1377 - ]), 1378 - ], 1379 - ), 1380 - ], 1381 - ), 1178 + html.img([attribute.src("/svg/links.svg")]), 1382 1179 ], 1383 1180 ), 1384 1181 ], ··· 1790 1587 ] 1791 1588 } 1792 1589 1793 - fn socials(collapsible small: Bool) -> Element(Msg) { 1794 - html.div([attribute.class("grid grid-flow-col gap-4")], [ 1795 - // Mastodon ================================================================================= 1796 - html.a( 1797 - [ 1798 - attribute.target("_blank"), 1799 - attribute.href("https://pony.social/@strawmelonjuice"), 1800 - attribute.class("cursor-pointer w-[26px] h-[26px] hover:text-[#5638cc]"), 1801 - attribute.classes([#("hidden md:block", small)]), 1802 - ], 1803 - [ 1804 - svg.svg( 1805 - [ 1806 - attribute("xmlns", "http://www.w3.org/2000/svg"), 1807 - attribute("fill", "currentColor"), 1808 - attribute("viewBox", "0 0 74 79"), 1809 - attribute("height", "24"), 1810 - attribute("width", "24"), 1811 - ], 1812 - [ 1813 - svg.path([ 1814 - attribute("fill", "inherit"), 1815 - attribute( 1816 - "d", 1817 - "M73.7014 17.9592C72.5616 9.62034 65.1774 3.04876 56.424 1.77536C54.9472 1.56019 49.3517 0.7771 36.3901 0.7771H36.2933C23.3281 0.7771 20.5465 1.56019 19.0697 1.77536C10.56 3.01348 2.78877 8.91838 0.903306 17.356C-0.00357857 21.5113 -0.100361 26.1181 0.068112 30.3439C0.308275 36.404 0.354874 42.4535 0.91406 48.489C1.30064 52.498 1.97502 56.4751 2.93215 60.3905C4.72441 67.6217 11.9795 73.6395 19.0876 76.0945C26.6979 78.6548 34.8821 79.0799 42.724 77.3221C43.5866 77.1245 44.4398 76.8953 45.2833 76.6342C47.1867 76.0381 49.4199 75.3714 51.0616 74.2003C51.0841 74.1839 51.1026 74.1627 51.1156 74.1382C51.1286 74.1138 51.1359 74.0868 51.1368 74.0592V68.2108C51.1364 68.185 51.1302 68.1596 51.1185 68.1365C51.1069 68.1134 51.0902 68.0932 51.0695 68.0773C51.0489 68.0614 51.0249 68.0503 50.9994 68.0447C50.9738 68.0391 50.9473 68.0392 50.9218 68.045C45.8976 69.226 40.7491 69.818 35.5836 69.8087C26.694 69.8087 24.3031 65.6569 23.6184 63.9285C23.0681 62.4347 22.7186 60.8764 22.5789 59.2934C22.5775 59.2669 22.5825 59.2403 22.5934 59.216C22.6043 59.1916 22.621 59.1702 22.6419 59.1533C22.6629 59.1365 22.6876 59.1248 22.714 59.1191C22.7404 59.1134 22.7678 59.1139 22.794 59.1206C27.7345 60.2936 32.799 60.8856 37.8813 60.8843C39.1036 60.8843 40.3223 60.8843 41.5447 60.8526C46.6562 60.7115 52.0437 60.454 57.0728 59.4874C57.1983 59.4628 57.3237 59.4416 57.4313 59.4098C65.3638 57.9107 72.9128 53.2051 73.6799 41.2895C73.7086 40.8204 73.7803 36.3758 73.7803 35.889C73.7839 34.2347 74.3216 24.1533 73.7014 17.9592ZM61.4925 47.6918H53.1514V27.5855C53.1514 23.3526 51.3591 21.1938 47.7136 21.1938C43.7061 21.1938 41.6988 23.7476 41.6988 28.7919V39.7974H33.4078V28.7919C33.4078 23.7476 31.3969 21.1938 27.3894 21.1938C23.7654 21.1938 21.9552 23.3526 21.9516 27.5855V47.6918H13.6176V26.9752C13.6176 22.7423 14.7157 19.3795 16.9118 16.8868C19.1772 14.4 22.1488 13.1231 25.8373 13.1231C30.1064 13.1231 33.3325 14.7386 35.4832 17.9662L37.5587 21.3949L39.6377 17.9662C41.7884 14.7386 45.0145 13.1231 49.2765 13.1231C52.9614 13.1231 55.9329 14.4 58.2055 16.8868C60.4017 19.3772 61.4997 22.74 61.4997 26.9752L61.4925 47.6918Z", 1818 - ), 1819 - ]), 1820 - ], 1821 - ), 1822 - ], 1823 - ), 1824 - 1825 - // Instagram ================================================================================= 1826 - // html.a( 1827 - // [ 1828 - // attribute.target("_blank"), 1829 - // attribute.href("https://instagram.com/strawmelonjuice"), 1830 - // attribute.class("cursor-pointer"), 1831 - // ], 1832 - // [ 1833 - // svg.svg( 1834 - // [ 1835 - // attribute("xmlns:xlink", "http://www.w3.org/1999/xlink"), 1836 - // attribute("xmlns", "http://www.w3.org/2000/svg"), 1837 - // attribute("version", "1.1"), 1838 - // attribute("viewBox", "0 0 20 20"), 1839 - // attribute("height", "24"), 1840 - // attribute("width", "24"), 1841 - // ], 1842 - // [ 1843 - // svg.g( 1844 - // [ 1845 - // attribute("fill-rule", "evenodd"), 1846 - // attribute("fill", "none"), 1847 - // attribute("stroke-width", "1"), 1848 - // attribute("stroke", "none"), 1849 - // attribute.id("Page-1"), 1850 - // ], 1851 - // [ 1852 - // svg.g( 1853 - // [ 1854 - // attribute("fill", "currentColor"), 1855 - // attribute( 1856 - // "transform", 1857 - // "translate(-340.000000, -7439.000000)", 1858 - // ), 1859 - // attribute.id("Dribbble-Light-Preview"), 1860 - // ], 1861 - // [ 1862 - // svg.g( 1863 - // [ 1864 - // attribute( 1865 - // "transform", 1866 - // "translate(56.000000, 160.000000)", 1867 - // ), 1868 - // attribute.id("icons"), 1869 - // ], 1870 - // [ 1871 - // svg.path([ 1872 - // attribute.id("instagram-[#167]"), 1873 - // attribute( 1874 - // "d", 1875 - // "M289.869652,7279.12273 C288.241769,7279.19618 286.830805,7279.5942 285.691486,7280.72871 C284.548187,7281.86918 284.155147,7283.28558 284.081514,7284.89653 C284.035742,7285.90201 283.768077,7293.49818 284.544207,7295.49028 C285.067597,7296.83422 286.098457,7297.86749 287.454694,7298.39256 C288.087538,7298.63872 288.809936,7298.80547 289.869652,7298.85411 C298.730467,7299.25511 302.015089,7299.03674 303.400182,7295.49028 C303.645956,7294.859 303.815113,7294.1374 303.86188,7293.08031 C304.26686,7284.19677 303.796207,7282.27117 302.251908,7280.72871 C301.027016,7279.50685 299.5862,7278.67508 289.869652,7279.12273 M289.951245,7297.06748 C288.981083,7297.0238 288.454707,7296.86201 288.103459,7296.72603 C287.219865,7296.3826 286.556174,7295.72155 286.214876,7294.84312 C285.623823,7293.32944 285.819846,7286.14023 285.872583,7284.97693 C285.924325,7283.83745 286.155174,7282.79624 286.959165,7281.99226 C287.954203,7280.99968 289.239792,7280.51332 297.993144,7280.90837 C299.135448,7280.95998 300.179243,7281.19026 300.985224,7281.99226 C301.980262,7282.98483 302.473801,7284.28014 302.071806,7292.99991 C302.028024,7293.96767 301.865833,7294.49274 301.729513,7294.84312 C300.829003,7297.15085 298.757333,7297.47145 289.951245,7297.06748 M298.089663,7283.68956 C298.089663,7284.34665 298.623998,7284.88065 299.283709,7284.88065 C299.943419,7284.88065 300.47875,7284.34665 300.47875,7283.68956 C300.47875,7283.03248 299.943419,7282.49847 299.283709,7282.49847 C298.623998,7282.49847 298.089663,7283.03248 298.089663,7283.68956 M288.862673,7288.98792 C288.862673,7291.80286 291.150266,7294.08479 293.972194,7294.08479 C296.794123,7294.08479 299.081716,7291.80286 299.081716,7288.98792 C299.081716,7286.17298 296.794123,7283.89205 293.972194,7283.89205 C291.150266,7283.89205 288.862673,7286.17298 288.862673,7288.98792 M290.655732,7288.98792 C290.655732,7287.16159 292.140329,7285.67967 293.972194,7285.67967 C295.80406,7285.67967 297.288657,7287.16159 297.288657,7288.98792 C297.288657,7290.81525 295.80406,7292.29716 293.972194,7292.29716 C292.140329,7292.29716 290.655732,7290.81525 290.655732,7288.98792", 1876 - // ), 1877 - // ]), 1878 - // ], 1879 - // ), 1880 - // ], 1881 - // ), 1882 - // ], 1883 - // ), 1884 - // ], 1885 - // ), 1886 - // ], 1887 - // ), 1888 - // 1889 - // Matrix ================================================================================= 1890 - html.a( 1891 - [ 1892 - attribute.target("_blank"), 1893 - attribute.href("https://matrix.to/#/@mar:strawmelonjuice.com"), 1894 - attribute.class( 1895 - "cursor-pointer w-[26px] h-[26px] hover:text-black hover:bg-white", 1896 - ), 1897 - ], 1898 - [ 1899 - svg.svg( 1900 - [ 1901 - attribute("xmlns", "http://www.w3.org/2000/svg"), 1902 - attribute("xml:space", "preserve"), 1903 - attribute("viewBox", "0 0 26 26"), 1904 - attribute("version", "1.1"), 1905 - attribute("height", "26"), 1906 - attribute("width", "26"), 1907 - ], 1908 - [ 1909 - svg.g( 1910 - [ 1911 - attribute("stroke-width", ".05"), 1912 - attribute("fill", "currentColor"), 1913 - ], 1914 - [ 1915 - svg.path([ 1916 - attribute( 1917 - "d", 1918 - "m0.685 0.595v24.81h1.785v0.59499h-2.47v-26h2.47v0.595z", 1919 - ), 1920 - ]), 1921 - svg.path([ 1922 - attribute( 1923 - "d", 1924 - "m8.315 8.46v1.255h0.035007c0.33499-0.48 0.73999-0.85 1.21-1.11 0.47-0.265 1.015-0.395 1.625-0.395 0.585 0 1.12 0.115 1.605 0.34 0.48501 0.225 0.85001 0.63 1.105 1.2 0.275-0.405 0.65-0.765 1.12-1.075 0.47001-0.31 1.03-0.465 1.675-0.465 0.49001 0 0.94501 0.060005 1.365 0.18 0.42001 0.12 0.775 0.31 1.075 0.575 0.3 0.265 0.52999 0.605 0.69999 1.03 0.16501 0.425 0.25001 0.935 0.25001 1.535v6.205h-2.545v-5.255c0-0.31-0.0093-0.605-0.03492-0.88001-0.02507-0.27499-0.09007-0.51499-0.19506-0.71499-0.11002-0.205-0.26503-0.365-0.47502-0.485-0.21-0.12-0.495-0.18-0.85-0.18-0.36001 0-0.65 0.06999-0.87002 0.205-0.22 0.14-0.395 0.315-0.52 0.54-0.12498 0.22-0.20999 0.47-0.24999 0.755-0.03993 0.28-0.065 0.565-0.065 0.85v5.165h-2.545v-5.2c0-0.275-0.0047-0.54501-0.02005-0.81501-0.0099-0.27-0.06498-0.515-0.15497-0.745-0.08994-0.225-0.23997-0.41-0.44996-0.545-0.21-0.135-0.515-0.205-0.925-0.205-0.12 0-0.28 0.02497-0.475 0.08-0.195 0.05501-0.39 0.155-0.575 0.305-0.185 0.15-0.345 0.365-0.475 0.645-0.13 0.28-0.195 0.65-0.195 1.105v5.38h-2.545v-9.28z", 1925 - ), 1926 - ]), 1927 - svg.path([ 1928 - attribute( 1929 - "d", 1930 - "m25.315 25.405v-24.81h-1.785v-0.595h2.47v26h-2.47v-0.59499z", 1931 - ), 1932 - ]), 1933 - ], 1934 - ), 1935 - ], 1936 - ), 1937 - ], 1938 - ), 1939 - // Email ================================================================================== 1940 - html.a( 1941 - [ 1942 - attribute.target("_blank"), 1943 - attribute.href("mailto:web@strawmelonjuice.com"), 1944 - attribute.class("cursor-pointer w-[26px] h-[26px] hover:text-[#cc3856]"), 1945 - ], 1946 - [ 1947 - svg.svg( 1948 - [ 1949 - attribute("xmlns", "http://www.w3.org/2000/svg"), 1950 - 1951 - attribute("viewBox", "0 0 .72 .72"), 1952 - 1953 - attribute("version", "1.1"), 1954 - 1955 - attribute("fill", "none"), 1956 - 1957 - attribute("height", "24"), 1958 - 1959 - attribute("width", "24"), 1960 - ], 1961 - [ 1962 - svg.path([ 1963 - attribute("stroke-width", ".072"), 1964 - 1965 - attribute("stroke-linejoin", "round"), 1966 - 1967 - attribute("stroke-linecap", "round"), 1968 - 1969 - attribute("stroke", "currentColor"), 1970 - 1971 - attribute( 1972 - "d", 1973 - "m0.074646 0.1641 0.24984 0.15615c0.023346 0.014591 0.052974 0.014591 0.07632 0l0.24984-0.15615m-0.54 0.396h0.504c0.039766 0 0.072-0.032234 0.072-0.072v-0.288c0-0.039764-0.032234-0.072-0.072-0.072h-0.504c-0.039764 0-0.072 0.032236-0.072 0.072v0.288c0 0.039766 0.032236 0.072 0.072 0.072z", 1974 - ), 1975 - ]), 1976 - ], 1977 - ), 1978 - ], 1979 - ), 1980 - // Bluesky ================================================================================ 1981 - html.a( 1982 - [ 1983 - attribute.target("_blank"), 1984 - attribute.href( 1985 - "https://witchsky.app/profile/did:plc:jgtfsmv25thfs4zmydtbccnn", 1986 - ), 1987 - attribute.class("cursor-pointer w-[26px] h-[26px] hover:text-[#006aff]"), 1988 - attribute.classes([#("hidden md:block", small)]), 1989 - ], 1990 - [ 1991 - svg.svg( 1992 - [ 1993 - attribute("xmlns", "http://www.w3.org/2000/svg"), 1994 - attribute("viewBox", "0 0 48 24"), 1995 - attribute("version", "1.1"), 1996 - attribute("fill", "none"), 1997 - attribute("height", "24"), 1998 - attribute("width", "24"), 1999 - ], 2000 - [ 2001 - svg.path([ 2002 - attribute("stroke-width", ".65268"), 2003 - attribute("fill", "currentColor"), 2004 - attribute( 2005 - "d", 2006 - "m12.083-4.7208c4.7887 3.6074 9.9404 10.921 11.831 14.845v10.366c0-0.22061-0.08485 0.02872-0.2676 0.56588-0.98686 2.9084-4.8416 14.259-13.656 5.1849-4.6412-4.7776-2.4926-9.5553 5.9557-10.998-4.8331 0.82499-10.267-0.53846-11.757-5.8839-0.42947-1.5377-1.1605-11.009-1.1605-12.289 0-6.408 5.5994-4.3939 9.0547-1.7916zm23.662 0c-4.7887 3.6074-9.9404 10.921-11.831 14.845v10.366c0-0.22061 0.08485 0.02872 0.2676 0.56588 0.98686 2.9084 4.8416 14.259 13.656 5.1849 4.6412-4.7776 2.4926-9.5553-5.9557-10.998 4.8331 0.82499 10.267-0.53846 11.757-5.8839 0.42946-1.5377 1.1605-11.009 1.1605-12.289 0-6.408-5.5987-4.3939-9.0547-1.7916z", 2007 - ), 2008 - ]), 2009 - ], 2010 - ), 2011 - ], 2012 - ), 2013 - // Tumblr ================================================================================= 2014 - // html.a( 2015 - // [ 2016 - // attribute.target("_blank"), 2017 - // attribute.href("https://tumblr.com/strawmelonjuice"), 2018 - // ], 2019 - // [ 2020 - // svg.svg( 2021 - // [ 2022 - // attribute("xmlns:xlink", "http://www.w3.org/1999/xlink"), 2023 - // attribute("xmlns", "http://www.w3.org/2000/svg"), 2024 - // attribute("version", "1.1"), 2025 - // attribute("viewBox", "-4 0 20 20"), 2026 - // attribute("height", "24"), 2027 - // attribute("width", "24"), 2028 - // ], 2029 - // [ 2030 - // svg.g( 2031 - // [ 2032 - // attribute("fill-rule", "evenodd"), 2033 - // attribute("fill", "none"), 2034 - // attribute("stroke-width", "1"), 2035 - // attribute("stroke", "none"), 2036 - // attribute.id("Page-1"), 2037 - // ], 2038 - // [ 2039 - // svg.g( 2040 - // [ 2041 - // attribute("fill", "currentColor"), 2042 - // attribute( 2043 - // "transform", 2044 - // "translate(-184.000000, -7399.000000)", 2045 - // ), 2046 - // attribute.id("Dribbble-Light-Preview"), 2047 - // ], 2048 - // [ 2049 - // svg.g( 2050 - // [ 2051 - // attribute( 2052 - // "transform", 2053 - // "translate(56.000000, 160.000000)", 2054 - // ), 2055 - // attribute.id("icons"), 2056 - // ], 2057 - // [ 2058 - // svg.path([ 2059 - // attribute.id("tumblr-[#181]"), 2060 - // attribute( 2061 - // "d", 2062 - // "M139.00148,7254.975 L140,7257.827 C139.622944,7258.358 137.91209,7258.973 136.376708,7258.998 C131.82592,7259.073 130.088955,7255.895 130.088955,7253.657 L130.088955,7247 L128,7247 L128,7244.539 C131.169989,7243.445 131.931413,7240.708 132.110018,7239.149 C132.122552,7239.042 132.210288,7239 132.261467,7239 L135.311341,7239 L135.311341,7244 L139.489251,7244 L139.489251,7247 L135.311341,7247 L135.311341,7253.349 C135.311341,7254.195 135.646619,7255.363 137.318827,7255.32 C137.873444,7255.307 138.612934,7255.152 139.00148,7254.975", 2063 - // ), 2064 - // ]), 2065 - // ], 2066 - // ), 2067 - // ], 2068 - // ), 2069 - // ], 2070 - // ), 2071 - // ], 2072 - // ), 2073 - // ], 2074 - // ), 2075 - // Twitter =================================================================================== 2076 - // html.a( 2077 - // [ 2078 - // attribute.target("_blank"), 2079 - // attribute.href("https://x.com/strawmelonjuice"), 2080 - // ], 2081 - // [ 2082 - // svg.svg( 2083 - // [ 2084 - // attribute("fill", "currentColor"), 2085 - // attribute("viewBox", "0 0 24 24"), 2086 - // attribute("height", "24"), 2087 - // attribute("width", "24"), 2088 - // attribute("xmlns", "http://www.w3.org/2000/svg"), 2089 - // ], 2090 - // [ 2091 - // svg.path([ 2092 - // attribute( 2093 - // "d", 2094 - // "M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z", 2095 - // ), 2096 - // ]), 2097 - // ], 2098 - // ), 2099 - // ], 2100 - // ), 2101 - ]) 2102 - } 2103 - 2104 1590 fn view_index(model: Model) -> List(Element(Msg)) { 2105 1591 [ 2106 1592 title("Welcome to my fruity little corner of the web"), ··· 2190 1676 ), 2191 1677 ], 2192 1678 [ 2193 - svg.svg( 2194 - [ 2195 - attribute("xmlns", "http://www.w3.org/2000/svg"), 2196 - attribute("viewBox", "0 0 10 10"), 2197 - attribute("version", "1.1"), 2198 - attribute.class("size-[1.2em] p-0 m-1"), 2199 - ], 2200 - [ 2201 - svg.g( 2202 - [ 2203 - attribute("fill-rule", "evenodd"), 2204 - attribute("fill", "none"), 2205 - ], 2206 - [ 2207 - svg.g( 2208 - [ 2209 - attribute("fill", "currentColor"), 2210 - attribute("transform", "translate(-65 -3644)"), 2211 - attribute.id("a"), 2212 - ], 2213 - [ 2214 - svg.g( 2215 - [ 2216 - attribute("transform", "translate(56 160)"), 2217 - attribute.id("b"), 2218 - ], 2219 - [ 2220 - svg.path([ 2221 - attribute( 2222 - "d", 2223 - "m9.01 3492v1c0 .553.45 1 1 1h1c0-1.11-.899-2-2.01-2m-.0141-4.01v2c2.22 0 4.02 2.05 4.02 4.05h2.01c0-3.01-2.7-6.06-6.03-6.06m9.99 4.91c.0663.598-.402 1.15-1 1.15h-.942c0-4.01-4.03-8.06-8.05-8.06v-.94c0-.601.536-1.06 1.13-.991 4.65.518 8.34 4.21 8.86 8.85", 2224 - ), 2225 - attribute.id("c"), 2226 - ]), 2227 - ], 2228 - ), 2229 - ], 2230 - ), 2231 - ], 2232 - ), 2233 - ], 2234 - ), 1679 + html.img([ 1680 + attribute.class("size-[1.2em] p-0 m-1"), 1681 + attribute.src("/svg/feed.svg"), 1682 + ]), 2235 1683 ], 2236 1684 ), 2237 1685 ]), ··· 2291 1739 PostsWithTag(".creative") -> { 2292 1740 [ 2293 1741 title("Creative works"), 2294 - html.p([], [link(Posts, "<- See all posts instead")]), 1742 + html.p([], [ 1743 + link(Posts, "<- See all posts instead"), 1744 + ]), 2295 1745 ] 2296 1746 |> element.fragment 2297 1747 } 2298 1748 PostsWithTag(".blog-personal") -> { 2299 1749 [ 2300 1750 title("Personal blog posts"), 2301 - html.p([], [link(Posts, "<- See all posts instead")]), 1751 + html.p([], [ 1752 + link(Posts, "<- See all posts instead"), 1753 + ]), 2302 1754 ] 2303 1755 |> element.fragment 2304 1756 } 2305 1757 PostsWithTag(".creative-art") -> { 2306 1758 [ 2307 1759 title("Drawings and scribbles"), 2308 - html.p([], [link(Posts, "<- See all posts instead")]), 1760 + html.p([], [ 1761 + link(Posts, "<- See all posts instead"), 1762 + ]), 2309 1763 ] 2310 1764 |> element.fragment 2311 1765 } 2312 1766 PostsWithTag(".creative-writings") -> { 2313 1767 [ 2314 1768 title("Stories"), 2315 - html.p([], [link(Posts, "<- See all posts instead")]), 1769 + html.p([], [ 1770 + link(Posts, "<- See all posts instead"), 1771 + ]), 2316 1772 ] 2317 1773 |> element.fragment 2318 1774 } 2319 1775 PostsWithTag(tag) -> 2320 1776 [ 2321 1777 title("Posts with tag: " <> tag |> string.replace("_", " ")), 2322 - html.p([], [link(Posts, "<- See all posts instead")]), 1778 + html.p([], [ 1779 + link(Posts, "<- See all posts instead"), 1780 + ]), 2323 1781 ] 2324 1782 |> element.fragment 2325 1783 }, ··· 2365 1823 2366 1824 fn view_post(model: Model, post_id: Int) -> List(Element(Msg)) { 2367 1825 case dict.get(model.posts, post_id) { 2368 - Error(_) -> view_not_found() 1826 + Error(_) -> not_found.view() 2369 1827 Ok(post) -> [ 2370 1828 html.article([attribute.class(" bg-[#FAEBEB]")], [ 2371 1829 html.p( ··· 2592 2050 ) 2593 2051 } 2594 2052 2595 - fn codeforges_links() -> Element(Msg) { 2596 - [ 2597 - html.div( 2598 - [attribute.class("flex flex-wrap justify-center gap-4")], 2599 - [ 2600 - html.a( 2601 - [ 2602 - attribute.class( 2603 - "flex items-center justify-center p-4 w-28 md:w-64 bg-[#ff6f91] hover:bg-[#ff4f78] rounded-xl shadow-lg transition-all border-[#ff6f91] border-2 border-solid", 2604 - ), 2605 - attribute.target("_blank"), 2606 - attribute.href("https://github.com/strawmelonjuice"), 2607 - ], 2608 - [ 2609 - html.img([ 2610 - attribute.class("w-full max-h-10 p-1 rounded-sm"), 2611 - attribute.src("/svg/GitHub_Lockup_Black.svg"), 2612 - ]), 2613 - ], 2614 - ), 2615 - html.a( 2616 - [ 2617 - attribute.class( 2618 - "flex items-center justify-center p-4 w-28 md:w-64 bg-white hover:bg-[#ff4f78] rounded-xl shadow-lg transition-all border-[#ff6f91] border-2 border-solid", 2619 - ), 2620 - attribute.target("_blank"), 2621 - attribute.href("https://codeberg.org/strawmelonjuice"), 2622 - ], 2623 - [ 2624 - html.img([ 2625 - attribute.class("w-full max-h-10 p-1 rounded-sm"), 2626 - attribute.src( 2627 - "https://codeberg.org/Codeberg/Design/raw/branch/main/logo/horizontal/svg/codeberg-logo_horizontal_blue.svg", 2628 - ), 2629 - attribute.alt("Codeberg"), 2630 - ]), 2631 - ], 2632 - ), 2633 - html.a( 2634 - [ 2635 - attribute.class( 2636 - "flex items-center justify-center p-2 w-28 md:w-64 bg-white hover:bg-[#ff4f78] rounded-xl shadow-lg transition-all border-[#ff6f91] border-2 border-solid", 2637 - ), 2638 - attribute.target("_blank"), 2639 - attribute.href("https://forge.strawmelonjuice.com/strawmelonjuice"), 2640 - ], 2641 - [ 2642 - html.img([ 2643 - attribute.class("w-full max-h-10 p-1 rounded-sm"), 2644 - attribute.src("https://forgejo.org/images/forgejo-wordmark.svg"), 2645 - attribute.alt("Forgejo"), 2646 - ]), 2647 - ], 2648 - ), 2649 - html.a( 2650 - [ 2651 - attribute.class( 2652 - "flex items-center justify-center gap-3 p-4 w-28 md:w-64 bg-[#ff6f91] text-white hover:bg-[#ff4f78] rounded-xl shadow-lg transition-all border-[#ff6f91] border-2 border-solid", 2653 - ), 2654 - attribute.target("_blank"), 2655 - attribute.href("https://tangled.org/strawmelonjuice.com/"), 2656 - ], 2657 - [ 2658 - html.img([ 2659 - attribute.class("h-10"), 2660 - attribute.src("/svg/dolly.svg"), 2661 - ]), 2662 - html.span([attribute.class("font-bold text-xl hidden md:inline")], [ 2663 - html.text("tangled"), 2664 - ]), 2665 - ], 2666 - ), 2667 - ] 2668 - |> list.shuffle, 2669 - ), 2670 - ] 2671 - |> element.fragment 2672 - } 2673 - 2674 - fn view_not_found() -> List(Element(Msg)) { 2675 - let first = 2676 - "You glimpse into the void and see -- nothing? 2677 - Well that was somewhat expected." 2678 - [ 2679 - title("Not found"), 2680 - paragraph( 2681 - case 2682 - [ 2683 - first, 2684 - "You've wandered off the map. There are no monsters here, just an endless, pixelated silence.", 2685 - "This page has achieved enlightenment and transcended the physical server. It no longer exists in this dimension.", 2686 - "Error 404: The digital equivalent of walking into a room and forgetting why you came here.", 2687 - "Everything you see here is a hallucination. Especially this 404 page.", 2688 - "You reached the end of the internet. Please turn around and head back the way you came.", 2689 - "404: A quiet space for reflection. Or just a broken link. Mostly the broken link thing.", 2690 - "Lost in the sauce? This page certainly is.", 2691 - "Nothing to see here. Move along, citizen.", 2692 - "You picked a bad time to get lost, friend!", 2693 - "This page is currently 'Works on my machine'—but apparently not on yours.", 2694 - "A 404 error has occurred. Please pet your nearest cat and try again.", 2695 - "You took a wrong turn at the last hyperlink. Care for a juice box while you find your way back?", 2696 - "Oh no! The pixels for this page haven't been delivered yet. The digital mail is running late.", 2697 - "You found a secret area! Unfortunately, the secret is that there’s nothing here.", 2698 - "Error 404: The hamsters powering this specific page are currently on their lunch break.", 2699 - "404: Under Construction... indefinitely. (Just kidding, it's just gone.)", 2700 - "This URL did not exist. Please refresh your browser or your outlook on life.", 2701 - "Nope, not here!", 2702 - ] 2703 - |> list.shuffle() 2704 - |> list.first() 2705 - { 2706 - Error(_) -> first 2707 - Ok(r) -> r 2708 - }, 2709 - ), 2710 - ] 2711 - } 2712 - 2713 2053 pub fn date_to_yyyy_mm_dd(date: calendar.Date) -> String { 2714 2054 let Date(year, month, day) = date 2715 2055 int.to_string(year) ··· 2734 2074 <> int.to_string(day) |> string.pad_start(with: "0", to: 2) 2735 2075 } 2736 2076 2737 - // Reusable non-component components ======================================================================== 2738 - 2739 - fn title(title: String) -> Element(Msg) { 2740 - html.h2([attribute.class("text-3xl text-accent-content font-light")], [ 2741 - html.text(title), 2742 - ]) 2743 - } 2744 - 2745 - fn subtitle(subtitle: String) -> Element(Msg) { 2746 - html.h3([attribute.class("text-xl text-accent font-light")], [ 2747 - html.text(subtitle), 2748 - ]) 2749 - } 2750 - 2751 - fn subsubtitle(subsubtitle: String) -> Element(Msg) { 2752 - html.h4([attribute.class("text-lg mt-5 mb-3 text-accent font-light")], [ 2753 - html.text(subsubtitle), 2754 - ]) 2755 - } 2077 + // Wrapper functions 2756 2078 2757 - fn leading(text: String) -> Element(Msg) { 2758 - html.p([attribute.class("mt-0 text-lg")], [html.text(text)]) 2079 + /// Convenience wrapper, public for use by prepare, other modules will have to 2080 + /// make these wrappers function-scoped or just call stuff's version directly 2081 + /// and supply posts. 2082 + pub fn to_url(m: Route) -> String { 2083 + stuff.to_url(m, posts()) 2759 2084 } 2760 2085 2761 - fn paragraph(text: String) -> Element(Msg) { 2762 - html.p([attribute.class("mt-6")], [html.text(text)]) 2086 + /// Convenience wrapper around href, so I don't need to call posts() every time 2087 + fn href(m: Route) -> Attribute(Msg) { 2088 + stuff.href(m, posts()) 2763 2089 } 2764 2090 2765 - fn link(target: Route, title: String) -> Element(Msg) { 2766 - html.a( 2767 - [ 2768 - href(target), 2769 - attribute.class("link link-accent"), 2770 - ], 2771 - [html.text(title)], 2772 - ) 2091 + /// Convenience wrapper, public for use by prepare, other modules will have to 2092 + /// make these wrappers function-scoped or just call stuff's version directly 2093 + /// and supply posts. 2094 + pub fn link(target: Route, title: String) -> Element(Msg) { 2095 + prestyled_elements.link(target, title, href) 2773 2096 }
+151
src/homepage/stuff.gleam
··· 1 + // Imports 2 + import gleam/dict.{type Dict} 3 + import gleam/int 4 + import gleam/list 5 + import gleam/option.{type Option} 6 + import gleam/time/calendar 7 + import gleam/uri.{type Uri} 8 + import lustre/attribute.{type Attribute} 9 + import lustre/element.{type Element as LustreElement} 10 + 11 + // Some types for your consideration 12 + 13 + pub type Element = 14 + LustreElement(Msg) 15 + 16 + pub type Entry { 17 + Entry(route: Route, title: String, last_updated: calendar.Date, parent: Route) 18 + } 19 + 20 + pub type FeedEntry { 21 + FeedEntry( 22 + /// Id, used to determine permalink. 23 + id: Int, 24 + /// Description 25 + description: String, 26 + entry: Entry, 27 + ) 28 + } 29 + 30 + pub type Badge { 31 + Badge( 32 + clickable_url: String, 33 + img_url: String, 34 + img_alt: String, 35 + img_title: String, 36 + text_badge: String, 37 + ) 38 + } 39 + 40 + pub type Model { 41 + Model( 42 + raw_posts: List(Post), 43 + posts: Dict(Int, NormalizedPost), 44 + aliases: Dict(String, Int), 45 + route: Route, 46 + ) 47 + } 48 + 49 + pub type Post { 50 + Post( 51 + id: Int, 52 + category: String, 53 + title: String, 54 + summary: String, 55 + published: calendar.Date, 56 + revised: Option(calendar.Date), 57 + body: Body, 58 + tags: List(String), 59 + aliases: List(String), 60 + comments: MastodonComments, 61 + ) 62 + } 63 + 64 + pub type MastodonComments { 65 + /// example https://[pony.social]/@strawmelonjuice/[115911235653686237]. 66 + MastodonStatusLink(instance: String, id: String) 67 + CommentsDisable 68 + } 69 + 70 + pub type NormalizedPost { 71 + NormalizedPost( 72 + id: Int, 73 + category: String, 74 + title: String, 75 + published: calendar.Date, 76 + revised: Option(calendar.Date), 77 + summary: String, 78 + body: Element, 79 + tags: List(String), 80 + comments: MastodonComments, 81 + ) 82 + } 83 + 84 + pub type Body { 85 + Lustre(Element) 86 + File(markup: Markup, path: String) 87 + Inline(markup: Markup, string: String) 88 + } 89 + 90 + pub type Markup { 91 + Djot 92 + Plain 93 + HTML 94 + } 95 + 96 + pub type Msg { 97 + UserNavigatedTo(route: Route) 98 + } 99 + 100 + pub type Route { 101 + Index 102 + Posts 103 + PostById(id: Int) 104 + Me 105 + Portfolio 106 + NotFound(uri: Uri) 107 + AllAndEverything 108 + Sitemap 109 + Category(String) 110 + Tagged(String) 111 + Links 112 + PersonalStartPage 113 + CuriculumVitae(in_dutch: Bool) 114 + } 115 + 116 + pub fn href(route: Route, posts: List(Post)) -> Attribute(Msg) { 117 + attribute.href(to_url(route, posts)) 118 + } 119 + 120 + pub fn to_url(route: Route, posts: List(Post)) -> String { 121 + case route { 122 + Index -> "/" 123 + Me -> "/me" 124 + Posts -> "/posts" 125 + PostById(post_id) -> { 126 + let slug = { 127 + let m = list.find(posts, fn(p) { p.id == post_id }) 128 + case m { 129 + Error(Nil) -> int.to_string(post_id) 130 + Ok(p) -> { 131 + case p.aliases { 132 + [] -> int.to_string(post_id) 133 + [alias, ..] -> alias 134 + } 135 + } 136 + } 137 + } 138 + "/post/" <> slug 139 + } 140 + Portfolio -> "/me/portfolio" 141 + Links -> "/me/links" 142 + AllAndEverything -> "/everything" 143 + PersonalStartPage -> "/startpage" 144 + NotFound(_) -> "/404" 145 + Tagged(v) -> "/posts/tagged/" <> v 146 + Category(c) -> "/posts/category/" <> c 147 + Sitemap -> "/sitemap" 148 + CuriculumVitae(False) -> "/cv/en" 149 + CuriculumVitae(True) -> "/cv/nl" 150 + } 151 + }
+438
src/homepage/stuff/prestyled_elements.gleam
··· 1 + import gleam/list 2 + import homepage/stuff.{type Msg, type Route} 3 + import lustre/attribute.{attribute} 4 + import lustre/element.{type Element} 5 + import lustre/element/html 6 + import lustre/element/svg 7 + 8 + // Reusable non-component components ======================================================================== 9 + 10 + pub fn title(title: String) -> Element(Msg) { 11 + html.h2([attribute.class("text-3xl text-accent-content font-light")], [ 12 + html.text(title), 13 + ]) 14 + } 15 + 16 + pub fn subtitle(subtitle: String) -> Element(Msg) { 17 + html.h3([attribute.class("text-xl text-accent font-light")], [ 18 + html.text(subtitle), 19 + ]) 20 + } 21 + 22 + pub fn subsubtitle(subsubtitle: String) -> Element(Msg) { 23 + html.h4([attribute.class("text-lg mt-5 mb-3 text-accent font-light")], [ 24 + html.text(subsubtitle), 25 + ]) 26 + } 27 + 28 + pub fn leading(text: String) -> Element(Msg) { 29 + html.p([attribute.class("mt-0 text-lg")], [html.text(text)]) 30 + } 31 + 32 + pub fn paragraph(text: String) -> Element(Msg) { 33 + html.p([attribute.class("mt-6")], [html.text(text)]) 34 + } 35 + 36 + pub fn link( 37 + target: Route, 38 + title: String, 39 + href: fn(Route) -> attribute.Attribute(Msg), 40 + ) -> Element(Msg) { 41 + html.a( 42 + [ 43 + href(target), 44 + attribute.class("link link-accent"), 45 + ], 46 + [html.text(title)], 47 + ) 48 + } 49 + 50 + pub fn codeforges_links() -> Element(Msg) { 51 + [ 52 + html.div( 53 + [attribute.class("flex flex-wrap justify-center gap-4")], 54 + [ 55 + html.a( 56 + [ 57 + attribute.class( 58 + "flex items-center justify-center p-4 w-28 md:w-64 bg-[#ff6f91] hover:bg-[#ff4f78] rounded-xl shadow-lg transition-all border-[#ff6f91] border-2 border-solid", 59 + ), 60 + attribute.target("_blank"), 61 + attribute.href("https://github.com/strawmelonjuice"), 62 + ], 63 + [ 64 + html.img([ 65 + attribute.class("w-full max-h-10 p-1 rounded-sm"), 66 + attribute.src("/svg/GitHub_Lockup_Black.svg"), 67 + ]), 68 + ], 69 + ), 70 + html.a( 71 + [ 72 + attribute.class( 73 + "flex items-center justify-center p-4 w-28 md:w-64 bg-white hover:bg-[#ff4f78] rounded-xl shadow-lg transition-all border-[#ff6f91] border-2 border-solid", 74 + ), 75 + attribute.target("_blank"), 76 + attribute.href("https://codeberg.org/strawmelonjuice"), 77 + ], 78 + [ 79 + html.img([ 80 + attribute.class("w-full max-h-10 p-1 rounded-sm"), 81 + attribute.src( 82 + "https://codeberg.org/Codeberg/Design/raw/branch/main/logo/horizontal/svg/codeberg-logo_horizontal_blue.svg", 83 + ), 84 + attribute.alt("Codeberg"), 85 + ]), 86 + ], 87 + ), 88 + html.a( 89 + [ 90 + attribute.class( 91 + "flex items-center justify-center p-2 w-28 md:w-64 bg-white hover:bg-[#ff4f78] rounded-xl shadow-lg transition-all border-[#ff6f91] border-2 border-solid", 92 + ), 93 + attribute.target("_blank"), 94 + attribute.href("https://forge.strawmelonjuice.com/strawmelonjuice"), 95 + ], 96 + [ 97 + html.img([ 98 + attribute.class("w-full max-h-10 p-1 rounded-sm"), 99 + attribute.src("https://forgejo.org/images/forgejo-wordmark.svg"), 100 + attribute.alt("Forgejo"), 101 + ]), 102 + ], 103 + ), 104 + html.a( 105 + [ 106 + attribute.class( 107 + "flex items-center justify-center gap-3 p-4 w-28 md:w-64 bg-[#ff6f91] text-white hover:bg-[#ff4f78] rounded-xl shadow-lg transition-all border-[#ff6f91] border-2 border-solid", 108 + ), 109 + attribute.target("_blank"), 110 + attribute.href("https://tangled.org/strawmelonjuice.com/"), 111 + ], 112 + [ 113 + html.img([ 114 + attribute.class("h-10"), 115 + attribute.src("/svg/dolly.svg"), 116 + ]), 117 + html.span([attribute.class("font-bold text-xl hidden md:inline")], [ 118 + html.text("tangled"), 119 + ]), 120 + ], 121 + ), 122 + ] 123 + |> list.shuffle, 124 + ), 125 + ] 126 + |> element.fragment 127 + } 128 + 129 + pub fn socials(collapsible small: Bool) -> Element(Msg) { 130 + html.div([attribute.class("grid grid-flow-col gap-4")], [ 131 + // Mastodon ================================================================================= 132 + html.a( 133 + [ 134 + attribute.target("_blank"), 135 + attribute.href("https://pony.social/@strawmelonjuice"), 136 + attribute.class("cursor-pointer w-[26px] h-[26px] hover:text-[#5638cc]"), 137 + attribute.classes([#("hidden md:block", small)]), 138 + ], 139 + [ 140 + svg.svg( 141 + [ 142 + attribute("xmlns", "http://www.w3.org/2000/svg"), 143 + attribute("fill", "currentColor"), 144 + attribute("viewBox", "0 0 74 79"), 145 + attribute("height", "24"), 146 + attribute("width", "24"), 147 + ], 148 + [ 149 + svg.path([ 150 + attribute("fill", "inherit"), 151 + attribute( 152 + "d", 153 + "M73.7014 17.9592C72.5616 9.62034 65.1774 3.04876 56.424 1.77536C54.9472 1.56019 49.3517 0.7771 36.3901 0.7771H36.2933C23.3281 0.7771 20.5465 1.56019 19.0697 1.77536C10.56 3.01348 2.78877 8.91838 0.903306 17.356C-0.00357857 21.5113 -0.100361 26.1181 0.068112 30.3439C0.308275 36.404 0.354874 42.4535 0.91406 48.489C1.30064 52.498 1.97502 56.4751 2.93215 60.3905C4.72441 67.6217 11.9795 73.6395 19.0876 76.0945C26.6979 78.6548 34.8821 79.0799 42.724 77.3221C43.5866 77.1245 44.4398 76.8953 45.2833 76.6342C47.1867 76.0381 49.4199 75.3714 51.0616 74.2003C51.0841 74.1839 51.1026 74.1627 51.1156 74.1382C51.1286 74.1138 51.1359 74.0868 51.1368 74.0592V68.2108C51.1364 68.185 51.1302 68.1596 51.1185 68.1365C51.1069 68.1134 51.0902 68.0932 51.0695 68.0773C51.0489 68.0614 51.0249 68.0503 50.9994 68.0447C50.9738 68.0391 50.9473 68.0392 50.9218 68.045C45.8976 69.226 40.7491 69.818 35.5836 69.8087C26.694 69.8087 24.3031 65.6569 23.6184 63.9285C23.0681 62.4347 22.7186 60.8764 22.5789 59.2934C22.5775 59.2669 22.5825 59.2403 22.5934 59.216C22.6043 59.1916 22.621 59.1702 22.6419 59.1533C22.6629 59.1365 22.6876 59.1248 22.714 59.1191C22.7404 59.1134 22.7678 59.1139 22.794 59.1206C27.7345 60.2936 32.799 60.8856 37.8813 60.8843C39.1036 60.8843 40.3223 60.8843 41.5447 60.8526C46.6562 60.7115 52.0437 60.454 57.0728 59.4874C57.1983 59.4628 57.3237 59.4416 57.4313 59.4098C65.3638 57.9107 72.9128 53.2051 73.6799 41.2895C73.7086 40.8204 73.7803 36.3758 73.7803 35.889C73.7839 34.2347 74.3216 24.1533 73.7014 17.9592ZM61.4925 47.6918H53.1514V27.5855C53.1514 23.3526 51.3591 21.1938 47.7136 21.1938C43.7061 21.1938 41.6988 23.7476 41.6988 28.7919V39.7974H33.4078V28.7919C33.4078 23.7476 31.3969 21.1938 27.3894 21.1938C23.7654 21.1938 21.9552 23.3526 21.9516 27.5855V47.6918H13.6176V26.9752C13.6176 22.7423 14.7157 19.3795 16.9118 16.8868C19.1772 14.4 22.1488 13.1231 25.8373 13.1231C30.1064 13.1231 33.3325 14.7386 35.4832 17.9662L37.5587 21.3949L39.6377 17.9662C41.7884 14.7386 45.0145 13.1231 49.2765 13.1231C52.9614 13.1231 55.9329 14.4 58.2055 16.8868C60.4017 19.3772 61.4997 22.74 61.4997 26.9752L61.4925 47.6918Z", 154 + ), 155 + ]), 156 + ], 157 + ), 158 + ], 159 + ), 160 + 161 + // Instagram ================================================================================= 162 + // html.a( 163 + // [ 164 + // attribute.target("_blank"), 165 + // attribute.href("https://instagram.com/strawmelonjuice"), 166 + // attribute.class("cursor-pointer"), 167 + // ], 168 + // [ 169 + // svg.svg( 170 + // [ 171 + // attribute("xmlns:xlink", "http://www.w3.org/1999/xlink"), 172 + // attribute("xmlns", "http://www.w3.org/2000/svg"), 173 + // attribute("version", "1.1"), 174 + // attribute("viewBox", "0 0 20 20"), 175 + // attribute("height", "24"), 176 + // attribute("width", "24"), 177 + // ], 178 + // [ 179 + // svg.g( 180 + // [ 181 + // attribute("fill-rule", "evenodd"), 182 + // attribute("fill", "none"), 183 + // attribute("stroke-width", "1"), 184 + // attribute("stroke", "none"), 185 + // attribute.id("Page-1"), 186 + // ], 187 + // [ 188 + // svg.g( 189 + // [ 190 + // attribute("fill", "currentColor"), 191 + // attribute( 192 + // "transform", 193 + // "translate(-340.000000, -7439.000000)", 194 + // ), 195 + // attribute.id("Dribbble-Light-Preview"), 196 + // ], 197 + // [ 198 + // svg.g( 199 + // [ 200 + // attribute( 201 + // "transform", 202 + // "translate(56.000000, 160.000000)", 203 + // ), 204 + // attribute.id("icons"), 205 + // ], 206 + // [ 207 + // svg.path([ 208 + // attribute.id("instagram-[#167]"), 209 + // attribute( 210 + // "d", 211 + // "M289.869652,7279.12273 C288.241769,7279.19618 286.830805,7279.5942 285.691486,7280.72871 C284.548187,7281.86918 284.155147,7283.28558 284.081514,7284.89653 C284.035742,7285.90201 283.768077,7293.49818 284.544207,7295.49028 C285.067597,7296.83422 286.098457,7297.86749 287.454694,7298.39256 C288.087538,7298.63872 288.809936,7298.80547 289.869652,7298.85411 C298.730467,7299.25511 302.015089,7299.03674 303.400182,7295.49028 C303.645956,7294.859 303.815113,7294.1374 303.86188,7293.08031 C304.26686,7284.19677 303.796207,7282.27117 302.251908,7280.72871 C301.027016,7279.50685 299.5862,7278.67508 289.869652,7279.12273 M289.951245,7297.06748 C288.981083,7297.0238 288.454707,7296.86201 288.103459,7296.72603 C287.219865,7296.3826 286.556174,7295.72155 286.214876,7294.84312 C285.623823,7293.32944 285.819846,7286.14023 285.872583,7284.97693 C285.924325,7283.83745 286.155174,7282.79624 286.959165,7281.99226 C287.954203,7280.99968 289.239792,7280.51332 297.993144,7280.90837 C299.135448,7280.95998 300.179243,7281.19026 300.985224,7281.99226 C301.980262,7282.98483 302.473801,7284.28014 302.071806,7292.99991 C302.028024,7293.96767 301.865833,7294.49274 301.729513,7294.84312 C300.829003,7297.15085 298.757333,7297.47145 289.951245,7297.06748 M298.089663,7283.68956 C298.089663,7284.34665 298.623998,7284.88065 299.283709,7284.88065 C299.943419,7284.88065 300.47875,7284.34665 300.47875,7283.68956 C300.47875,7283.03248 299.943419,7282.49847 299.283709,7282.49847 C298.623998,7282.49847 298.089663,7283.03248 298.089663,7283.68956 M288.862673,7288.98792 C288.862673,7291.80286 291.150266,7294.08479 293.972194,7294.08479 C296.794123,7294.08479 299.081716,7291.80286 299.081716,7288.98792 C299.081716,7286.17298 296.794123,7283.89205 293.972194,7283.89205 C291.150266,7283.89205 288.862673,7286.17298 288.862673,7288.98792 M290.655732,7288.98792 C290.655732,7287.16159 292.140329,7285.67967 293.972194,7285.67967 C295.80406,7285.67967 297.288657,7287.16159 297.288657,7288.98792 C297.288657,7290.81525 295.80406,7292.29716 293.972194,7292.29716 C292.140329,7292.29716 290.655732,7290.81525 290.655732,7288.98792", 212 + // ), 213 + // ]), 214 + // ], 215 + // ), 216 + // ], 217 + // ), 218 + // ], 219 + // ), 220 + // ], 221 + // ), 222 + // ], 223 + // ), 224 + // 225 + // Matrix ================================================================================= 226 + html.a( 227 + [ 228 + attribute.target("_blank"), 229 + attribute.href("https://matrix.to/#/@mar:strawmelonjuice.com"), 230 + attribute.class( 231 + "cursor-pointer w-[26px] h-[26px] hover:text-black hover:bg-white", 232 + ), 233 + ], 234 + [ 235 + svg.svg( 236 + [ 237 + attribute("xmlns", "http://www.w3.org/2000/svg"), 238 + attribute("xml:space", "preserve"), 239 + attribute("viewBox", "0 0 26 26"), 240 + attribute("version", "1.1"), 241 + attribute("height", "26"), 242 + attribute("width", "26"), 243 + ], 244 + [ 245 + svg.g( 246 + [ 247 + attribute("stroke-width", ".05"), 248 + attribute("fill", "currentColor"), 249 + ], 250 + [ 251 + svg.path([ 252 + attribute( 253 + "d", 254 + "m0.685 0.595v24.81h1.785v0.59499h-2.47v-26h2.47v0.595z", 255 + ), 256 + ]), 257 + svg.path([ 258 + attribute( 259 + "d", 260 + "m8.315 8.46v1.255h0.035007c0.33499-0.48 0.73999-0.85 1.21-1.11 0.47-0.265 1.015-0.395 1.625-0.395 0.585 0 1.12 0.115 1.605 0.34 0.48501 0.225 0.85001 0.63 1.105 1.2 0.275-0.405 0.65-0.765 1.12-1.075 0.47001-0.31 1.03-0.465 1.675-0.465 0.49001 0 0.94501 0.060005 1.365 0.18 0.42001 0.12 0.775 0.31 1.075 0.575 0.3 0.265 0.52999 0.605 0.69999 1.03 0.16501 0.425 0.25001 0.935 0.25001 1.535v6.205h-2.545v-5.255c0-0.31-0.0093-0.605-0.03492-0.88001-0.02507-0.27499-0.09007-0.51499-0.19506-0.71499-0.11002-0.205-0.26503-0.365-0.47502-0.485-0.21-0.12-0.495-0.18-0.85-0.18-0.36001 0-0.65 0.06999-0.87002 0.205-0.22 0.14-0.395 0.315-0.52 0.54-0.12498 0.22-0.20999 0.47-0.24999 0.755-0.03993 0.28-0.065 0.565-0.065 0.85v5.165h-2.545v-5.2c0-0.275-0.0047-0.54501-0.02005-0.81501-0.0099-0.27-0.06498-0.515-0.15497-0.745-0.08994-0.225-0.23997-0.41-0.44996-0.545-0.21-0.135-0.515-0.205-0.925-0.205-0.12 0-0.28 0.02497-0.475 0.08-0.195 0.05501-0.39 0.155-0.575 0.305-0.185 0.15-0.345 0.365-0.475 0.645-0.13 0.28-0.195 0.65-0.195 1.105v5.38h-2.545v-9.28z", 261 + ), 262 + ]), 263 + svg.path([ 264 + attribute( 265 + "d", 266 + "m25.315 25.405v-24.81h-1.785v-0.595h2.47v26h-2.47v-0.59499z", 267 + ), 268 + ]), 269 + ], 270 + ), 271 + ], 272 + ), 273 + ], 274 + ), 275 + // Email ================================================================================== 276 + html.a( 277 + [ 278 + attribute.target("_blank"), 279 + attribute.href("mailto:web@strawmelonjuice.com"), 280 + attribute.class("cursor-pointer w-[26px] h-[26px] hover:text-[#cc3856]"), 281 + ], 282 + [ 283 + svg.svg( 284 + [ 285 + attribute("xmlns", "http://www.w3.org/2000/svg"), 286 + 287 + attribute("viewBox", "0 0 .72 .72"), 288 + 289 + attribute("version", "1.1"), 290 + 291 + attribute("fill", "none"), 292 + 293 + attribute("height", "24"), 294 + 295 + attribute("width", "24"), 296 + ], 297 + [ 298 + svg.path([ 299 + attribute("stroke-width", ".072"), 300 + 301 + attribute("stroke-linejoin", "round"), 302 + 303 + attribute("stroke-linecap", "round"), 304 + 305 + attribute("stroke", "currentColor"), 306 + 307 + attribute( 308 + "d", 309 + "m0.074646 0.1641 0.24984 0.15615c0.023346 0.014591 0.052974 0.014591 0.07632 0l0.24984-0.15615m-0.54 0.396h0.504c0.039766 0 0.072-0.032234 0.072-0.072v-0.288c0-0.039764-0.032234-0.072-0.072-0.072h-0.504c-0.039764 0-0.072 0.032236-0.072 0.072v0.288c0 0.039766 0.032236 0.072 0.072 0.072z", 310 + ), 311 + ]), 312 + ], 313 + ), 314 + ], 315 + ), 316 + // Bluesky ================================================================================ 317 + html.a( 318 + [ 319 + attribute.target("_blank"), 320 + attribute.href( 321 + "https://witchsky.app/profile/did:plc:jgtfsmv25thfs4zmydtbccnn", 322 + ), 323 + attribute.class("cursor-pointer w-[26px] h-[26px] hover:text-[#006aff]"), 324 + attribute.classes([#("hidden md:block", small)]), 325 + ], 326 + [ 327 + svg.svg( 328 + [ 329 + attribute("xmlns", "http://www.w3.org/2000/svg"), 330 + attribute("viewBox", "0 0 48 24"), 331 + attribute("version", "1.1"), 332 + attribute("fill", "none"), 333 + attribute("height", "24"), 334 + attribute("width", "24"), 335 + ], 336 + [ 337 + svg.path([ 338 + attribute("stroke-width", ".65268"), 339 + attribute("fill", "currentColor"), 340 + attribute( 341 + "d", 342 + "m12.083-4.7208c4.7887 3.6074 9.9404 10.921 11.831 14.845v10.366c0-0.22061-0.08485 0.02872-0.2676 0.56588-0.98686 2.9084-4.8416 14.259-13.656 5.1849-4.6412-4.7776-2.4926-9.5553 5.9557-10.998-4.8331 0.82499-10.267-0.53846-11.757-5.8839-0.42947-1.5377-1.1605-11.009-1.1605-12.289 0-6.408 5.5994-4.3939 9.0547-1.7916zm23.662 0c-4.7887 3.6074-9.9404 10.921-11.831 14.845v10.366c0-0.22061 0.08485 0.02872 0.2676 0.56588 0.98686 2.9084 4.8416 14.259 13.656 5.1849 4.6412-4.7776 2.4926-9.5553-5.9557-10.998 4.8331 0.82499 10.267-0.53846 11.757-5.8839 0.42946-1.5377 1.1605-11.009 1.1605-12.289 0-6.408-5.5987-4.3939-9.0547-1.7916z", 343 + ), 344 + ]), 345 + ], 346 + ), 347 + ], 348 + ), 349 + // Tumblr ================================================================================= 350 + // html.a( 351 + // [ 352 + // attribute.target("_blank"), 353 + // attribute.href("https://tumblr.com/strawmelonjuice"), 354 + // ], 355 + // [ 356 + // svg.svg( 357 + // [ 358 + // attribute("xmlns:xlink", "http://www.w3.org/1999/xlink"), 359 + // attribute("xmlns", "http://www.w3.org/2000/svg"), 360 + // attribute("version", "1.1"), 361 + // attribute("viewBox", "-4 0 20 20"), 362 + // attribute("height", "24"), 363 + // attribute("width", "24"), 364 + // ], 365 + // [ 366 + // svg.g( 367 + // [ 368 + // attribute("fill-rule", "evenodd"), 369 + // attribute("fill", "none"), 370 + // attribute("stroke-width", "1"), 371 + // attribute("stroke", "none"), 372 + // attribute.id("Page-1"), 373 + // ], 374 + // [ 375 + // svg.g( 376 + // [ 377 + // attribute("fill", "currentColor"), 378 + // attribute( 379 + // "transform", 380 + // "translate(-184.000000, -7399.000000)", 381 + // ), 382 + // attribute.id("Dribbble-Light-Preview"), 383 + // ], 384 + // [ 385 + // svg.g( 386 + // [ 387 + // attribute( 388 + // "transform", 389 + // "translate(56.000000, 160.000000)", 390 + // ), 391 + // attribute.id("icons"), 392 + // ], 393 + // [ 394 + // svg.path([ 395 + // attribute.id("tumblr-[#181]"), 396 + // attribute( 397 + // "d", 398 + // "M139.00148,7254.975 L140,7257.827 C139.622944,7258.358 137.91209,7258.973 136.376708,7258.998 C131.82592,7259.073 130.088955,7255.895 130.088955,7253.657 L130.088955,7247 L128,7247 L128,7244.539 C131.169989,7243.445 131.931413,7240.708 132.110018,7239.149 C132.122552,7239.042 132.210288,7239 132.261467,7239 L135.311341,7239 L135.311341,7244 L139.489251,7244 L139.489251,7247 L135.311341,7247 L135.311341,7253.349 C135.311341,7254.195 135.646619,7255.363 137.318827,7255.32 C137.873444,7255.307 138.612934,7255.152 139.00148,7254.975", 399 + // ), 400 + // ]), 401 + // ], 402 + // ), 403 + // ], 404 + // ), 405 + // ], 406 + // ), 407 + // ], 408 + // ), 409 + // ], 410 + // ), 411 + // Twitter =================================================================================== 412 + // html.a( 413 + // [ 414 + // attribute.target("_blank"), 415 + // attribute.href("https://x.com/strawmelonjuice"), 416 + // ], 417 + // [ 418 + // svg.svg( 419 + // [ 420 + // attribute("fill", "currentColor"), 421 + // attribute("viewBox", "0 0 24 24"), 422 + // attribute("height", "24"), 423 + // attribute("width", "24"), 424 + // attribute("xmlns", "http://www.w3.org/2000/svg"), 425 + // ], 426 + // [ 427 + // svg.path([ 428 + // attribute( 429 + // "d", 430 + // "M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z", 431 + // ), 432 + // ]), 433 + // ], 434 + // ), 435 + // ], 436 + // ), 437 + ]) 438 + }
+237 -185
src/homepage/view/cv.gleam
··· 1 1 import gleam/dict 2 2 import gleam/list 3 + import homepage/stuff.{type Element, type Route} 3 4 import lustre/attribute.{attribute} 4 - import lustre/element.{type Element} 5 + import lustre/element 5 6 import lustre/element/html 6 7 7 - pub fn view(in_dutch: Bool) -> Element(a) { 8 + // #(keyname, #(eng,dut)) 9 + const translations = [ 10 + #("langswitch", #("🇳🇱 NL", "🇬🇧 EN")), 11 + #("header-summary", #("About", "Over")), 12 + #("header-profiles", #("Profiles", "Online")), 13 + #("header-interests", #("Interests", "Interesses")), 14 + #("header-skills", #("Skills", "Vaardigheden")), 15 + #("header-experience", #("Experience", "Ervaring")), 16 + #("subheader-experience-older", #("Earlier", "Eerder")), 17 + #("header-education", #("Education", "Opleidingen")), 18 + #("header-languages", #("Languages", "Talen")), 19 + #("lang-dut", #("Dutch", "Nederlands")), 20 + #("lang-eng", #("English", "Engels")), 21 + #("word-native", #("Native.", "Moedertaal.")), 22 + #( 23 + "cambridge-daily", 24 + #( 25 + "Daily speaker, Cambridge C1 level.", 26 + "Dagelijkse spreker, Cambridge C1 niveau.", 27 + ), 28 + ), 29 + #("date-2/'26", #("February 2026", "Februari 2026")), 30 + #("attribution-1", #("Based on the design from ", "Ontworpen naar ")), 31 + #("attribution-2", #(", delivered in Gleam. ", ", uitgevoerd in Gleam. ")), 32 + #("present", #("Present", "Heden")), 33 + #( 34 + "education-fontys-institute", 35 + #("Fontys University of Applied Sciences", "Fontys Hogeschool"), 36 + ), 37 + #("education-fontys-level", #("Bachelor", "HBO/Bachelor")), 38 + #( 39 + "education-fontys-orientation", 40 + #("ICT / Software Engineering", "ICT / Software Engineering"), 41 + ), 42 + #("education-fontys-summary", #("", "")), 43 + #( 44 + "education-kw1c-institute", 45 + #("Koning Willem 1 College", "Koning Willem 1 College, Den Bosch"), 46 + ), 47 + #("education-kw1c-level", #("College", "MBO 4+")), 48 + #( 49 + "education-kw1c-orientation", 50 + #("Software Development", "Softwareontwikkeling"), 51 + ), 52 + #( 53 + "education-kw1c-period", 54 + #("February 2024 - January 2026", "Februari 2024 - Januari 2026"), 55 + ), 56 + #( 57 + "education-kw1c-summary", 58 + #( 59 + "Finished with submodule certificates before switching to Fontys.", 60 + "Afgerond met deelcertificaten voor mijn afslag naar Fontys.", 61 + ), 62 + ), 63 + #("education-bs-institute", #("Berkenschutse", "De Berkenschutse, Heeze")), 64 + #("education-bs-level", #("MAVO/HAVO", "MAVO/HAVO")), 65 + #( 66 + "education-bs-orientation", 67 + #( 68 + "Theoretical learning path / Economics and Society (E&M)", 69 + "Theoretische leerweg / Economie en Maatschappij (E&M)", 70 + ), 71 + ), 72 + #( 73 + "education-bs-period", 74 + #("February 2024 - January 2026", "Februari 2024 - Januari 2026"), 75 + ), 76 + #("education-bs-summary", #("", "")), 77 + #( 78 + "education-stercollege-institute", 79 + #("Ster College", "Ster College Eindhoven"), 80 + ), 81 + #("education-stercollege-level", #("HAVO", "HAVO/VAVO")), 82 + #( 83 + "education-stercollege-orientation", 84 + #("Culture and society (C&M)", "Cultuur en maatschappij (C&M)"), 85 + ), 86 + #("education-stercollege-summary", #("", "")), 87 + #("education-roc-institute", #("ROC", "ROC Tilburg")), 88 + #("education-roc-level", #("College", "MBO4")), 89 + #( 90 + "education-roc-orientation", 91 + #("Social / Disability Care", "Maatschappelijke Zorg"), 92 + ), 93 + #("education-roc-summary", #("", "")), 94 + #("experience-asml-internship-title", #("ASML", "ASML")), 95 + #( 96 + "experience-asml-internship-tagline", 97 + #("Internship software engineering", "Stage als software engineer"), 98 + ), 99 + #( 100 + "experience-asml-internship-summary", 101 + #( 102 + "This internship solidified my passion for software architecture and inspired me to switch from college to pursuing a Bachelor’s degree at Fontys University.", 103 + "Deze stage heeft mijn passie voor softwarearchitectuur bevestigd en me geïnspireerd om van het mbo over te stappen naar een hbo-opleiding aan Fontys Hogeschool.", 104 + ), 105 + ), 106 + #("experience-maintain-oss-title", #("", "")), 107 + #( 108 + "experience-maintain-oss-tagline", 109 + #( 110 + "Contributing to and developing Open-Source Software.", 111 + "Bijdragen aan en ontwikkeling van open-source-software.", 112 + ), 113 + ), 114 + #( 115 + "experience-maintain-oss-summary", 116 + #( 117 + "Maintenance and development of multiple small-scale open-source-software projects some of those in use at small to mid-sized companies.", 118 + "Maintainer meerdere kleinschalige opensourcesoftwareprojecten met gebruiken door kleinere tot middelgrote bedrijven.", 119 + ), 120 + ), 121 + #( 122 + "experience-maintain-oss-location", 123 + #("Online and at meets", "Online en bij congressen"), 124 + ), 125 + #("experience-ksf-title", #("Korean Soul Food", "Korean Soul Food")), 126 + #("experience-ksf-tagline", #("Catering services", "Horecamedewerker")), 127 + #( 128 + "experience-ksf-summary", 129 + #( 130 + "Servicing, maintaining customer contacts, coordinating home-delivery/takeout counter, preparation of some cold dishes", 131 + "Bediening, onderhouden van klantcontacten, coördineren van de thuisbezorging/afhaalbalie, en het bereiden van enkele koude gerechten", 132 + ), 133 + ), 134 + #("experience-spotta-title", #("Spotta", "Spotta")), 135 + #("experience-spotta-tagline", #("Brochure delivery", "Folderbezorging")), 136 + #( 137 + "experience-spotta-summary", 138 + #( 139 + "Deliverer of weekend brochures and sometimes specific pamphlets.", 140 + "Bezorgen van weekendfolders en soms speciale pamfletten.", 141 + ), 142 + ), 143 + #("interests-coding", #("Writing code", "Schrijven van code")), 144 + #( 145 + "interests-reading", 146 + #("Reading (fiction, philosophy)", "Lezen (fictie, filosofie)"), 147 + ), 148 + #( 149 + "interests-music", 150 + #( 151 + "Listening to music, visiting bands", 152 + "Luisteren naar muziek, bands bezoeken", 153 + ), 154 + ), 155 + #( 156 + "interests-party", 157 + #("Member of political party", "Lid van een politieke partij"), 158 + ), 159 + #( 160 + "interests-horse", 161 + #( 162 + "Horse care, with the occasional ride", 163 + "Paardenverzorging, en af en toe ook een ritje", 164 + ), 165 + ), 166 + #( 167 + "skills-rust-title", 168 + #("Rust (programming language)", "Rust (programmeertaal)"), 169 + ), 170 + #( 171 + "skills-gleam-title", 172 + #("Gleam (programming language)", "Gleam (programmeertaal)"), 173 + ), 174 + #( 175 + "skills-php-title", 176 + #("PHP (programming language)", "PHP (programmeertaal)"), 177 + ), 178 + #( 179 + "skills-php-desc", 180 + #( 181 + "7 & 8, SymfonyPHP, API's and fullstack applications", 182 + "7 & 8, SymfonyPHP, API's en volledige applicaties", 183 + ), 184 + ), 185 + #( 186 + "skills-js-title", 187 + #( 188 + "JavaScript / TypeScript (programming language)", 189 + "JavaScript / TypeScript (programmeertaal)", 190 + ), 191 + ), 192 + #( 193 + "skills-js-desc", 194 + #( 195 + "Fullstack, NodeJS/BunJS, backend, ExpressJS, browsers", 196 + "Fullstack, NodeJS/BunJS, backend, ExpressJS, browsers", 197 + ), 198 + ), 199 + #("view-source", #("[source code]", "[broncode]")), 200 + #("translate", #("to Dutch", "naar Engels")), 201 + #("eindhoven-nl", #("Eindhoven, The Netherlands", "Eindhoven, Noord-Brabant")), 202 + #( 203 + "headline", 204 + #( 205 + "Driven by creativity, activated by curiosity.", 206 + "Gedreven door creativiteit, geactiveerd door nieuwsgierigheid.", 207 + ), 208 + ), 209 + #( 210 + "summary-summary", 211 + #( 212 + "I am deeply passionate about the intersection of people, society, and developing things! As a versatile professional, I thrive on navigating complex challenges and driving meaningful impact across diverse environments.", 213 + "Ik heb een enorme passie voor het snijvlak van mens, maatschappij en ontwikkeling! Als veelzijdige professional krijg ik energie van het aanpakken van complexe uitdagingen en het maken van een betekenisvolle impact in uiteenlopende omgevingen.", 214 + ), 215 + ), 216 + #( 217 + "subheader-languages", 218 + #( 219 + "Good verbal and written language skills in both Dutch and English.", 220 + "Goede gesproken en geschreven kennis in zowel Nederlands als Engels.", 221 + ), 222 + ), 223 + ] 224 + 225 + pub fn view(model: stuff.Model, in_dutch: Bool) -> Element { 226 + let href = fn(r: Route) { stuff.href(r, model.raw_posts) } 8 227 // Dict(keyname, #(english, dutch)) 9 228 let translations = 10 - [ 11 - #("langswitch", #("🇳🇱 NL", "🇬🇧 EN")), 12 - #("header-summary", #("About", "Over")), 13 - #("header-profiles", #("Profiles", "Online")), 14 - #("header-interests", #("Interests", "Interesses")), 15 - #("header-skills", #("Skills", "Vaardigheden")), 16 - #("header-experience", #("Experience", "Ervaring")), 17 - #("subheader-experience-older", #("Earlier", "Eerder")), 18 - #("header-education", #("Education", "Opleidingen")), 19 - #("header-languages", #("Languages", "Talen")), 20 - #("lang-dut", #("Dutch", "Nederlands")), 21 - #("lang-eng", #("English", "Engels")), 22 - #("word-native", #("Native.", "Moedertaal.")), 23 - #("cambridge-daily", #( 24 - "Daily speaker, Cambridge C1 level.", 25 - "Dagelijkse spreker, Cambridge C1 niveau.", 26 - )), 27 - #("date-2/'26", #("February 2026", "Februari 2026")), 28 - #("attribution-1", #("Based on the design from ", "Ontworpen naar ")), 29 - #("attribution-2", #(", delivered in Gleam. ", ", uitgevoerd in Gleam. ")), 30 - #("present", #("Present", "Heden")), 31 - #("education-fontys-institute", #( 32 - "Fontys University of Applied Sciences", 33 - "Fontys Hogeschool", 34 - )), 35 - #("education-fontys-level", #("Bachelor", "HBO/Bachelor")), 36 - #("education-fontys-orientation", #( 37 - "ICT / Software Engineering", 38 - "ICT / Software Engineering", 39 - )), 40 - #("education-fontys-summary", #("", "")), 41 - #("education-kw1c-institute", #( 42 - "Koning Willem 1 College", 43 - "Koning Willem 1 College, Den Bosch", 44 - )), 45 - #("education-kw1c-level", #("College", "MBO 4+")), 46 - #("education-kw1c-orientation", #( 47 - "Software Development", 48 - "Softwareontwikkeling", 49 - )), 50 - #("education-kw1c-period", #( 51 - "February 2024 - January 2026", 52 - "Februari 2024 - Januari 2026", 53 - )), 54 - #("education-kw1c-summary", #( 55 - "Finished with submodule certificates before switching to Fontys.", 56 - "Afgerond met deelcertificaten voor mijn afslag naar Fontys.", 57 - )), 58 - #("education-bs-institute", #("Berkenschutse", "De Berkenschutse, Heeze")), 59 - #("education-bs-level", #("MAVO/HAVO", "MAVO/HAVO")), 60 - #("education-bs-orientation", #( 61 - "Theoretical learning path / Economics and Society (E&M)", 62 - "Theoretische leerweg / Economie en Maatschappij (E&M)", 63 - )), 64 - #("education-bs-period", #( 65 - "February 2024 - January 2026", 66 - "Februari 2024 - Januari 2026", 67 - )), 68 - #("education-bs-summary", #("", "")), 69 - #("education-stercollege-institute", #( 70 - "Ster College", 71 - "Ster College Eindhoven", 72 - )), 73 - #("education-stercollege-level", #("HAVO", "HAVO/VAVO")), 74 - #("education-stercollege-orientation", #( 75 - "Culture and society (C&M)", 76 - "Cultuur en maatschappij (C&M)", 77 - )), 78 - #("education-stercollege-summary", #("", "")), 79 - #("education-roc-institute", #("ROC", "ROC Tilburg")), 80 - #("education-roc-level", #("College", "MBO4")), 81 - #("education-roc-orientation", #( 82 - "Social / Disability Care", 83 - "Maatschappelijke Zorg", 84 - )), 85 - #("education-roc-summary", #("", "")), 86 - #("experience-asml-internship-title", #("ASML", "ASML")), 87 - #("experience-asml-internship-tagline", #( 88 - "Internship software engineering", 89 - "Stage als software engineer", 90 - )), 91 - #("experience-asml-internship-summary", #( 92 - "This internship solidified my passion for software architecture and inspired me to switch from college to pursuing a Bachelor’s degree at Fontys University.", 93 - "Deze stage heeft mijn passie voor softwarearchitectuur bevestigd en me geïnspireerd om van het mbo over te stappen naar een hbo-opleiding aan Fontys Hogeschool.", 94 - )), 95 - #("experience-maintain-oss-title", #("", "")), 96 - #("experience-maintain-oss-tagline", #( 97 - "Contributing to and developing Open-Source Software.", 98 - "Bijdragen aan en ontwikkeling van open-source-software.", 99 - )), 100 - #("experience-maintain-oss-summary", #( 101 - "Maintenance and development of multiple small-scale open-source-software projects some of those in use at small to mid-sized companies.", 102 - "Maintainer meerdere kleinschalige opensourcesoftwareprojecten met gebruiken door kleinere tot middelgrote bedrijven.", 103 - )), 104 - #("experience-maintain-oss-location", #( 105 - "Online and at meets", 106 - "Online en bij congressen", 107 - )), 108 - #("experience-ksf-title", #("Korean Soul Food", "Korean Soul Food")), 109 - #("experience-ksf-tagline", #("Catering services", "Horecamedewerker")), 110 - #("experience-ksf-summary", #( 111 - "Servicing, maintaining customer contacts, coordinating home-delivery/takeout counter, preparation of some cold dishes", 112 - "Bediening, onderhouden van klantcontacten, coördineren van de thuisbezorging/afhaalbalie, en het bereiden van enkele koude gerechten", 113 - )), 114 - #("experience-spotta-title", #("Spotta", "Spotta")), 115 - #("experience-spotta-tagline", #("Brochure delivery", "Folderbezorging")), 116 - #("experience-spotta-summary", #( 117 - "Deliverer of weekend brochures and sometimes specific pamphlets.", 118 - "Bezorgen van weekendfolders en soms speciale pamfletten.", 119 - )), 120 - #("interests-coding", #("Writing code", "Schrijven van code")), 121 - #("interests-reading", #( 122 - "Reading (fiction, philosophy)", 123 - "Lezen (fictie, filosofie)", 124 - )), 125 - #("interests-music", #( 126 - "Listening to music, visiting bands", 127 - "Luisteren naar muziek, bands bezoeken", 128 - )), 129 - #("interests-party", #( 130 - "Member of political party", 131 - "Lid van een politieke partij", 132 - )), 133 - #("interests-horse", #( 134 - "Horse care, with the occasional ride", 135 - "Paardenverzorging, en af en toe ook een ritje", 136 - )), 137 - #("skills-rust-title", #( 138 - "Rust (programming language)", 139 - "Rust (programmeertaal)", 140 - )), 141 - #("skills-gleam-title", #( 142 - "Gleam (programming language)", 143 - "Gleam (programmeertaal)", 144 - )), 145 - #("skills-php-title", #( 146 - "PHP (programming language)", 147 - "PHP (programmeertaal)", 148 - )), 149 - #("skills-php-desc", #( 150 - "7 & 8, SymfonyPHP, API's and fullstack applications", 151 - "7 & 8, SymfonyPHP, API's en volledige applicaties", 152 - )), 153 - #("skills-js-title", #( 154 - "JavaScript / TypeScript (programming language)", 155 - "JavaScript / TypeScript (programmeertaal)", 156 - )), 157 - #("skills-js-desc", #( 158 - "Fullstack, NodeJS/BunJS, backend, ExpressJS, browsers", 159 - "Fullstack, NodeJS/BunJS, backend, ExpressJS, browsers", 160 - )), 161 - #("view-source", #("[source code]", "[broncode]")), 162 - #("translate", #("to Dutch", "naar Engels")), 163 - #("eindhoven-nl", #( 164 - "Eindhoven, The Netherlands", 165 - "Eindhoven, Noord-Brabant", 166 - )), 167 - #("headline", #( 168 - "Driven by creativity, activated by curiosity.", 169 - "Gedreven door creativiteit, geactiveerd door nieuwsgierigheid.", 170 - )), 171 - #("summary-summary", #( 172 - "I am deeply passionate about the intersection of people, society, and developing things! As a versatile professional, I thrive on navigating complex challenges and driving meaningful impact across diverse environments.", 173 - "Ik heb een enorme passie voor het snijvlak van mens, maatschappij en ontwikkeling! Als veelzijdige professional krijg ik energie van het aanpakken van complexe uitdagingen en het maken van een betekenisvolle impact in uiteenlopende omgevingen.", 174 - )), 175 - #("subheader-languages", #( 176 - "Good verbal and written language skills in both Dutch and English.", 177 - "Goede gesproken en geschreven kennis in zowel Nederlands als Engels.", 178 - )), 179 - ] 229 + translations 180 230 |> dict.from_list() 181 231 let localise = fn(keyname) { 182 232 case translations |> dict.get(keyname) { 183 233 Ok(v) -> 184 234 case in_dutch { 185 - True -> v.1 186 235 False -> v.0 236 + True -> v.1 187 237 } 188 238 |> element.text() 189 239 ··· 247 297 html.li([], [ 248 298 html.a( 249 299 [ 250 - attribute.href(case in_dutch { 251 - False -> "/cv/nl" 252 - True -> "/cv/en" 253 - }), 300 + case in_dutch { 301 + // eng -> dut 302 + False -> href(stuff.CuriculumVitae(True)) 303 + // dut -> eng 304 + True -> href(stuff.CuriculumVitae(False)) 305 + }, 254 306 attribute.class("tooltip tooltip-bottom"), 255 307 ], 256 308 [ ··· 313 365 ) 314 366 } 315 367 316 - fn view_cv_inner(localise: fn(String) -> Element(a)) { 368 + fn view_cv_inner(localise: fn(String) -> Element) { 317 369 [ 318 370 html.div( 319 371 [ ··· 1141 1193 1142 1194 fn experience_item( 1143 1195 primary primary: Bool, 1144 - localise localise: fn(String) -> element.Element(a), 1196 + localise localise: fn(String) -> Element, 1145 1197 name name: String, 1146 - location location: element.Element(a), 1147 - period period: List(element.Element(a)), 1198 + location location: Element, 1199 + period period: List(Element), 1148 1200 ) { 1149 1201 let bordercolour = case primary { 1150 1202 True -> " border-primary" ··· 1200 1252 1201 1253 fn education_item( 1202 1254 primary primary: Bool, 1203 - localise localise: fn(String) -> element.Element(a), 1255 + localise localise: fn(String) -> Element, 1204 1256 name name: String, 1205 - period period: List(element.Element(a)), 1257 + period period: List(Element), 1206 1258 ) { 1207 1259 let bordercolour = case primary { 1208 1260 True -> " border-primary" ··· 1260 1312 } 1261 1313 1262 1314 fn skill_item( 1263 - name skillname: List(Element(a)), 1264 - description skilldesc: List(element.Element(a)), 1315 + name skillname: List(Element), 1316 + description skilldesc: List(Element), 1265 1317 strength strength: Float, 1266 1318 ) { 1267 1319 let unfilled_skill_block =
+42
src/homepage/view/not_found.gleam
··· 1 + import gleam/list 2 + import homepage/stuff.{type Element} 3 + import homepage/stuff/prestyled_elements.{paragraph, title} 4 + 5 + pub fn view() -> List(Element) { 6 + let first = 7 + "You glimpse into the void and see -- nothing? 8 + Well that was somewhat expected." 9 + [ 10 + title("Not found"), 11 + paragraph( 12 + case 13 + [ 14 + first, 15 + "You've wandered off the map. There are no monsters here, just an endless, pixelated silence.", 16 + "This page has achieved enlightenment and transcended the physical server. It no longer exists in this dimension.", 17 + "Error 404: The digital equivalent of walking into a room and forgetting why you came here.", 18 + "Everything you see here is a hallucination. Especially this 404 page.", 19 + "You reached the end of the internet. Please turn around and head back the way you came.", 20 + "404: A quiet space for reflection. Or just a broken link. Mostly the broken link thing.", 21 + "Lost in the sauce? This page certainly is.", 22 + "Nothing to see here. Move along, citizen.", 23 + "You picked a bad time to get lost, friend!", 24 + "This page is currently 'Works on my machine'—but apparently not on yours.", 25 + "A 404 error has occurred. Please pet your nearest cat and try again.", 26 + "You took a wrong turn at the last hyperlink. Care for a juice box while you find your way back?", 27 + "Oh no! The pixels for this page haven't been delivered yet. The digital mail is running late.", 28 + "You found a secret area! Unfortunately, the secret is that there’s nothing here.", 29 + "Error 404: The hamsters powering this specific page are currently on their lunch break.", 30 + "404: Under Construction... indefinitely. (Just kidding, it's just gone.)", 31 + "This URL did not exist. Please refresh your browser or your outlook on life.", 32 + "Nope, not here!", 33 + ] 34 + |> list.shuffle() 35 + |> list.first() 36 + { 37 + Error(_) -> first 38 + Ok(r) -> r 39 + }, 40 + ), 41 + ] 42 + }