From 1346fffdd835e2fc2fedb3ee86e11d3b3ec85efe Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Thu, 12 Oct 2023 15:40:10 -0400 Subject: lume/blog: xesite v4 Signed-off-by: Xe Iaso --- .vscode/settings.json | 5 + lume/_config.ts | 1 + lume/deno.lock | 500 ++++++++++++++++++++++++++++++++++++ lume/src/_components/Figure.tsx | 14 +- lume/src/_components/XeblogConv.tsx | 4 +- lume/src/blog/xesite-v4.mdx | 393 ++++++++++++++++++++++++++++ 6 files changed, 913 insertions(+), 4 deletions(-) create mode 100644 lume/src/blog/xesite-v4.mdx diff --git a/.vscode/settings.json b/.vscode/settings.json index c6ed1b4..393a19a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,4 +4,9 @@ "editor.wordWrapColumn": 80, "editor.wordBasedSuggestions": false }, + "[mdx]": { + "editor.wordWrap": "wordWrapColumn", + "editor.wordWrapColumn": 80, + "editor.wordBasedSuggestions": false + }, } \ No newline at end of file diff --git a/lume/_config.ts b/lume/_config.ts index 4d91ff2..514332c 100644 --- a/lume/_config.ts +++ b/lume/_config.ts @@ -31,6 +31,7 @@ const site = lume({ site.copy("static"); site.copy("favicon.ico"); site.copy("static/font/inter/inter.css"); +site.copy("static/img"); site.data("getYear", () => { return new Date().getFullYear(); diff --git a/lume/deno.lock b/lume/deno.lock index 7cc9dc7..ed5ebb9 100644 --- a/lume/deno.lock +++ b/lume/deno.lock @@ -501,6 +501,7 @@ "react": "react@18.2.0", "react-dom@18.2.0": "react-dom@18.2.0_react@18.2.0", "react@18.2.0": "react@18.2.0", + "rehype-mermaidjs": "rehype-mermaidjs@2.0.0", "rehype-prism-plus": "rehype-prism-plus@1.6.3", "rehype-raw@7.0.0": "rehype-raw@7.0.0", "rehype-sanitize@6.0.0": "rehype-sanitize@6.0.0", @@ -522,12 +523,20 @@ "regenerator-runtime": "regenerator-runtime@0.14.0" } }, + "@braintree/sanitize-url@6.0.4": { + "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", + "dependencies": {} + }, "@csstools/selector-specificity@3.0.0_postcss-selector-parser@6.0.13": { "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==", "dependencies": { "postcss-selector-parser": "postcss-selector-parser@6.0.13" } }, + "@fortawesome/fontawesome-free@6.4.2": { + "integrity": "sha512-m5cPn3e2+FDCOgi1mz0RexTUvvQibBebOUlUlW0+YrMjDTPkiJ6VTKukA1GRsvRw+12KyJndNjj0O4AgTxm2Pg==", + "dependencies": {} + }, "@headlessui/react@1.7.17_react@18.2.0_react-dom@18.2.0__react@18.2.0": { "integrity": "sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==", "dependencies": { @@ -632,6 +641,20 @@ "@types/estree": "@types/estree@1.0.2" } }, + "@types/d3-scale-chromatic@3.0.0": { + "integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==", + "dependencies": {} + }, + "@types/d3-scale@4.0.5": { + "integrity": "sha512-w/C++3W394MHzcLKO2kdsIn5KKNTOqeQVzyPSGPLzQbkPw/jpeaGtSRlakcKevGgGsjJxGsbqS0fPrVFDbHrDA==", + "dependencies": { + "@types/d3-time": "@types/d3-time@3.0.1" + } + }, + "@types/d3-time@3.0.1": { + "integrity": "sha512-5j/AnefKAhCw4HpITmLDTPlf4vhi8o/dES+zbegfPb7LaGfNyqkLxBR6E+4yvTAgnJLmhe80EXFMzUs38fw4oA==", + "dependencies": {} + }, "@types/debug@4.1.9": { "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", "dependencies": { @@ -866,10 +889,26 @@ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dependencies": {} }, + "commander@7.2.0": { + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dependencies": {} + }, "concat-map@0.0.1": { "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dependencies": {} }, + "cose-base@1.0.3": { + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "dependencies": { + "layout-base": "layout-base@1.0.2" + } + }, + "cose-base@2.2.0": { + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "dependencies": { + "layout-base": "layout-base@2.0.1" + } + }, "cssesc@3.0.0": { "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dependencies": {} @@ -878,12 +917,281 @@ "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", "dependencies": {} }, + "cytoscape-cose-bilkent@4.1.0_cytoscape@3.26.0": { + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "dependencies": { + "cose-base": "cose-base@1.0.3", + "cytoscape": "cytoscape@3.26.0" + } + }, + "cytoscape-fcose@2.2.0_cytoscape@3.26.0": { + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "dependencies": { + "cose-base": "cose-base@2.2.0", + "cytoscape": "cytoscape@3.26.0" + } + }, + "cytoscape@3.26.0": { + "integrity": "sha512-IV+crL+KBcrCnVVUCZW+zRRRFUZQcrtdOPXki+o4CFUWLdAEYvuZLcBSJC9EBK++suamERKzeY7roq2hdovV3w==", + "dependencies": { + "heap": "heap@0.2.7", + "lodash": "lodash@4.17.21" + } + }, + "d3-array@2.12.1": { + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "dependencies": { + "internmap": "internmap@1.0.1" + } + }, + "d3-array@3.2.4": { + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "internmap@2.0.3" + } + }, + "d3-axis@3.0.0": { + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "dependencies": {} + }, + "d3-brush@3.0.0_d3-selection@3.0.0": { + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "d3-dispatch@3.0.1", + "d3-drag": "d3-drag@3.0.0", + "d3-interpolate": "d3-interpolate@3.0.1", + "d3-selection": "d3-selection@3.0.0", + "d3-transition": "d3-transition@3.0.1_d3-selection@3.0.0" + } + }, + "d3-chord@3.0.1": { + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "d3-path@3.1.0" + } + }, + "d3-color@3.1.0": { + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "dependencies": {} + }, + "d3-contour@4.0.2": { + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "d3-array@3.2.4" + } + }, + "d3-delaunay@6.0.4": { + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "delaunator@5.0.0" + } + }, + "d3-dispatch@3.0.1": { + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "dependencies": {} + }, + "d3-drag@3.0.0": { + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "d3-dispatch@3.0.1", + "d3-selection": "d3-selection@3.0.0" + } + }, + "d3-dsv@3.0.1": { + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "commander@7.2.0", + "iconv-lite": "iconv-lite@0.6.3", + "rw": "rw@1.3.3" + } + }, + "d3-ease@3.0.1": { + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "dependencies": {} + }, + "d3-fetch@3.0.1": { + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "d3-dsv@3.0.1" + } + }, + "d3-force@3.0.0": { + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "d3-dispatch@3.0.1", + "d3-quadtree": "d3-quadtree@3.0.1", + "d3-timer": "d3-timer@3.0.1" + } + }, + "d3-format@3.1.0": { + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "dependencies": {} + }, + "d3-geo@3.1.0": { + "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", + "dependencies": { + "d3-array": "d3-array@3.2.4" + } + }, + "d3-hierarchy@3.1.2": { + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "dependencies": {} + }, + "d3-interpolate@3.0.1": { + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "d3-color@3.1.0" + } + }, + "d3-path@1.0.9": { + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dependencies": {} + }, + "d3-path@3.1.0": { + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "dependencies": {} + }, + "d3-polygon@3.0.1": { + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "dependencies": {} + }, + "d3-quadtree@3.0.1": { + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "dependencies": {} + }, + "d3-random@3.0.1": { + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "dependencies": {} + }, + "d3-sankey@0.12.3": { + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "dependencies": { + "d3-array": "d3-array@2.12.1", + "d3-shape": "d3-shape@1.3.7" + } + }, + "d3-scale-chromatic@3.0.0": { + "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", + "dependencies": { + "d3-color": "d3-color@3.1.0", + "d3-interpolate": "d3-interpolate@3.0.1" + } + }, + "d3-scale@4.0.2": { + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "d3-array@3.2.4", + "d3-format": "d3-format@3.1.0", + "d3-interpolate": "d3-interpolate@3.0.1", + "d3-time": "d3-time@3.1.0", + "d3-time-format": "d3-time-format@4.1.0" + } + }, + "d3-selection@3.0.0": { + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "dependencies": {} + }, + "d3-shape@1.3.7": { + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dependencies": { + "d3-path": "d3-path@1.0.9" + } + }, + "d3-shape@3.2.0": { + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "d3-path@3.1.0" + } + }, + "d3-time-format@4.1.0": { + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "d3-time@3.1.0" + } + }, + "d3-time@3.1.0": { + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "d3-array@3.2.4" + } + }, + "d3-timer@3.0.1": { + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "dependencies": {} + }, + "d3-transition@3.0.1_d3-selection@3.0.0": { + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "d3-color@3.1.0", + "d3-dispatch": "d3-dispatch@3.0.1", + "d3-ease": "d3-ease@3.0.1", + "d3-interpolate": "d3-interpolate@3.0.1", + "d3-selection": "d3-selection@3.0.0", + "d3-timer": "d3-timer@3.0.1" + } + }, + "d3-zoom@3.0.0_d3-selection@3.0.0": { + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "d3-dispatch@3.0.1", + "d3-drag": "d3-drag@3.0.0", + "d3-interpolate": "d3-interpolate@3.0.1", + "d3-selection": "d3-selection@3.0.0", + "d3-transition": "d3-transition@3.0.1_d3-selection@3.0.0" + } + }, + "d3@7.8.5_d3-selection@3.0.0": { + "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", + "dependencies": { + "d3-array": "d3-array@3.2.4", + "d3-axis": "d3-axis@3.0.0", + "d3-brush": "d3-brush@3.0.0_d3-selection@3.0.0", + "d3-chord": "d3-chord@3.0.1", + "d3-color": "d3-color@3.1.0", + "d3-contour": "d3-contour@4.0.2", + "d3-delaunay": "d3-delaunay@6.0.4", + "d3-dispatch": "d3-dispatch@3.0.1", + "d3-drag": "d3-drag@3.0.0", + "d3-dsv": "d3-dsv@3.0.1", + "d3-ease": "d3-ease@3.0.1", + "d3-fetch": "d3-fetch@3.0.1", + "d3-force": "d3-force@3.0.0", + "d3-format": "d3-format@3.1.0", + "d3-geo": "d3-geo@3.1.0", + "d3-hierarchy": "d3-hierarchy@3.1.2", + "d3-interpolate": "d3-interpolate@3.0.1", + "d3-path": "d3-path@3.1.0", + "d3-polygon": "d3-polygon@3.0.1", + "d3-quadtree": "d3-quadtree@3.0.1", + "d3-random": "d3-random@3.0.1", + "d3-scale": "d3-scale@4.0.2", + "d3-scale-chromatic": "d3-scale-chromatic@3.0.0", + "d3-selection": "d3-selection@3.0.0", + "d3-shape": "d3-shape@3.2.0", + "d3-time": "d3-time@3.1.0", + "d3-time-format": "d3-time-format@4.1.0", + "d3-timer": "d3-timer@3.0.1", + "d3-transition": "d3-transition@3.0.1_d3-selection@3.0.0", + "d3-zoom": "d3-zoom@3.0.0_d3-selection@3.0.0" + } + }, + "dagre-d3-es@7.0.10": { + "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==", + "dependencies": { + "d3": "d3@7.8.5_d3-selection@3.0.0", + "lodash-es": "lodash-es@4.17.21" + } + }, "date-fns@2.30.0": { "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dependencies": { "@babel/runtime": "@babel/runtime@7.23.1" } }, + "dayjs@1.11.10": { + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==", + "dependencies": {} + }, "debug@4.3.4": { "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { @@ -896,6 +1204,12 @@ "character-entities": "character-entities@2.0.2" } }, + "delaunator@5.0.0": { + "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", + "dependencies": { + "robust-predicates": "robust-predicates@3.0.2" + } + }, "dequal@2.0.3": { "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dependencies": {} @@ -918,10 +1232,18 @@ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "dependencies": {} }, + "dompurify@3.0.6": { + "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==", + "dependencies": {} + }, "electron-to-chromium@1.4.531": { "integrity": "sha512-H6gi5E41Rn3/mhKlPaT1aIMg/71hTAqn0gYEllSuw9igNWtvQwu185jiCZoZD29n7Zukgh7GVZ3zGf0XvkhqjQ==", "dependencies": {} }, + "elkjs@0.8.2": { + "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==", + "dependencies": {} + }, "entities@3.0.1": { "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", "dependencies": {} @@ -1048,6 +1370,34 @@ "function-bind": "function-bind@1.1.1" } }, + "hast-util-from-dom@5.0.0": { + "integrity": "sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==", + "dependencies": { + "@types/hast": "@types/hast@3.0.1", + "hastscript": "hastscript@8.0.0", + "web-namespaces": "web-namespaces@2.0.1" + } + }, + "hast-util-from-html-isomorphic@2.0.0": { + "integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==", + "dependencies": { + "@types/hast": "@types/hast@3.0.1", + "hast-util-from-dom": "hast-util-from-dom@5.0.0", + "hast-util-from-html": "hast-util-from-html@2.0.1", + "unist-util-remove-position": "unist-util-remove-position@5.0.0" + } + }, + "hast-util-from-html@2.0.1": { + "integrity": "sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==", + "dependencies": { + "@types/hast": "@types/hast@3.0.1", + "devlop": "devlop@1.1.0", + "hast-util-from-parse5": "hast-util-from-parse5@8.0.1", + "parse5": "parse5@7.1.2", + "vfile": "vfile@6.0.1", + "vfile-message": "vfile-message@4.0.2" + } + }, "hast-util-from-parse5@7.1.2": { "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", "dependencies": { @@ -1073,6 +1423,12 @@ "web-namespaces": "web-namespaces@2.0.1" } }, + "hast-util-is-element@3.0.0": { + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dependencies": { + "@types/hast": "@types/hast@3.0.1" + } + }, "hast-util-parse-selector@3.1.1": { "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", "dependencies": { @@ -1166,6 +1522,15 @@ "@types/hast": "@types/hast@2.3.6" } }, + "hast-util-to-text@4.0.0": { + "integrity": "sha512-EWiE1FSArNBPUo1cKWtzqgnuRQwEeQbQtnFJRYV1hb1BWDgrAlBU0ExptvZMM/KSA82cDpm2sFGf3Dmc5Mza3w==", + "dependencies": { + "@types/hast": "@types/hast@3.0.1", + "@types/unist": "@types/unist@3.0.0", + "hast-util-is-element": "hast-util-is-element@3.0.0", + "unist-util-find-after": "unist-util-find-after@5.0.0" + } + }, "hast-util-whitespace@2.0.1": { "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", "dependencies": {} @@ -1196,6 +1561,10 @@ "space-separated-tokens": "space-separated-tokens@2.0.2" } }, + "heap@0.2.7": { + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", + "dependencies": {} + }, "hls.js@1.4.12": { "integrity": "sha512-1RBpx2VihibzE3WE9kGoVCtrhhDWTzydzElk/kyRbEOLnb1WIE+3ZabM/L8BqKFTCL3pUy4QzhXgD1Q6Igr1JA==", "dependencies": {} @@ -1204,6 +1573,12 @@ "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", "dependencies": {} }, + "iconv-lite@0.6.3": { + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": "safer-buffer@2.1.2" + } + }, "inflight@1.0.6": { "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { @@ -1219,6 +1594,14 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", "dependencies": {} }, + "internmap@1.0.1": { + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "dependencies": {} + }, + "internmap@2.0.3": { + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "dependencies": {} + }, "is-alphabetical@2.0.1": { "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", "dependencies": {} @@ -1286,10 +1669,22 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dependencies": {} }, + "khroma@2.0.0": { + "integrity": "sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==", + "dependencies": {} + }, "kleur@4.1.5": { "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "dependencies": {} }, + "layout-base@1.0.2": { + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "dependencies": {} + }, + "layout-base@2.0.1": { + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "dependencies": {} + }, "lilconfig@2.1.0": { "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dependencies": {} @@ -1304,6 +1699,10 @@ "uc.micro": "uc.micro@1.0.6" } }, + "lodash-es@4.17.21": { + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dependencies": {} + }, "lodash.castarray@4.4.0": { "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", "dependencies": {} @@ -1316,6 +1715,10 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dependencies": {} }, + "lodash@4.17.21": { + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dependencies": {} + }, "longest-streak@3.1.0": { "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", "dependencies": {} @@ -1547,6 +1950,39 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dependencies": {} }, + "mermaid-isomorphic@2.1.1": { + "integrity": "sha512-iShQaYYfGYakKs6fbwVjaTAaTVYm02aIvq8QZJFZMEJ18it2YMhW7QF23jLc1SgXHfVLbeWVoQ27jar2X8KP9g==", + "dependencies": { + "@fortawesome/fontawesome-free": "@fortawesome/fontawesome-free@6.4.2", + "mermaid": "mermaid@10.5.0_cytoscape@3.26.0", + "playwright-core": "playwright-core@1.39.0" + } + }, + "mermaid@10.5.0_cytoscape@3.26.0": { + "integrity": "sha512-9l0o1uUod78D3/FVYPGSsgV+Z0tSnzLBDiC9rVzvelPxuO80HbN1oDr9ofpPETQy9XpypPQa26fr09VzEPfvWA==", + "dependencies": { + "@braintree/sanitize-url": "@braintree/sanitize-url@6.0.4", + "@types/d3-scale": "@types/d3-scale@4.0.5", + "@types/d3-scale-chromatic": "@types/d3-scale-chromatic@3.0.0", + "cytoscape": "cytoscape@3.26.0", + "cytoscape-cose-bilkent": "cytoscape-cose-bilkent@4.1.0_cytoscape@3.26.0", + "cytoscape-fcose": "cytoscape-fcose@2.2.0_cytoscape@3.26.0", + "d3": "d3@7.8.5_d3-selection@3.0.0", + "d3-sankey": "d3-sankey@0.12.3", + "dagre-d3-es": "dagre-d3-es@7.0.10", + "dayjs": "dayjs@1.11.10", + "dompurify": "dompurify@3.0.6", + "elkjs": "elkjs@0.8.2", + "khroma": "khroma@2.0.0", + "lodash-es": "lodash-es@4.17.21", + "mdast-util-from-markdown": "mdast-util-from-markdown@1.3.1", + "non-layered-tidy-tree-layout": "non-layered-tidy-tree-layout@2.0.2", + "stylis": "stylis@4.3.0", + "ts-dedent": "ts-dedent@2.2.0", + "uuid": "uuid@9.0.1", + "web-worker": "web-worker@1.2.0" + } + }, "micromark-core-commonmark@1.1.0": { "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", "dependencies": { @@ -1947,6 +2383,10 @@ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dependencies": {} }, + "non-layered-tidy-tree-layout@2.0.2": { + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", + "dependencies": {} + }, "normalize-path@3.0.0": { "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dependencies": {} @@ -2036,6 +2476,10 @@ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dependencies": {} }, + "playwright-core@1.39.0": { + "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", + "dependencies": {} + }, "postcss-import@15.1.0_postcss@8.4.29": { "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "dependencies": { @@ -2163,6 +2607,20 @@ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", "dependencies": {} }, + "rehype-mermaidjs@2.0.0": { + "integrity": "sha512-QY8uiV31GZd/devc/3vzGOrTkNI5vktEXvRmArqw1oBSeFe1EWnfXXH/5J83Had8kG6Z/2xiLWvL/pJ/rgIr9g==", + "dependencies": { + "@types/hast": "@types/hast@3.0.1", + "hast-util-from-html-isomorphic": "hast-util-from-html-isomorphic@2.0.0", + "hast-util-to-text": "hast-util-to-text@4.0.0", + "mermaid-isomorphic": "mermaid-isomorphic@2.1.1", + "mini-svg-data-uri": "mini-svg-data-uri@1.4.4", + "space-separated-tokens": "space-separated-tokens@2.0.2", + "unified": "unified@11.0.2", + "unist-util-visit-parents": "unist-util-visit-parents@6.0.1", + "vfile": "vfile@6.0.1" + } + }, "rehype-parse@8.0.5": { "integrity": "sha512-Ds3RglaY/+clEX2U2mHflt7NlMA72KspZ0JLUJgBBLpRddBcEw3H8uYZQliQriku22NZpYMfjDdSgHcjxue24A==", "dependencies": { @@ -2251,18 +2709,30 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dependencies": {} }, + "robust-predicates@3.0.2": { + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "dependencies": {} + }, "run-parallel@1.2.0": { "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dependencies": { "queue-microtask": "queue-microtask@1.2.3" } }, + "rw@1.3.3": { + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "dependencies": {} + }, "sade@1.8.1": { "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", "dependencies": { "mri": "mri@1.2.0" } }, + "safer-buffer@2.1.2": { + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dependencies": {} + }, "scheduler@0.23.0": { "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "dependencies": { @@ -2294,6 +2764,10 @@ "inline-style-parser": "inline-style-parser@0.1.1" } }, + "stylis@4.3.0": { + "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==", + "dependencies": {} + }, "sucrase@3.34.0": { "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", "dependencies": { @@ -2363,6 +2837,10 @@ "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", "dependencies": {} }, + "ts-dedent@2.2.0": { + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dependencies": {} + }, "ts-interface-checker@0.1.13": { "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dependencies": {} @@ -2403,6 +2881,13 @@ "unist-util-visit-parents": "unist-util-visit-parents@5.1.3" } }, + "unist-util-find-after@5.0.0": { + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "dependencies": { + "@types/unist": "@types/unist@3.0.0", + "unist-util-is": "unist-util-is@6.0.0" + } + }, "unist-util-generated@2.0.1": { "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", "dependencies": {} @@ -2444,6 +2929,13 @@ "unist-util-visit": "unist-util-visit@4.1.2" } }, + "unist-util-remove-position@5.0.0": { + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dependencies": { + "@types/unist": "@types/unist@3.0.0", + "unist-util-visit": "unist-util-visit@5.0.0" + } + }, "unist-util-stringify-position@3.0.3": { "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", "dependencies": { @@ -2498,6 +2990,10 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dependencies": {} }, + "uuid@9.0.1": { + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dependencies": {} + }, "uvu@0.5.6": { "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", "dependencies": { @@ -2556,6 +3052,10 @@ "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", "dependencies": {} }, + "web-worker@1.2.0": { + "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==", + "dependencies": {} + }, "wrappy@1.0.2": { "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dependencies": {} diff --git a/lume/src/_components/Figure.tsx b/lume/src/_components/Figure.tsx index 99dc4e2..ad8d802 100644 --- a/lume/src/_components/Figure.tsx +++ b/lume/src/_components/Figure.tsx @@ -5,10 +5,20 @@ export interface FigureProps { alt?: string; } -export default function Figure({ className, path, alt, desc = alt}: FigureProps) { +export default function Figure( + { className, path, alt, desc = alt }: FigureProps, +) { return (
- {desc} + + {desc} + {desc &&
{desc}
}
); diff --git a/lume/src/_components/XeblogConv.tsx b/lume/src/_components/XeblogConv.tsx index f876cd0..c522e45 100644 --- a/lume/src/_components/XeblogConv.tsx +++ b/lume/src/_components/XeblogConv.tsx @@ -13,9 +13,9 @@ const ConvSnippet = ({ name, mood, children, standalone }: XeblogConvProps) => { return ( <>
-
+
{`${name} + Arguably, I did have a static site generator, but it was just kinda halfassed + and stored everything in memory. + + +However, there were a few problems with this approach: + +I couldn't trigger updates to the website content without redeploying the entire server it was on, due to how it was implemented with NixOS. This is not a fault in how NixOS works, this was a fault in how I implemented it. + +To be fair, I tried adding dynamic updates to the mix, but I was running into issues involving state contention with how I designed things in Rust. I could've fixed this, but it would've required a lot of work. It probably would have ended in me rendering every page to the disk and serving that disk folder, but that's not really what I wanted. + +I wanted to adopt [Tailwind](https://tailwindcss.com) so that I could style my posts a lot more freely, but I wasn't really able to find a way to fit it in because the Tailwind parser couldn't understand the HTML templates I was using. + +I was using the proc macro [Maud](https://maud.lambda.xyz/) to write HTML, but the Tailwind parser can't handle reading class names out of Maud templates. Here's an example JSX component from my website that I wanted to port over: + +```jsx +export default function BlockQuote({ children }) { + return ( +
+ > {children} +
+ ); +} +``` + +In Maud, the template would look like this: + +```rust +use maud::Markup; + +pub fn blockquote(body: Markup) -> Markup { + html! { + ."mx-auto mt-4 mb-2 rounded-lg bg-bg-2 p-4 dark:bg-bgDark-2 md:max-w-lg xe-dont-newline" { + "> " (body) + } + } +} +``` + +This is all fine and dandy, but then the real trouble came in with passing this to lol*html. lol\_html doesn't have the concept of getting the children of a component (because this is designed to do *streaming* replacement of HTML elements), so in order to make this work in lol\_html I can't use that template function. I have to write it like this: + +```rust +use lol_html::{element, RewriteStrSettings}; + +let mut html = magic_get_html_for_post!(); + +let html = rewrite_str( + &html, + RewriteStrSettings { + element_content_handlers: vec![ + // ... + element!("xeblog-blockquote", |el| { + el.before("
> "); + el.after("
"); + el.remove_and_keep_content(); + }) + // .. + ], + ..RewriteStrSettings::default() + } +); +``` + +You can see how this would get fairly unmanintainable very quickly. + +At work I was exposed to a new technology called [MDX](https://mdxjs.com) that looks like it could really solve all these problems. It's a bit of an unholy combination of React and JSX with Markdown, but it's really cool. Instead of defining my components in bespoke syntaxes or in Rust, I can just write them in React and use them in my blog posts. This is really cool, and I'm excited to see what I can do with it. + +The biggest problem was the old format of these things: + + + These little conversation snippets were a huge pain to move over! + + +Previously they were done by [hacking up the markdown parser in a way that is known to cause cancer in the state of California](https://github.com/Xe/site/blob/cbdea8ba3fca9a663778af71f8df5965aeb6c090/lib/xesite_markdown/src/lib.rs#L50-L94), which made them look like this: + +```markdown +[Wow this is text that I am saying!](conversation://Mara/hacker) +``` + +With the lol\_html flow I had to explicitly namespace my HTML elements ad nauseum, so it looked like this: + +```html +Wow this is text I am saying! +``` + +But even this was annoying in practice because I could _not_ use newlines in the conversation snippets without breaking the hell out of everything in ways that were difficult to diagnose. I ended up using `
`, `
    `, `
  • `, and other such elements everywhere in ways that were hard to read and write: + +```markdown +Okay so when you use the +[rilkef method](/blog/experimental-rilkef-2018-11-30/) to dynamically +reparse the flux matricies, you need to follow these steps:
      +
    • First, desalinate the yolo manifold
    • +
    • Then make sure you have Ubuntu up to date
    • +
    • Finally, watch this video +to find out any missing steps
    +``` + +This sucked. Majorly. I hated it. I wanted to be able to write my conversations like this: + +```markdown + + Okay so when you use the + [rilkef method](/blog/experimental-rilkef-2018-11-30/) to dynamically + reparse the flux matricies, you need to follow these steps: + + - First, desalinate the yolo manifold + - Then make sure you have Ubuntu up to date + - Finally, watch [this video](https://youtu.be/MpJsYFZtQbw) to find out any missing steps + +``` + + + Okay so when you use the + [rilkef method](/blog/experimental-rilkef-2018-11-30/) to dynamically + reparse the flux matricies, you need to follow these steps: + + - First, desalinate the yolo manifold + - Then make sure you have Ubuntu up to date + - Finally, watch [this video](https://youtu.be/MpJsYFZtQbw) to find out any missing steps + + +This is the real strength of MDX. It combines React and Markdown to give you superpowers. + +## Migration + +The main pain point was migration. For the most part the "new style" syntax transferred over without basically any editing. I chose to fix some minor spelling and grammar errors, but most of it was migrated over fully intact. + +I probably missed something, and with the sheer number of articles I have (over 500 by the end of the year) I almost certainly missed something. Please [let me know](/contact/) if I did! Sorry! + +When it came to the CSS, I started with a blank HTML file and copied over rendered HTML from my website in production. Once I had the basic structure copied over, I started pouring over [Tailwind UI](https://tailwindui.com/) to make a short list of the components I wanted to play with. + +I had existing experience adding my Gruvbox inspired theme to Tailwind, so I copied over that Tailwind configuration file and went to down replicating the styles I had before, combining in parts from Tailwind UI and a few other places for inspiration. I had to make some minor changes to the colors, but for the most part it was a fairly straightforward process. + +The part I was most worried about was the [prose](https://tailwindcss.com/docs/typography-plugin) formatting in Tailwind. It didn't follow my old style of prose formatting, so I had to make a few minor changes. I'm not fully happy with this yet (it makes prose text a bit too dark for my tastes), but I'll get there in due time. + +## The light at the end of the tunnel + +As an added bonus of using Tailwind, React, and all that startup goop, I can make satirical [landing pages](/landing/alvis/) for fake products I make up. This is a huge win for me, because I absolutely love abstract methods and ways of making fun of my own industry. + + + Hilariously enough, when I published that landing page and shared it around, I + expected people to click _literally any_ of the links on it to see the + [associated blogpost](/blog/alvis/). Instead, people just commented on how + baity the page was. Some people thought it was serious. This was an even more + hilarious result than I thought. I'd have hoped that having the Enterprise + tier _list a price on the page_ would be a dead giveaway that it's a joke, but + I guess not. Same with the mention of artificial general intelligence. Oh + well, lessons learned I guess! + + +## Dynamic updating + +The biggest change in Xesite v4 is that it can now update itself dynamically. This is a huge win for me, because it means I can update my blog posts, resume, and other content without having to redeploy the entire server. All I do is push things to GitHub and it updates itself _within a minute_. + +This is thanks to me adopting a dystatic approach to my website. In essence, it boils down to this: the application itself serves a static site, but the static site is rebuilt every time something changes. + +This is a bit of a weird concept, so let me explain it in a bit more detail. I made a diagram of all of this that you will need to click on to expand, because it's a bit dense: + +
    + +When you think about it, a static site generator is really just a compiler. It takes input in the form of source files and outputs a folder with HTML in it. When I was evaluating static site generators, a feature of [Lume](https://lume.land) kept standing out for me: [shared data](https://lume.land/docs/creating-pages/shared-data/). + +A lot of my site's content is actually stored in a series of increasingly large [Dhall](https://dhall-lang.org) documents. This includes everything from my [salary transparency history](/salary-transparency/), the [signalboost](/signalboost/) page, and even key parts of my [resume](/resume/). I wanted to be able to use this data in my blog posts, but I didn't want to have to copy and paste it everywhere. + +I did [make a draft of v4 that changed everything over to TypeScript](https://github.com/Xe/site/tree/go/config) that'd be parsed on the fly using [tyson](https://github.com/jetpack-io/tyson), but I didn't like the idea of having everything in kinda hard to read files. There's a certain surreal beauty to the way I'm using Dhall here and I want to keep that dream alive. + +The way I hacked around this was by making the Go rebuild process [dump a bunch of Dhall data into Lume shared data](https://github.com/Xe/site/blob/6f8d93b9d8d8f9168fa0dfb88d755793ff6e770c/internal/lume/lume.go#L320-L340). Arguably this could be worked around if Lume supported loading Dhall data, but I just hacked it together using JSON in the meantime. This could probably be improved on in the future, but it has the advantage of working. + +Amazingly enough, this means I could slap [patron information](/patrons/) into the right place with the same flow. I don't have to do anything special to make this work, it just works. + +Combine this with dumping the right JSON file in the right place for [Typst](https://typst.app/) to pick up when building [my resume](/static/resume/resume.pdf) and you have a pretty powerful system. + +Once this all was working, I added in the dynamic updating system. This works like this: + +- The Fly server keeps a copy of my site's git repo on disk, cloning a new copy on application startup (TODO: fix) +- When I make commits to the site on GitHub, or [someone signs up on Patreon](https://patreon.com/cadey), they send webhooks to my website +- The webhooks trigger a rebuild, which fetches new commits from GitHub, and then rebuilds the site using the entire process I outlined above. + +This is how you get up to this point: + +
    + +It makes a bit more sense now! I'm really happy with how this turned out, and I'm excited to see what I can do with it in the future. + +I've looked around, and there doesn't seem to be a name for this concept. In order to trigger someone [calling me wrong on the Internet](https://xkcd.com/386/), I'm calling this a _dystatic_ approach. It's a dynamic website that rebuilds its static website when things change. + +## Fly + + + I got some free credits from Fly a while back for writing about them. Please + flavor your reading of this section with that in mind. Nothing about my setup + has a hard requirement on Fly, but the fact that they have anycast routing + _out of the box_ really makes it convenient for XeDN and xesite. + + +My website has a few moving components now. Here's a quick overview of what's going on: + +
    + +`xesite` is the binary that serves the website you are reading right now. It's what does all the rebuilds and stuff. It's written in Go, and it's what I'm most familiar with. + + + Didn't you rewrite it in Rust from Go a while ago? Why go back? + + + Go is my best language. It's not a perfect shining city on a hill, but I can + write and maintain it without thinking. I can't say the same for Rust yet. + Arguably there's nothing stopping it from being that way, but I wanted + something easier to implement because this was already _several months of + work_. Editing all of the articles took _forever_. + + +### patreon-saasproxy and OAuth2 ""fun"" + +When it starts up, it reaches out to [patreon-saasproxy](https://github.com/Xe/site/blob/6f8d93b9d8d8f9168fa0dfb88d755793ff6e770c/cmd/patreon-saasproxy/main.go#L1) fetch an authentication token for [Patreon](https://patreon.com). Originally, I was going to make it a full reverse proxy for the Patreon API, but the [Patreon API bindings I'm using](https://gopkg.in/mxpv/patreon-go.v1) didn't have support for this, so I just made it a token source. + +The Go oauth2 library seems to very much not be designed with this kind of usecase in mind. In order to get things working, I had to write my own [TokenSource](https://pkg.go.dev/golang.org/x/oauth2#TokenSource) like this: + +```go +type remoteTokenSource struct { + curr *oauth2.Token + lock sync.Mutex + remoteURL string + httpClient *http.Client +} + +func (r *remoteTokenSource) fetchToken() (*oauth2.Token, error) { + resp, err := r.httpClient.Get(r.remoteURL) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, web.NewError(http.StatusOK, resp) + } + + var tok oauth2.Token + if err := json.NewDecoder(resp.Body).Decode(&tok); err != nil { + return nil, err + } + + return &tok, nil +} + +func (r *remoteTokenSource) Token() (*oauth2.Token, error) { + r.lock.Lock() + defer r.lock.Unlock() + + if r.curr == nil { + tok, err := r.fetchToken() + if err != nil { + return nil, err + } + r.curr = tok + return tok, nil + } + + if r.curr.Expiry.Before(time.Now()) { + tok, err := r.fetchToken() + if err != nil { + return nil, err + } + r.curr = tok + } + + return r.curr, nil +} +``` + +It works, but it's kinda hacky. Ideally I'd like to make this a bit more generic in the future (so I can have it manage other tokens from different OAuth2 sources), but this has the advantage of working for now. I kinda hate how the Patreon API is abandonware, but I can vibe. + +### XeDN + +There's not currently a direct dependency between `xesite` and XeDN, but in practice everything `xesite` serves depends on XeDN in some way or another. If you want to read more about XeDN, you can read these posts: + +- [Announcing the glorious advent of XeDN](/blog/xedn/) +- [Site Update: CSS fixes](/blog/site-update-better-css/) +- [Fixing Xesite in reader mode and RSS readers](/vods/2023/reader-mode-css/) +- [Shouting at my editor](/vods/2023/cursorless/) + +### Mi + +I haven't really mentioned mi in much detail on my blog (and I am probably going to wait until I've rewritten a good portion of it to go into much detail), but it's basically a personal API server that does a bunch of things I find convenient for myself. + +One of those things is a bit of code that will grab my blog's JSONFeed, scrape it for new articles, and announce them in a few places. + + + I really wish this could include Patreon, but they seem to have no interest in + maintaining their API. I'm not sure it I want to reverse-engineer their webapp + to make this work, but I might have to. That's for another time though. + + +## Conclusion + +Xesite is here to stay. I hope this has given you an overview of everything that I've been up to with this. I'm really happy with how this turned out, and I'm excited to see what I can do with it in the future. + +Oh, by the way, because MDX lets me embed React components in my blog posts, I can do this: + +export function ChatFrame({ children }) { + return ( + <> +
    {children}
    + + ); +} + +export function ChatBubble({ + reply = false, + bg = "blue-dark", + fg = "slate-50", + children, +}) { + return ( +
    +
    +
    +
    + {children} +
    +
    +
    +
    + ); +} + + + + I can embed arbitrary HTML and React components in my blog posts now! This + is the crucial part of how my recent story posts work. Just imagine what I + can do with this! + + + +### Things I learned + +[Semantic import versioning](https://go.dev/blog/versioning-proposal) isn't actually that bad in practice. I decided to use it when writing the code for this version of the site because I wanted to give it a fair assessment. It's fine. I don't agree with the design decisions, but it's fine in practice. + +I have _way more articles_ than I thought I did. I knew I had a lot, but having to touch every single file made me realize just how much I've written over the years. I'm really proud of myself for this. + +React and Tailwind are stupidly powerful. [Xeact](/blog/xeact-0.0.69-2021-11-18/) isn't good enough for my needs anymore because I've outgrown it. Kinda sucks to be in this situation, but I am happy that I was able to use Xeact to help me learn what I needed to learn to make this work. + +### Bugs I need to fix + +- The site doesn't build the series index or tag index pages yet. Series indices will be created soon, but I'm not sure how I want to handle tags yet. +- The site doesn't show read time in minutes yet. I'm waiting on Lume to patch [pagefind](https://pagefind.app/) to handle this better. +- Search is super jank via [pagefind](https://pagefind.app/). I'm going to be working on making this better, but this is going to have to do for the time being. +- The site doesn't have a proper 404 page yet. +- The [🥺 post](/blog/xn--ts9h/) had to be renamed and not all of the attempts I've made to forward the old name to the new place have worked. + +Here's to the next hundred articles. Stay safe out there! \ No newline at end of file -- cgit v1.2.3