[Archived] Archived WIP of vielle.dev

Compare changes

Choose any two refs to compare.

-1
.gitignore
··· 22 22 23 23 # jetbrains setting folder 24 24 .idea/ 25 - .vscode/*
-3
.simple-git-hooks.json
··· 1 - { 2 - "pre-commit": "pnpm pretty-quick --staged" 3 - }
+3
.vscode/settings.json
··· 1 + { 2 + "cSpell.words": ["titlebar"] 3 + }
+3 -15
astro.config.mjs
··· 1 1 // @ts-check 2 2 import { defineConfig } from "astro/config"; 3 + 3 4 import mdx from "@astrojs/mdx"; 5 + 4 6 import sitemap from "@astrojs/sitemap"; 5 - 6 - import { rehypeAccessibleEmojis } from "rehype-accessible-emojis"; 7 - import rehypeCustomHtml from "./rehype-custom-html"; 8 7 9 8 // https://astro.build/config 10 9 export default defineConfig({ 11 10 integrations: [mdx(), sitemap()], 12 11 13 12 output: "server", 14 - site: "https://vielle.dev", 15 13 16 - markdown: { 17 - // @ts-expect-error idk why this gets flagged as wrong 18 - rehypePlugins: [rehypeAccessibleEmojis, rehypeCustomHtml], 19 - shikiConfig: { 20 - themes: { 21 - dark: "catppuccin-frappe", 22 - light: "github-light-high-contrast", 23 - }, 24 - defaultColor: false, 25 - }, 26 - }, 14 + site: "https://vielle.dev", 27 15 });
+6 -12
package.json
··· 12 12 }, 13 13 "dependencies": { 14 14 "@astrojs/check": "^0.9.4", 15 - "@astrojs/mdx": "^4.3.0", 16 - "@astrojs/rss": "^4.0.12", 17 - "@astrojs/sitemap": "^3.4.1", 18 - "astro": "5.11.0", 15 + "@astrojs/mdx": "^4.2.6", 16 + "@astrojs/rss": "^4.0.11", 17 + "@astrojs/sitemap": "^3.4.0", 18 + "astro": "5.7.13", 19 19 "lunarphase-js": "^2.0.3", 20 20 "markdown-it": "^14.1.0", 21 - "rehype-accessible-emojis": "^0.3.2", 22 - "remark-toc": "^9.0.0", 23 - "typescript": "^5.8.3", 24 - "unified": "^11.0.5" 21 + "typescript": "^5.8.3" 25 22 }, 26 23 "devDependencies": { 27 - "@types/hast": "^3.0.4", 28 24 "prettier": "3.5.3", 29 - "prettier-plugin-astro": "0.14.1", 30 - "pretty-quick": "^4.1.1", 31 - "simple-git-hooks": "^2.13.0" 25 + "prettier-plugin-astro": "0.14.1" 32 26 } 33 27 }
+48 -258
pnpm-lock.yaml
··· 11 11 specifier: ^0.9.4 12 12 version: 0.9.4(prettier-plugin-astro@0.14.1)(prettier@3.5.3)(typescript@5.8.3) 13 13 "@astrojs/mdx": 14 - specifier: ^4.3.0 15 - version: 4.3.0(astro@5.11.0(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0)) 14 + specifier: ^4.2.6 15 + version: 4.2.6(astro@5.7.13(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0)) 16 16 "@astrojs/rss": 17 - specifier: ^4.0.12 18 - version: 4.0.12 17 + specifier: ^4.0.11 18 + version: 4.0.11 19 19 "@astrojs/sitemap": 20 - specifier: ^3.4.1 21 - version: 3.4.1 20 + specifier: ^3.4.0 21 + version: 3.4.0 22 22 astro: 23 - specifier: 5.11.0 24 - version: 5.11.0(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0) 23 + specifier: 5.7.13 24 + version: 5.7.13(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0) 25 25 lunarphase-js: 26 26 specifier: ^2.0.3 27 27 version: 2.0.3 28 28 markdown-it: 29 29 specifier: ^14.1.0 30 30 version: 14.1.0 31 - rehype-accessible-emojis: 32 - specifier: ^0.3.2 33 - version: 0.3.2 34 - remark-toc: 35 - specifier: ^9.0.0 36 - version: 9.0.0 37 31 typescript: 38 32 specifier: ^5.8.3 39 33 version: 5.8.3 40 - unified: 41 - specifier: ^11.0.5 42 - version: 11.0.5 43 34 devDependencies: 44 - "@types/hast": 45 - specifier: ^3.0.4 46 - version: 3.0.4 47 35 prettier: 48 36 specifier: 3.5.3 49 37 version: 3.5.3 50 38 prettier-plugin-astro: 51 39 specifier: 0.14.1 52 40 version: 0.14.1 53 - pretty-quick: 54 - specifier: ^4.1.1 55 - version: 4.1.1(prettier@3.5.3) 56 - simple-git-hooks: 57 - specifier: ^2.13.0 58 - version: 2.13.0 59 41 60 42 packages: 61 43 "@astrojs/check@0.9.4": ··· 73 55 integrity: sha512-7bCjW6tVDpUurQLeKBUN9tZ5kSv5qYrGmcn0sG0IwacL7isR2ZbyyA3AdZ4uxsuUFOS2SlgReTH7wkxO6zpqWA==, 74 56 } 75 57 76 - "@astrojs/compiler@2.12.2": 77 - resolution: 78 - { 79 - integrity: sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==, 80 - } 81 - 82 58 "@astrojs/internal-helpers@0.6.1": 83 59 resolution: 84 60 { ··· 100 76 prettier-plugin-astro: 101 77 optional: true 102 78 103 - "@astrojs/markdown-remark@6.3.2": 79 + "@astrojs/markdown-remark@6.3.1": 104 80 resolution: 105 81 { 106 - integrity: sha512-bO35JbWpVvyKRl7cmSJD822e8YA8ThR/YbUsciWNA7yTcqpIAL2hJDToWP5KcZBWxGT6IOdOkHSXARSNZc4l/Q==, 82 + integrity: sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg==, 107 83 } 108 84 109 - "@astrojs/mdx@4.3.0": 85 + "@astrojs/mdx@4.2.6": 110 86 resolution: 111 87 { 112 - integrity: sha512-OGX2KvPeBzjSSKhkCqrUoDMyzFcjKt5nTE5SFw3RdoLf0nrhyCXBQcCyclzWy1+P+XpOamn+p+hm1EhpCRyPxw==, 88 + integrity: sha512-0i/GmOm6d0qq1/SCfcUgY/IjDc/bS0i42u7h85TkPFBmlFOcBZfkYhR5iyz6hZLwidvJOEq5yGfzt9B1Azku4w==, 113 89 } 114 - engines: { node: 18.20.8 || ^20.3.0 || >=22.0.0 } 90 + engines: { node: ^18.17.1 || ^20.3.0 || >=22.0.0 } 115 91 peerDependencies: 116 92 astro: ^5.0.0 117 93 118 - "@astrojs/prism@3.3.0": 94 + "@astrojs/prism@3.2.0": 119 95 resolution: 120 96 { 121 - integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==, 97 + integrity: sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw==, 122 98 } 123 - engines: { node: 18.20.8 || ^20.3.0 || >=22.0.0 } 99 + engines: { node: ^18.17.1 || ^20.3.0 || >=22.0.0 } 124 100 125 - "@astrojs/rss@4.0.12": 101 + "@astrojs/rss@4.0.11": 126 102 resolution: 127 103 { 128 - integrity: sha512-O5yyxHuDVb6DQ6VLOrbUVFSm+NpObulPxjs6XT9q3tC+RoKbN4HXMZLpv0LvXd1qdAjzVgJ1NFD+zKHJNDXikw==, 104 + integrity: sha512-3e3H8i6kc97KGnn9iaZBJpIkdoQi8MmR5zH5R+dWsfCM44lLTszOqy1OBfGGxDt56mpQkYVtZJWoxMyWuUZBfw==, 129 105 } 130 106 131 - "@astrojs/sitemap@3.4.1": 107 + "@astrojs/sitemap@3.4.0": 132 108 resolution: 133 109 { 134 - integrity: sha512-VjZvr1e4FH6NHyyHXOiQgLiw94LnCVY4v06wN/D0gZKchTMkg71GrAHJz81/huafcmavtLkIv26HnpfDq6/h/Q==, 110 + integrity: sha512-C5m/xsKvRSILKM3hy47n5wKtTQtJXn8epoYuUmCCstaE9XBt20yInym3Bz2uNbEiNfv11bokoW0MqeXPIvjFIQ==, 135 111 } 136 112 137 - "@astrojs/telemetry@3.3.0": 113 + "@astrojs/telemetry@3.2.1": 138 114 resolution: 139 115 { 140 - integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==, 116 + integrity: sha512-SSVM820Jqc6wjsn7qYfV9qfeQvePtVc1nSofhyap7l0/iakUKywj3hfy3UJAOV4sGV4Q/u450RD4AaCaFvNPlg==, 141 117 } 142 - engines: { node: 18.20.8 || ^20.3.0 || >=22.0.0 } 118 + engines: { node: ^18.17.1 || ^20.3.0 || >=22.0.0 } 143 119 144 120 "@astrojs/yaml2ts@0.2.2": 145 121 resolution: ··· 948 924 integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==, 949 925 } 950 926 951 - "@types/ungap__structured-clone@1.2.0": 952 - resolution: 953 - { 954 - integrity: sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==, 955 - } 956 - 957 927 "@types/unist@2.0.11": 958 928 resolution: 959 929 { ··· 1117 1087 } 1118 1088 hasBin: true 1119 1089 1120 - astro@5.11.0: 1090 + astro@5.7.13: 1121 1091 resolution: 1122 1092 { 1123 - integrity: sha512-MEICntERthUxJPSSDsDiZuwiCMrsaYy3fnDhp4c6ScUfldCB8RBnB/myYdpTFXpwYBy6SgVsHQ1H4MuuA7ro/Q==, 1093 + integrity: sha512-cRGq2llKOhV3XMcYwQpfBIUcssN6HEK5CRbcMxAfd9OcFhvWE7KUy50zLioAZVVl3AqgUTJoNTlmZfD2eG0G1w==, 1124 1094 } 1125 1095 engines: 1126 - { node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: ">=9.6.5", pnpm: ">=7.1.0" } 1096 + { node: ^18.17.1 || ^20.3.0 || >=22.0.0, npm: ">=9.6.5", pnpm: ">=7.1.0" } 1127 1097 hasBin: true 1128 1098 1129 1099 axobject-query@4.1.0: ··· 1587 1557 integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==, 1588 1558 } 1589 1559 1590 - fast-xml-parser@5.2.3: 1560 + fast-xml-parser@4.5.3: 1591 1561 resolution: 1592 1562 { 1593 - integrity: sha512-OdCYfRqfpuLUFonTNjvd30rCBZUneHpSQkCqfaeWQ9qrKcl6XlWeDBNVwGb+INAIxRshuN2jF+BE0L6gbBO2mw==, 1563 + integrity: sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==, 1594 1564 } 1595 1565 hasBin: true 1596 1566 ··· 1618 1588 } 1619 1589 engines: { node: ">=8" } 1620 1590 1621 - find-up@5.0.0: 1622 - resolution: 1623 - { 1624 - integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, 1625 - } 1626 - engines: { node: ">=10" } 1627 - 1628 1591 flattie@1.1.1: 1629 1592 resolution: 1630 1593 { ··· 1651 1614 } 1652 1615 engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } 1653 1616 os: [darwin] 1654 - 1655 - gemoji@4.2.1: 1656 - resolution: 1657 - { 1658 - integrity: sha512-V9lUpRSn+KQGavZx8Pk+6mxG3kaz21ae2kTCXuT36KaRPNgYU8eHtj/RcUCNFVvmwppsYYz3nnNS9lmcP5kTsg==, 1659 - } 1660 1617 1661 1618 get-caller-file@2.0.5: 1662 1619 resolution: ··· 1703 1660 integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==, 1704 1661 } 1705 1662 1706 - hast-util-is-element@1.1.0: 1707 - resolution: 1708 - { 1709 - integrity: sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==, 1710 - } 1711 - 1712 1663 hast-util-is-element@3.0.0: 1713 1664 resolution: 1714 1665 { ··· 1786 1737 { 1787 1738 integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==, 1788 1739 } 1789 - 1790 - ignore@7.0.5: 1791 - resolution: 1792 - { 1793 - integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, 1794 - } 1795 - engines: { node: ">= 4" } 1796 1740 1797 1741 import-meta-resolve@4.1.0: 1798 1742 resolution: ··· 1945 1889 integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==, 1946 1890 } 1947 1891 1948 - locate-path@6.0.0: 1949 - resolution: 1950 - { 1951 - integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, 1952 - } 1953 - engines: { node: ">=10" } 1954 - 1955 1892 lodash@4.17.21: 1956 1893 resolution: 1957 1894 { ··· 2108 2045 resolution: 2109 2046 { 2110 2047 integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==, 2111 - } 2112 - 2113 - mdast-util-toc@7.1.0: 2114 - resolution: 2115 - { 2116 - integrity: sha512-2TVKotOQzqdY7THOdn2gGzS9d1Sdd66bvxUyw3aNpWfcPXCLYSJCCgfPy30sEtuzkDraJgqF35dzgmz6xlvH/w==, 2117 2048 } 2118 2049 2119 2050 mdn-data@2.12.2: ··· 2352 2283 } 2353 2284 engines: { node: ">=8.6" } 2354 2285 2355 - mri@1.2.0: 2356 - resolution: 2357 - { 2358 - integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==, 2359 - } 2360 - engines: { node: ">=4" } 2361 - 2362 2286 mrmime@2.0.1: 2363 2287 resolution: 2364 2288 { ··· 2454 2378 integrity: sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==, 2455 2379 } 2456 2380 2457 - p-limit@3.1.0: 2458 - resolution: 2459 - { 2460 - integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, 2461 - } 2462 - engines: { node: ">=10" } 2463 - 2464 2381 p-limit@6.2.0: 2465 2382 resolution: 2466 2383 { 2467 2384 integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==, 2468 2385 } 2469 2386 engines: { node: ">=18" } 2470 - 2471 - p-locate@5.0.0: 2472 - resolution: 2473 - { 2474 - integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, 2475 - } 2476 - engines: { node: ">=10" } 2477 2387 2478 2388 p-queue@8.1.0: 2479 2389 resolution: ··· 2524 2434 { 2525 2435 integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==, 2526 2436 } 2527 - 2528 - path-exists@4.0.0: 2529 - resolution: 2530 - { 2531 - integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, 2532 - } 2533 - engines: { node: ">=8" } 2534 2437 2535 2438 picocolors@1.1.1: 2536 2439 resolution: ··· 2582 2485 engines: { node: ">=14" } 2583 2486 hasBin: true 2584 2487 2585 - pretty-quick@4.1.1: 2586 - resolution: 2587 - { 2588 - integrity: sha512-9Ud0l/CspNTmyIdYac9X7Inb3o8fuUsw+1zJFvCGn+at0t1UwUcUdo2RSZ41gcmfLv1fxgWQxWEfItR7CBwugg==, 2589 - } 2590 - engines: { node: ">=14" } 2591 - hasBin: true 2592 - peerDependencies: 2593 - prettier: ^3.0.0 2594 - 2595 2488 prismjs@1.30.0: 2596 2489 resolution: 2597 2490 { ··· 2686 2579 integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==, 2687 2580 } 2688 2581 2689 - rehype-accessible-emojis@0.3.2: 2690 - resolution: 2691 - { 2692 - integrity: sha512-kChZo+EZsuFQYHUPu6kOZFjDrG7UtQdGxkrCvHBVo9ariKPL6S68QdPVxLxwcAtZSRZIXZhDuTJHgIM8KW24Qw==, 2693 - } 2694 - 2695 2582 rehype-parse@9.0.1: 2696 2583 resolution: 2697 2584 { ··· 2759 2646 integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==, 2760 2647 } 2761 2648 2762 - remark-toc@9.0.0: 2763 - resolution: 2764 - { 2765 - integrity: sha512-KJ9txbo33GjDAV1baHFze7ij4G8c7SGYoY8Kzsm2gzFpbhL/bSoVpMMzGa3vrNDSWASNd/3ppAqL7cP2zD6JIA==, 2766 - } 2767 - 2768 2649 request-light@0.5.8: 2769 2650 resolution: 2770 2651 { ··· 2881 2762 integrity: sha512-wuxzZzQG8kvZndD7nustrNFIKYJ1jJoWIPaBpVe2+KHSvtzMi4SBjOxrigs8qeqce/l3U0cwiC+VAkLKSunHQQ==, 2882 2763 } 2883 2764 2884 - simple-git-hooks@2.13.0: 2885 - resolution: 2886 - { 2887 - integrity: sha512-N+goiLxlkHJlyaYEglFypzVNMaNplPAk5syu0+OPp/Bk6dwVoXF6FfOw2vO0Dp+JHsBaI+w6cm8TnFl2Hw6tDA==, 2888 - } 2889 - hasBin: true 2890 - 2891 2765 simple-swizzle@0.2.2: 2892 2766 resolution: 2893 2767 { ··· 2975 2849 } 2976 2850 engines: { node: ">=12" } 2977 2851 2978 - strnum@2.1.1: 2852 + strnum@1.1.2: 2979 2853 resolution: 2980 2854 { 2981 - integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==, 2855 + integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==, 2982 2856 } 2983 2857 2984 2858 style-to-js@1.1.16: ··· 3147 3021 resolution: 3148 3022 { 3149 3023 integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==, 3150 - } 3151 - 3152 - unist-util-flatmap@1.0.0: 3153 - resolution: 3154 - { 3155 - integrity: sha512-IG32jcKJlhARCYT2LsYPJWdoXYkzz3ESAdl1aa2hn9Auh+cgUmU6wgkII4yCc/1GgeWibRdELdCZh/p3QKQ1dQ==, 3156 3024 } 3157 3025 3158 3026 unist-util-is@6.0.0: ··· 3607 3475 } 3608 3476 engines: { node: ">=12" } 3609 3477 3610 - yocto-queue@0.1.0: 3611 - resolution: 3612 - { 3613 - integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, 3614 - } 3615 - engines: { node: ">=10" } 3616 - 3617 3478 yocto-queue@1.2.1: 3618 3479 resolution: 3619 3480 { ··· 3678 3539 3679 3540 "@astrojs/compiler@2.12.0": {} 3680 3541 3681 - "@astrojs/compiler@2.12.2": {} 3682 - 3683 3542 "@astrojs/internal-helpers@0.6.1": {} 3684 3543 3685 3544 "@astrojs/language-server@2.15.4(prettier-plugin-astro@0.14.1)(prettier@3.5.3)(typescript@5.8.3)": ··· 3708 3567 transitivePeerDependencies: 3709 3568 - typescript 3710 3569 3711 - "@astrojs/markdown-remark@6.3.2": 3570 + "@astrojs/markdown-remark@6.3.1": 3712 3571 dependencies: 3713 3572 "@astrojs/internal-helpers": 0.6.1 3714 - "@astrojs/prism": 3.3.0 3573 + "@astrojs/prism": 3.2.0 3715 3574 github-slugger: 2.0.0 3716 3575 hast-util-from-html: 2.0.3 3717 3576 hast-util-to-text: 4.0.2 ··· 3734 3593 transitivePeerDependencies: 3735 3594 - supports-color 3736 3595 3737 - "@astrojs/mdx@4.3.0(astro@5.11.0(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0))": 3596 + "@astrojs/mdx@4.2.6(astro@5.7.13(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0))": 3738 3597 dependencies: 3739 - "@astrojs/markdown-remark": 6.3.2 3598 + "@astrojs/markdown-remark": 6.3.1 3740 3599 "@mdx-js/mdx": 3.1.0(acorn@8.14.1) 3741 3600 acorn: 8.14.1 3742 - astro: 5.11.0(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0) 3601 + astro: 5.7.13(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0) 3743 3602 es-module-lexer: 1.7.0 3744 3603 estree-util-visit: 2.0.0 3745 3604 hast-util-to-html: 9.0.5 ··· 3753 3612 transitivePeerDependencies: 3754 3613 - supports-color 3755 3614 3756 - "@astrojs/prism@3.3.0": 3615 + "@astrojs/prism@3.2.0": 3757 3616 dependencies: 3758 3617 prismjs: 1.30.0 3759 3618 3760 - "@astrojs/rss@4.0.12": 3619 + "@astrojs/rss@4.0.11": 3761 3620 dependencies: 3762 - fast-xml-parser: 5.2.3 3621 + fast-xml-parser: 4.5.3 3763 3622 kleur: 4.1.5 3764 3623 3765 - "@astrojs/sitemap@3.4.1": 3624 + "@astrojs/sitemap@3.4.0": 3766 3625 dependencies: 3767 3626 sitemap: 8.0.0 3768 3627 stream-replace-string: 2.0.0 3769 3628 zod: 3.25.7 3770 3629 3771 - "@astrojs/telemetry@3.3.0": 3630 + "@astrojs/telemetry@3.2.1": 3772 3631 dependencies: 3773 3632 ci-info: 4.2.0 3774 3633 debug: 4.4.1 ··· 4172 4031 4173 4032 "@types/sax@1.2.7": 4174 4033 dependencies: 4175 - "@types/node": 22.15.20 4176 - 4177 - "@types/ungap__structured-clone@1.2.0": {} 4034 + "@types/node": 17.0.45 4178 4035 4179 4036 "@types/unist@2.0.11": {} 4180 4037 ··· 4274 4131 4275 4132 astring@1.9.0: {} 4276 4133 4277 - astro@5.11.0(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0): 4134 + astro@5.7.13(@types/node@22.15.20)(rollup@4.41.0)(typescript@5.8.3)(yaml@2.8.0): 4278 4135 dependencies: 4279 - "@astrojs/compiler": 2.12.2 4136 + "@astrojs/compiler": 2.12.0 4280 4137 "@astrojs/internal-helpers": 0.6.1 4281 - "@astrojs/markdown-remark": 6.3.2 4282 - "@astrojs/telemetry": 3.3.0 4138 + "@astrojs/markdown-remark": 6.3.1 4139 + "@astrojs/telemetry": 3.2.1 4283 4140 "@capsizecss/unpack": 2.4.0 4284 4141 "@oslojs/encoding": 1.1.0 4285 4142 "@rollup/pluginutils": 5.1.4(rollup@4.41.0) ··· 4306 4163 github-slugger: 2.0.0 4307 4164 html-escaper: 3.0.3 4308 4165 http-cache-semantics: 4.2.0 4309 - import-meta-resolve: 4.1.0 4310 4166 js-yaml: 4.1.0 4311 4167 kleur: 4.1.5 4312 4168 magic-string: 0.30.17 ··· 4627 4483 4628 4484 fast-uri@3.0.6: {} 4629 4485 4630 - fast-xml-parser@5.2.3: 4486 + fast-xml-parser@4.5.3: 4631 4487 dependencies: 4632 - strnum: 2.1.1 4488 + strnum: 1.1.2 4633 4489 4634 4490 fastq@1.19.1: 4635 4491 dependencies: ··· 4643 4499 dependencies: 4644 4500 to-regex-range: 5.0.1 4645 4501 4646 - find-up@5.0.0: 4647 - dependencies: 4648 - locate-path: 6.0.0 4649 - path-exists: 4.0.0 4650 - 4651 4502 flattie@1.1.1: {} 4652 4503 4653 4504 fontace@0.3.0: ··· 4669 4520 4670 4521 fsevents@2.3.3: 4671 4522 optional: true 4672 - 4673 - gemoji@4.2.1: {} 4674 4523 4675 4524 get-caller-file@2.0.5: {} 4676 4525 ··· 4713 4562 vfile: 6.0.3 4714 4563 vfile-location: 5.0.3 4715 4564 web-namespaces: 2.0.1 4716 - 4717 - hast-util-is-element@1.1.0: {} 4718 4565 4719 4566 hast-util-is-element@3.0.0: 4720 4567 dependencies: ··· 4829 4676 html-void-elements@3.0.0: {} 4830 4677 4831 4678 http-cache-semantics@4.2.0: {} 4832 - 4833 - ignore@7.0.5: {} 4834 4679 4835 4680 import-meta-resolve@4.1.0: {} 4836 4681 ··· 4892 4737 dependencies: 4893 4738 uc.micro: 2.1.0 4894 4739 4895 - locate-path@6.0.0: 4896 - dependencies: 4897 - p-locate: 5.0.0 4898 - 4899 4740 lodash@4.17.21: {} 4900 4741 4901 4742 longest-streak@3.1.0: {} ··· 5095 4936 mdast-util-to-string@4.0.0: 5096 4937 dependencies: 5097 4938 "@types/mdast": 4.0.4 5098 - 5099 - mdast-util-toc@7.1.0: 5100 - dependencies: 5101 - "@types/mdast": 4.0.4 5102 - "@types/ungap__structured-clone": 1.2.0 5103 - "@ungap/structured-clone": 1.3.0 5104 - github-slugger: 2.0.0 5105 - mdast-util-to-string: 4.0.0 5106 - unist-util-is: 6.0.0 5107 - unist-util-visit: 5.0.0 5108 4939 5109 4940 mdn-data@2.12.2: {} 5110 4941 ··· 5381 5212 braces: 3.0.3 5382 5213 picomatch: 2.3.1 5383 5214 5384 - mri@1.2.0: {} 5385 - 5386 5215 mrmime@2.0.1: {} 5387 5216 5388 5217 ms@2.1.3: {} ··· 5423 5252 regex: 6.0.1 5424 5253 regex-recursion: 6.0.2 5425 5254 5426 - p-limit@3.1.0: 5427 - dependencies: 5428 - yocto-queue: 0.1.0 5429 - 5430 5255 p-limit@6.2.0: 5431 5256 dependencies: 5432 5257 yocto-queue: 1.2.1 5433 - 5434 - p-locate@5.0.0: 5435 - dependencies: 5436 - p-limit: 3.1.0 5437 5258 5438 5259 p-queue@8.1.0: 5439 5260 dependencies: ··· 5471 5292 5472 5293 path-browserify@1.0.1: {} 5473 5294 5474 - path-exists@4.0.0: {} 5475 - 5476 5295 picocolors@1.1.1: {} 5477 5296 5478 5297 picomatch@2.3.1: {} ··· 5496 5315 5497 5316 prettier@3.5.3: {} 5498 5317 5499 - pretty-quick@4.1.1(prettier@3.5.3): 5500 - dependencies: 5501 - find-up: 5.0.0 5502 - ignore: 7.0.5 5503 - mri: 1.2.0 5504 - picocolors: 1.1.1 5505 - picomatch: 4.0.2 5506 - prettier: 3.5.3 5507 - tinyexec: 0.3.2 5508 - tslib: 2.8.1 5509 - 5510 5318 prismjs@1.30.0: {} 5511 5319 5512 5320 prompts@2.4.2: ··· 5566 5374 dependencies: 5567 5375 regex-utilities: 2.3.0 5568 5376 5569 - rehype-accessible-emojis@0.3.2: 5570 - dependencies: 5571 - emoji-regex: 8.0.0 5572 - gemoji: 4.2.1 5573 - hast-util-is-element: 1.1.0 5574 - unist-util-flatmap: 1.0.0 5575 - 5576 5377 rehype-parse@9.0.1: 5577 5378 dependencies: 5578 5379 "@types/hast": 3.0.4 ··· 5654 5455 mdast-util-to-markdown: 2.1.2 5655 5456 unified: 11.0.5 5656 5457 5657 - remark-toc@9.0.0: 5658 - dependencies: 5659 - "@types/mdast": 4.0.4 5660 - mdast-util-toc: 7.1.0 5661 - 5662 5458 request-light@0.5.8: {} 5663 5459 5664 5460 request-light@0.7.0: {} ··· 5774 5570 "@shikijs/vscode-textmate": 10.0.2 5775 5571 "@types/hast": 3.0.4 5776 5572 5777 - simple-git-hooks@2.13.0: {} 5778 - 5779 5573 simple-swizzle@0.2.2: 5780 5574 dependencies: 5781 5575 is-arrayish: 0.3.2 ··· 5825 5619 dependencies: 5826 5620 ansi-regex: 6.1.0 5827 5621 5828 - strnum@2.1.1: {} 5622 + strnum@1.1.2: {} 5829 5623 5830 5624 style-to-js@1.1.16: 5831 5625 dependencies: ··· 5914 5708 "@types/unist": 3.0.3 5915 5709 unist-util-is: 6.0.0 5916 5710 5917 - unist-util-flatmap@1.0.0: {} 5918 - 5919 5711 unist-util-is@6.0.0: 5920 5712 dependencies: 5921 5713 "@types/unist": 3.0.3 ··· 6171 5963 string-width: 4.2.3 6172 5964 y18n: 5.0.8 6173 5965 yargs-parser: 21.1.1 6174 - 6175 - yocto-queue@0.1.0: {} 6176 5966 6177 5967 yocto-queue@1.2.1: {} 6178 5968
-140
posts/full-test.md
··· 1 - --- 2 - title: Full Test 3 - date: 3000-12-31 4 - colour: "#008282" 5 - image: "mc_map_art.png" 6 - --- 7 - 8 - ## this is 9 - 10 - ### simply 11 - 12 - #### a 13 - 14 - ##### test 15 - 16 - ###### i wouldnt use absurd headings in the wild, just h2 MAYBE h3 17 - 18 - look we r testinng!! 19 - 20 - ## normie syntax 21 - 22 - ### Paragraphs 23 - 24 - here is a paragraph 25 - 26 - and here is another 27 - 28 - Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 29 - 30 - ::breakout::test:: Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 31 - 32 - ::full-width::bg-red::@div::@nest:: Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 33 - 34 - ::full-width::bg-orange::@div::@nest:: Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 35 - 36 - ::full-width::bg-yellow::@div::@nest:: Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 37 - 38 - ::full-width::bg-green::@div::@nest:: Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 39 - 40 - ::full-width::bg-blue::@div::@nest:: Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 41 - 42 - ::full-width::bg-purple::@div::@nest:: Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 43 - 44 - ::breakout:: ![small left | ](./assets/minecraft.png) Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 45 - 46 - Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos. 47 - 48 - paragraph with **_strong emph_**, **\*strong** in emph\*, **_emph_ in strong**, **in strong _emph_**, and \*in emph **strong\*** but not ~~this text~~ bc i said so 49 - 50 - now heres a paragraph with a [link](/blog "Goes to blog") which goes to blog, [a link](https://vielle.dev/) which points to my site, [an unvisited link (DONT CLICK)](https://thissitedoesnotexist.com/fake_page), and a link to <https://deer.social> 51 - 52 - ### Code 53 - 54 - ```html 55 - <h1>Code</h1> 56 - <p>Theres more code</p> 57 - <!-- and then some more --> 58 - wow it just keeps going 59 - <style> 60 - this { 61 - size: long; 62 - } 63 - </style> 64 - ``` 65 - 66 - ``` 67 - This is code with a really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really really long line 68 - ``` 69 - 70 - ``` 71 - tinycode 72 - ``` 73 - 74 - heres sopme `inline` code 75 - 76 - ### Tables 77 - 78 - | this | is | 79 - | ---- | :---: | 80 - | a | table | 81 - | a | table | 82 - | a | table | 83 - | a | table | 84 - 85 - ### Blockquotes 86 - 87 - > and this, a block quote 88 - > which is multiline 89 - 90 - > and heres another 91 - 92 - ### Lists 93 - 94 - #### Unordered 95 - 96 - - an unordered list 97 - - with nesting 98 - - and more 99 - - going back 100 - - again 101 - 102 - #### Ordered 103 - 104 - 1. an unordered list 105 - 2. which has 106 - 1. nesting 107 - 2. high numbers 108 - 109 - #### Check 110 - 111 - - [ ] make this look good 112 - - [ ] make `/blog` look good 113 - - [x] oh yeah that was an inline code ๐Ÿ’ช 114 - 115 - ## fancy syntax 116 - 117 - ### blockquote flags 118 - 119 - > $NOTE 120 - > This one is a note 121 - 122 - > $ALERT 123 - > This one is another keyword 124 - 125 - > $NOTE 126 - > this can be achived by adding `$FLAG` to the first line of a blockquote (make sure to add the double space) 127 - 128 - ### Image 129 - 130 - ![An unimportiant image](./assets/minecraft.png) 131 - 132 - ![small left | An unimportiant image](./assets/minecraft.png) heres an image which should be on the right while this text wraps around it? i hope? make sure the image goes first tho !!!! 133 - 134 - > $INFO 135 - > image flags go in alt text 136 - > if alt text has a pipe (|), there are flags 137 - > all words up to the first pipe are treated as flags in a space seperated list 138 - > they are added to the data tag as `[data-img-flag--<name>="true"]` 139 - 140 - ![small centre | An unimportiant image](./assets/minecraft.png)
+7 -1
posts/test.mdx
··· 2 2 title: Test Post 3 3 --- 4 4 5 + import Balloon from "@components/blog/balloon.svelte"; 6 + 5 7 whats this about dawg 6 8 7 - (Vi a vis .MDX) 9 + <div style="padding: 15rem;"></div> 10 + 11 + <div style="position: absolute"> 12 + <Balloon client:load id={0} boundingWidth={300} boundingHeight={0} /> 13 + </div>
-175
rehype-custom-html.ts
··· 1 - import type { Plugin } from "unified"; 2 - import type { 3 - Root, 4 - Element, 5 - Node, 6 - ElementContent, 7 - RootContent, 8 - Text, 9 - } from "hast"; 10 - type Options = {}; 11 - 12 - /* 13 - blockquote flags go in the first line 14 - they are formatted as: 15 - `$FLAG `, where `FLAG` is the flag name 16 - there can only be one flag per blockquote 17 - */ 18 - 19 - function blockquote(node: Element) { 20 - for (const child of node.children) { 21 - if (child.type === "element" && child.children[0].type === "text") { 22 - const flag = child.children[0].value.match(/(?<=^\$).*/gm); 23 - if (flag?.length !== 1) continue; 24 - child.children.shift(); 25 - // finiky to get types working bc shift mutation etc 26 - if ( 27 - (child.children[0] as Node).type === "element" && 28 - (child.children[0] as Node as Element).tagName === "br" 29 - ) 30 - child.children.shift(); 31 - 32 - node.properties[`data-bq-flag--${flag[0].toLowerCase()}`] = true; 33 - } 34 - } 35 - } 36 - 37 - /* 38 - image flags go in alt text 39 - if alt text has a pipe (|), there are flags 40 - all words up to the first pipe are treated as flags in a space seperated list 41 - they are added to the data tag as [data-img-flag--<name>="true"] 42 - */ 43 - 44 - function image(node: Element) { 45 - // get alt; throw error if missing; convert to string 46 - const alt = ( 47 - node.properties.alt ?? 48 - (() => { 49 - throw new Error("NO ALT TEXT!!!"); 50 - })() 51 - ).toString(); 52 - 53 - // match section before | 54 - const prefixes = alt.match(/.*?(?= \|.*)/gm); 55 - if (!prefixes) return; 56 - 57 - node.properties.alt = alt.match(/(?<= \| ).*/gm); 58 - const flags = prefixes[0].split(" "); 59 - for (const flag of flags) { 60 - node.properties[`data-img-flag--${flag}`] = true; 61 - } 62 - } 63 - 64 - /* 65 - paragraph flags go at the start 66 - to use paragraph flags, include the following syntax at the start of a paragraph: 67 - `::FLAG[::FLAG]*::`, where FLAG is a flag which is included as [data-para-flag--FLAG] 68 - if FLAG starts with an `@`, it will be treated as a directive 69 - current directives: 70 - - @nest: replaces children with a p tag and moves children into it 71 - - @div: replaces self with div 72 - */ 73 - 74 - function para(value: Text, parent: Element) { 75 - const flags = value.value.match(/(?<=^::).*(?=::)/gm); 76 - 77 - if (!flags) return; 78 - 79 - const txt = value.value.match(/(?<=^::.*:: ).*/gm); 80 - value.value = 81 - !txt || txt.length !== 1 ? "Err: Parser Error (custom HTML)" : txt[0]; 82 - 83 - for (const flag of flags[0].split("::")) { 84 - if (flag[0] === "@") { 85 - switch (flag.slice(1)) { 86 - case "nest": { 87 - const prevChildren = parent.children; 88 - parent.children = [ 89 - { 90 - type: "element", 91 - tagName: "p", 92 - properties: {}, 93 - children: prevChildren, 94 - } satisfies Element, 95 - ]; 96 - break; 97 - } 98 - case "div": { 99 - parent.tagName = "div"; 100 - break; 101 - } 102 - default: { 103 - console.warn("Unknown paragraph directive:", flag); 104 - } 105 - } 106 - } else parent.properties[`data-para-flag--${flag}`] = true; 107 - } 108 - } 109 - 110 - const forChild = (children: ElementContent[] | RootContent[]) => { 111 - for (const node of children) { 112 - if (node.type !== "element") continue; 113 - 114 - switch (node.tagName) { 115 - case "blockquote": { 116 - blockquote(node); 117 - break; 118 - } 119 - 120 - case "img": { 121 - image(node); 122 - break; 123 - } 124 - 125 - case "p": { 126 - if (node.children[0].type === "text") para(node.children[0], node); 127 - forChild(node.children); 128 - break; 129 - } 130 - 131 - case "pre": { 132 - if (node.properties["tabindex"]) node.properties["tabindex"] = "-1"; 133 - break; 134 - } 135 - 136 - case "ul": 137 - { 138 - node.children.forEach((x) => { 139 - if (x.type === "element" && x.tagName === "li") { 140 - const contents = x.children.map((y) => { 141 - if ( 142 - y.type === "element" && 143 - y.tagName === "input" && 144 - y.properties.type === "checkbox" 145 - ) 146 - y.properties["aria-label"] = y.properties.checked 147 - ? "Checked checkbox" 148 - : "Unchecked checkbox"; 149 - return y; 150 - }); 151 - 152 - x.children = [ 153 - { 154 - type: "element", 155 - tagName: "label", 156 - properties: {}, 157 - children: contents, 158 - }, 159 - ]; 160 - } 161 - }); 162 - } 163 - 164 - break; 165 - } 166 - } 167 - }; 168 - 169 - const plugin: Plugin<[Options], Root> = function (options) { 170 - return function (root, _) { 171 - forChild(root.children); 172 - }; 173 - }; 174 - 175 - export default plugin;
+8 -4
src/Base.astro
··· 1 1 --- 2 2 interface Props { 3 - title?: string; 3 + title: string; 4 4 dataset?: Record<string, any>; 5 5 [key: string]: any; 6 6 } ··· 27 27 <meta name="viewport" content="width=device-width" /> 28 28 <meta name="generator" content={Astro.generator} /> 29 29 <link rel="sitemap" href="/sitemap-index.xml" /> 30 - <title>{title ? `${title} | vielle.dev` : "vielle.dev"}</title> 30 + <title>{title} | vielle.dev</title> 31 31 <script> 32 32 // sets the timezone offset 33 - document.cookie = `timezone=${new Date().toString()};path=/`; 33 + document.cookie = `timezone=${new Date().toString()}`; 34 34 </script> 35 - <!-- default styles --> 35 + <!-- default styles (rem, *) --> 36 36 <style is:global> 37 37 @layer reset { 38 + :root { 39 + font-size: 62.5%; 40 + } 38 41 body { 42 + font-size: 1.6rem; 39 43 line-height: 1.5; 40 44 -webkit-font-smoothing: antialiased; 41 45 font-family: sans-serif;
-17
src/assets/arrow-down.svg
··· 1 - <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 - <svg 3 - width="10" 4 - height="10" 5 - viewBox="0 0 10 10" 6 - version="1.1" 7 - id="svg1" 8 - xmlns="http://www.w3.org/2000/svg" 9 - xmlns:svg="http://www.w3.org/2000/svg" 10 - stroke="black" 11 - stroke-width="2px" 12 - fill="none" 13 - > 14 - <path 15 - d="m 7.8145673,2.2064799 c 0,0 -2.0655083,4.998245 -2.5000003,4.998245 -0.434492,0 -2.4999997,-4.998245 -2.4999997,-4.998245" 16 - /> 17 - </svg>
-17
src/assets/arrow-right.svg
··· 1 - <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 - <svg 3 - width="10" 4 - height="10" 5 - viewBox="0 0 10 10" 6 - version="1.1" 7 - id="svg1" 8 - xmlns="http://www.w3.org/2000/svg" 9 - xmlns:svg="http://www.w3.org/2000/svg" 10 - stroke="black" 11 - stroke-width="2px" 12 - fill="none" 13 - > 14 - <path 15 - d="m 2.8919737,2.1290735 c 0,0 4.998245,2.0655083 4.998245,2.5000003 0,0.434492 -4.998245,2.4999997 -4.998245,2.4999997" 16 - /> 17 - </svg>
+73
src/assets/arrow.svg
··· 1 + <svg 2 + width="100" 3 + height="20" 4 + viewBox="0 0 26.458333 5.2916666" 5 + class="{className}" 6 + style="{style}" 7 + > 8 + <defs id="arrow"> 9 + <marker 10 + id="DartArrow" 11 + refX="0" 12 + refY="0" 13 + orient="auto-start-reverse" 14 + markerWidth="0.75" 15 + markerHeight="0.75" 16 + viewBox="0 0 1 1" 17 + preserveAspectRatio="xMidYMid" 18 + markerUnits="strokeWidth" 19 + > 20 + <path 21 + d="M 0,0 5,-5 -12.5,0 5,5 Z" 22 + transform="scale(-0.5)" 23 + id="path6" 24 + ></path> 25 + </marker> 26 + </defs> 27 + <g 28 + id="layer1" 29 + transform="matrix(0.8611475,0.06332518,-0.05355696,1.0182114,1.9248292,-1.3174538)" 30 + > 31 + <path 32 + d="m 0.24644479,2.3103471 c 0,0 4.07342911,2.4441516 11.16257621,2.4441516 7.089149,0 11.162682,-2.4441342 11.162682,-2.4441342" 33 + id="path1" 34 + ></path> 35 + </g> 36 + </svg> 37 + 38 + <style> 39 + .line { 40 + position: absolute; 41 + display: block; 42 + 43 + width: var(--width); 44 + height: calc(var(--width) / 5); 45 + 46 + transform: rotate(var(--angle)) scaleY(var(--scaleY, 1)); 47 + transform-origin: top left; 48 + 49 + top: var(--y); 50 + left: var(--x); 51 + 52 + stroke-width: 0.957978; 53 + stroke-dasharray: none; 54 + marker-end: url(#DartArrow); 55 + 56 + stroke: var(--colour); 57 + filter: drop-shadow(0 0 0.25rem black); 58 + fill: none; 59 + 60 + .location:hover & { 61 + filter: drop-shadow(0 0 0.5rem var(--colour)); 62 + } 63 + } 64 + 65 + #arrow marker { 66 + overflow: visible; 67 + } 68 + #arrow path { 69 + fill: context-stroke; 70 + fill-rule: evenodd; 71 + stroke: none; 72 + } 73 + </style>
+13
src/assets/balloon-glint.svg
··· 1 + <svg 2 + xmlns="http://www.w3.org/2000/svg" 3 + width="210mm" 4 + height="297mm" 5 + viewBox="0 0 210 297" 6 + > 7 + <g> 8 + <path 9 + style="fill: #ffffff" 10 + d="M 9.2929728,1.5456421 C 5.8272482,2.0424561 2.9819023,4.5085073 1.7466634,7.8119263 l 2.361613,1.0051066 C 5.0089649,6.2523257 7.1627996,4.4036314 9.7544434,4.0757202 9.7129319,3.7094167 9.64465,3.2547364 9.5239665,2.6814901 9.4170573,2.1736713 9.3470099,1.8242883 9.2929728,1.5456421 Z" 11 + /> 12 + </g> 13 + </svg>
-16
src/assets/check.svg
··· 1 - <svg 2 - xmlns="http://www.w3.org/2000/svg" 3 - width="24" 4 - height="24" 5 - viewBox="0 0 24 24" 6 - fill="none" 7 - stroke="white" 8 - stroke-width="2" 9 - stroke-linecap="round" 10 - stroke-linejoin="round" 11 - class="lucide lucide-check-icon lucide-check" 12 - > 13 - <desc><!-- no alt text as descriptive --></desc> 14 - 15 - <path d="M20 6 9 17l-5-5" /> 16 - </svg>
-18
src/assets/copy.svg
··· 1 - <svg 2 - xmlns="http://www.w3.org/2000/svg" 3 - width="18" 4 - height="18" 5 - viewBox="0 0 18 18" 6 - fill="none" 7 - stroke="currentColor" 8 - stroke-width="2" 9 - stroke-linecap="round" 10 - stroke-linejoin="round" 11 - class="lucide lucide-copy-icon lucide-copy" 12 - > 13 - <title>Copy text</title> 14 - <rect width="10" height="10" x="6" y="6" rx="2" ry="2" /> 15 - <path 16 - d="m 3,12 c -1,0 -1.5,-0.5 -1.5,-1.5 V 3 c 0,-1 0.5,-1.5 1.5,-1.5 h 7 c 0.8,0 1.5,0.5 1.5,1.5" 17 - /> 18 - </svg>
+2 -1
src/assets/hamburger.svg
··· 9 9 stroke-linecap="round" 10 10 stroke-linejoin="round" 11 11 class="lucide lucide-menu-icon lucide-menu" 12 + title="" 12 13 > 13 - <title>Menu</title> 14 + <title><!-- no alt text as used for buttons --></title> 14 15 <path d="M4 12h16" /> 15 16 <path d="M4 18h16" /> 16 17 <path d="M4 6h16" />
src/assets/mc_blue_banner.png

This is a binary file and will not be displayed.

src/assets/mc_cyan_banner.png

This is a binary file and will not be displayed.

src/assets/mc_magenta_banner.png

This is a binary file and will not be displayed.

src/assets/mc_map.png

This is a binary file and will not be displayed.

src/assets/mc_map_contents.png

This is a binary file and will not be displayed.

src/assets/mc_red_banner.png

This is a binary file and will not be displayed.

-15
src/assets/moon.svg
··· 1 - <svg 2 - xmlns="http://www.w3.org/2000/svg" 3 - width="24" 4 - height="24" 5 - viewBox="0 0 24 24" 6 - fill="none" 7 - stroke="currentColor" 8 - stroke-width="2" 9 - stroke-linecap="round" 10 - stroke-linejoin="round" 11 - class="lucide lucide-moon-icon lucide-moon" 12 - > 13 - <desc><!-- no alt text as descriptive --></desc> 14 - <path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" /> 15 - </svg>
-1
src/assets/rss.svg
··· 4 4 viewBox="0 0 256 256" 5 5 xmlns="http://www.w3.org/2000/svg" 6 6 > 7 - <desc><!-- no alt text as descriptive --></desc> 8 7 <circle 9 8 cx="35.10857" 10 9 cy="220.89143"
-23
src/assets/sun.svg
··· 1 - <svg 2 - xmlns="http://www.w3.org/2000/svg" 3 - width="24" 4 - height="24" 5 - viewBox="0 0 24 24" 6 - fill="none" 7 - stroke="currentColor" 8 - stroke-width="2" 9 - stroke-linecap="round" 10 - stroke-linejoin="round" 11 - class="lucide lucide-sun-icon lucide-sun" 12 - > 13 - <desc><!-- no alt text as descriptive --></desc> 14 - <circle cx="12" cy="12" r="4" /> 15 - <path d="M12 2v2" /> 16 - <path d="M12 20v2" /> 17 - <path d="m4.93 4.93 1.41 1.41" /> 18 - <path d="m17.66 17.66 1.41 1.41" /> 19 - <path d="M2 12h2" /> 20 - <path d="M20 12h2" /> 21 - <path d="m6.34 17.66-1.41 1.41" /> 22 - <path d="m19.07 4.93-1.41 1.41" /> 23 - </svg>
+17
src/assets/x.svg
··· 1 + <svg 2 + xmlns="http://www.w3.org/2000/svg" 3 + width="24" 4 + height="24" 5 + viewBox="0 0 24 24" 6 + fill="none" 7 + stroke="currentColor" 8 + stroke-width="2" 9 + stroke-linecap="round" 10 + stroke-linejoin="round" 11 + class="lucide lucide-x-icon lucide-x" 12 + title="" 13 + > 14 + <title><!-- no alt text as used for buttons --></title> 15 + <path d="M18 6 6 18" /> 16 + <path d="m6 6 12 12" /> 17 + </svg>
+7 -7
src/components/blog/Background.astro
··· 12 12 Astro.cookies.get("timezone")?.value ?? 13 13 Astro.request.headers.get("Date") ?? 14 14 Astro.request.headers.get("date") ?? // idk if it cares about capitals so Both 15 - Date.now(), 15 + Date.now() 16 16 ); 17 17 18 18 const accurateHours = ··· 65 65 <div 66 66 id="background" 67 67 data-time={daytime ? "day" : "night"} 68 - style={`--palette-sky-day: ${blog.palette.environment.sky.day}; 69 - --palette-sky-night: ${blog.palette.environment.sky.night}; 70 - --palette-sun: ${blog.palette.environment.sun}; 71 - --palette-moon: ${blog.palette.environment.moon}; 72 - --palette-cloud: ${blog.palette.environment.clouds}; 73 - --palette-star: ${blog.palette.environment.stars}`} 68 + style={`--palette-sky-day: ${blog.palette.sky.day}; 69 + --palette-sky-night: ${blog.palette.sky.night}; 70 + --palette-sun: ${blog.palette.sun}; 71 + --palette-moon: ${blog.palette.moon}; 72 + --palette-cloud: ${blog.palette.clouds}; 73 + --palette-star: ${blog.palette.stars}`} 74 74 aria-hidden="true" 75 75 > 76 76 {
+24 -21
src/components/blog/Balloon.astro
··· 17 17 18 18 <div 19 19 class="cable" 20 - style={`--length: ${length}px; 20 + style={`--length: ${length}rem; 21 21 --id: ${id}; 22 22 --of: ${of}; 23 - --offset: ${offset}px; 23 + --offset: ${offset}rem; 24 24 ${rotation.map((x, i) => `--rot-${i}: ${x}deg;`).join(" ")} 25 25 --timing: ${utils.getRandom(blog.balloons.timing)}s; 26 26 `} 27 27 > 28 28 <div 29 29 class="balloon" 30 - style={`--width: ${utils.getRandom(blog.balloons.size[0])}px; 31 - --height: ${utils.getRandom(blog.balloons.size[1])}px;`} 30 + style={`--width: ${utils.getRandom(blog.balloons.size[0])}rem; 31 + --height: ${utils.getRandom(blog.balloons.size[1])}rem;`} 32 32 tabindex="-1" 33 33 data-min-time={blog.balloons.time[0]} 34 34 data-max-time={blog.balloons.time[1]} ··· 41 41 42 42 <script> 43 43 const balloons = document.querySelectorAll(".balloon"); 44 + console.log(balloons); 44 45 balloons.forEach((el) => { 45 46 if (!(el instanceof HTMLElement)) return; 46 47 ··· 52 53 const postParent = el.parentElement?.parentElement; 53 54 if (!cableParent) throw new Error("No parent 1 level up!!!"); 54 55 if (!postParent) throw new Error("No parent 2 levels up!!!"); 56 + console.log("clicked! popping", el, "with post", postParent); 55 57 56 58 el.blur(); 57 59 ··· 61 63 { 62 64 duration: 100, 63 65 fill: "forwards", 64 - }, 66 + } 65 67 ).finished, 66 68 67 69 cableParent.animate( ··· 75 77 { 76 78 duration: 500, 77 79 fill: "forwards", 78 - }, 80 + } 79 81 ), 80 82 81 83 postParent.animate( 82 84 [ 83 85 {}, 84 86 { 85 - top: "calc(var(--x-offset-0) + 500px)", 87 + top: "calc(var(--x-offset-0) + 50rem)", 86 88 }, 87 89 ], 88 90 { 89 91 duration: 1000, 90 92 easing: "ease-in-out", 91 - }, 93 + } 92 94 ).finished, 93 95 ]).then(() => { 94 96 const duration = (mintime + Math.random() * (maxtime - mintime)) * 1000; ··· 103 105 duration, 104 106 fill: "forwards", 105 107 // easing: "ease-in", 106 - }, 108 + } 107 109 ); 108 110 109 111 cableParent.animate( ··· 120 122 { 121 123 duration, 122 124 fill: "forwards", 123 - }, 125 + } 124 126 ); 125 127 126 128 postParent.animate( 127 129 [ 128 130 { 129 - top: "calc(var(--x-offset-0) + 500px)", 131 + top: "calc(var(--x-offset-0) + 50rem)", 130 132 }, 131 133 {}, 132 134 ], ··· 134 136 duration, 135 137 fill: "forwards", 136 138 easing: "ease-in", 137 - }, 139 + } 138 140 ); 139 141 }); 140 142 }); ··· 231 233 .cable { 232 234 position: absolute; 233 235 234 - width: 5px; 236 + width: 0.5rem; 235 237 height: var(--length); 236 - border-radius: 2.5px; 238 + border-radius: 0.25rem; 237 239 background: black; 238 240 239 241 [data-time="night"] + * & { 240 242 background: #404040; 241 243 } 242 244 245 + /* .5rem accounts for border (z-index doesn't work) */ 243 246 z-index: -99; 244 247 top: calc(-1 * var(--length)); 245 248 left: calc( ··· 274 277 } 275 278 276 279 .cable-tie { 277 - width: 17.5px; 278 - height: 5px; 280 + width: 1.75rem; 281 + height: 0.5rem; 279 282 280 283 position: absolute; 281 - bottom: -2.5px; 284 + bottom: -0.25rem; 282 285 left: 50%; 283 286 translate: -50%; 284 287 z-index: 1; 285 288 286 - border-radius: 2.5px; 289 + border-radius: 0.25rem; 287 290 background-color: black; 288 291 289 292 [data-time="night"] + * & { ··· 292 295 } 293 296 294 297 .tie { 295 - width: 20px; 296 - height: 20px; 298 + width: 2rem; 299 + height: 2rem; 297 300 background-color: var(--colour); 298 301 clip-path: polygon(50% 0, 0 100%, 100% 100%); 299 302 position: absolute; 300 - bottom: -10px; 303 + bottom: -1rem; 301 304 left: 50%; 302 305 translate: -50%; 303 306 }
-148
src/components/blog/CodeHeading.astro
··· 1 - --- 2 - import Copy from "@/assets/copy.svg"; 3 - 4 - interface Props { 5 - colours: { text: string; border: string }; 6 - } 7 - 8 - const { colours } = Astro.props; 9 - --- 10 - 11 - <template id="code-heading"> 12 - <span class="lang"><slot is:inline>.txt</slot></span> 13 - <span id="copied" style="visibility:hidden" role="alert">Copied!</span> 14 - <button id="copy"><Copy /></button> 15 - 16 - <!-- define:vars didnt work :( --> 17 - <style 18 - set:html={` 19 - :host { 20 - --text: ${colours.text}; 21 - --border: ${colours.border}; 22 - } 23 - `} 24 - ></style> 25 - 26 - <style> 27 - @keyframes teeter { 28 - from, 29 - to { 30 - rotate: 0deg; 31 - } 32 - 25% { 33 - rotate: 15deg; 34 - } 35 - 75% { 36 - rotate: -15deg; 37 - } 38 - } 39 - 40 - .lang { 41 - color: var(--text); 42 - } 43 - 44 - button { 45 - border: none; 46 - background: none; 47 - aspect-ratio: 1; 48 - border-radius: 100%; 49 - 50 - display: flex; 51 - align-items: center; 52 - justify-content: center; 53 - 54 - &:hover, 55 - &:focus { 56 - scale: 1.2; 57 - outline: none; 58 - background-color: #ffffff20; 59 - } 60 - 61 - &:active { 62 - scale: 1.4; 63 - animation: teeter 0.2s; 64 - } 65 - 66 - & svg { 67 - stroke: var(--text); 68 - margin: 2px; 69 - } 70 - } 71 - 72 - :host { 73 - display: flex block; 74 - justify-content: space-between; 75 - align-items: center; 76 - /* gets overridden by * because why not ig */ 77 - padding: 5px 15px !important; 78 - position: sticky; 79 - top: 0; 80 - left: 0; 81 - border-bottom: 4px solid var(--border); 82 - user-select: none; 83 - } 84 - </style> 85 - </template> 86 - 87 - <script> 88 - class CodeHeading extends HTMLElement { 89 - contents = ""; 90 - static observedAttributes = ["contents"]; 91 - 92 - template: HTMLTemplateElement; 93 - content: DocumentFragment; 94 - shadowRoot: ShadowRoot; 95 - 96 - constructor() { 97 - super(); 98 - const template = document.getElementById("code-heading"); 99 - if (!template || !(template instanceof HTMLTemplateElement)) 100 - throw new Error("Could not get #code-heading"); 101 - this.template = template; 102 - this.content = template.content; 103 - 104 - this.shadowRoot = this.attachShadow({ mode: "open" }); 105 - this.shadowRoot.appendChild(this.content.cloneNode(true)); 106 - 107 - const copy = this.shadowRoot.getElementById("copy"); 108 - if (!copy) throw new Error("No #copy in #code-heading"); 109 - 110 - const copied = this.shadowRoot.getElementById("copied"); 111 - if (!copied) throw new Error("No #copied in #code-heading"); 112 - 113 - const copied_animation = { 114 - opacity: [0, 1], 115 - visibility: ["hidden", "visible"], 116 - }; 117 - 118 - copy.addEventListener("click", () => { 119 - navigator.clipboard 120 - .writeText(this.contents) 121 - .catch((e) => { 122 - console.error("Encountered error copying to clipboard;", e); 123 - }) 124 - .then(async () => { 125 - await copied.animate(copied_animation, { 126 - duration: 200, 127 - fill: "forwards", 128 - }).finished; 129 - 130 - copied.animate(copied_animation, { 131 - duration: 200, 132 - delay: 2000, 133 - fill: "forwards", 134 - direction: "reverse", 135 - }); 136 - }); 137 - }); 138 - } 139 - 140 - attributeChangedCallback(name: string, _: any, newV?: string) { 141 - if (name == "contents") { 142 - this.contents = newV ?? ""; 143 - } 144 - } 145 - } 146 - 147 - customElements.define("code-heading", CodeHeading); 148 - </script>
+17 -17
src/components/blog/Post.astro
··· 17 17 if (!data.image) return; 18 18 const img = data.image.match(/.*(?=\.png)/gm); 19 19 if (img === null) return; 20 - return await import(`../../content/posts/assets/${img[0]}.png`).then( 21 - (x) => x.default, 20 + return await import(`../../posts/assets/${img[0]}.png`).then( 21 + (x) => x.default 22 22 ); 23 23 })(); 24 24 ··· 61 61 ${offsets 62 62 .map( 63 63 (x, i) => 64 - `--x-offset-${i}: calc((100svw - ${blog.post.width + 2 * blog.post.xPadding}px) * ${positions[0] + x[0]} + ${blog.post.xPadding}px); 65 - --y-offset-${i}: ${blog.post.yLeeway * 2 * (positions[1] + x[1]) - blog.post.yLeeway}px;`, 64 + `--x-offset-${i}: calc((100svw - ${blog.post.width + 2 * blog.post.xPadding}rem) * ${positions[0] + x[0]} + ${blog.post.xPadding}rem); 65 + --y-offset-${i}: ${blog.post.yLeeway * 2 * (positions[1] + x[1]) - blog.post.yLeeway}rem;` 66 66 ) 67 67 .join("\n")} 68 68 ··· 73 73 74 74 /* config */ 75 75 76 - --width: ${blog.post.width}px; 77 - --y-gap: ${blog.post.yGap}px; 76 + --width: ${blog.post.width}rem; 77 + --y-gap: ${blog.post.yGap}rem; 78 78 `} 79 79 > 80 80 { ··· 172 172 173 173 section { 174 174 width: var(--width); 175 - padding: 10px; 175 + padding: 1rem; 176 176 margin-bottom: var(--y-gap); 177 177 178 178 position: relative; ··· 185 185 content: "" / ""; 186 186 display: block; 187 187 position: absolute; 188 - top: -5px; 189 - left: -5px; 188 + top: -0.5rem; 189 + left: -0.5rem; 190 190 z-index: -2; 191 191 192 - width: calc(var(--width) + 10px); 193 - height: calc(100% + 10px); 192 + width: calc(var(--width) + 1rem); 193 + height: calc(100% + 1rem); 194 194 195 195 background-color: white; 196 - border: 5px solid var(--colour, dodgerblue); 197 - border-radius: 25px; 196 + border: 0.5rem solid var(--colour, dodgerblue); 197 + border-radius: 2.5rem; 198 198 199 - box-shadow: 0 0 75px var(--box-shadow-colour, #00000080); 199 + box-shadow: 0 0 7.5rem var(--box-shadow-colour, #00000080); 200 200 } 201 201 202 202 /* default, overridden by reduced motion */ ··· 217 217 } 218 218 219 219 & > img { 220 - border-radius: 15px; 220 + border-radius: 1.5rem; 221 221 222 - width: 300px; 223 - height: 200px; 222 + width: 30rem; 223 + height: 20rem; 224 224 object-fit: cover; 225 225 } 226 226 }
+7 -11
src/components/blog/background/Cloud.astro
··· 36 36 37 37 const vectorOffset = ( 38 38 v: [number, number], 39 - o: [number, number], 39 + o: [number, number] 40 40 ): [number, number] => { 41 41 return [o[0] - v[0], o[1] - v[1]]; 42 42 }; ··· 89 89 ]; 90 90 const newDistance = Math.sqrt( 91 91 (newCenter[0] - p.origin[0]) ** 2 + 92 - (newCenter[1] - p.origin[1]) ** 2, 92 + (newCenter[1] - p.origin[1]) ** 2 93 93 ); 94 94 return { 95 95 origin: vectorOffset(vector(ang, c), p.origin), ··· 120 120 prev: 0, 121 121 output: [] as any[], 122 122 complete: false, 123 - }, 123 + } 124 124 ).output 125 125 } 126 126 <circle cx={r} cy={r} r={r}></circle> ··· 133 133 y1="0" 134 134 y2="1" 135 135 > 136 - <stop offset="0%" stop-color={blog.palette.environment.clouds}></stop> 136 + <stop offset="0%" stop-color={blog.palette.clouds}></stop> 137 137 <stop 138 138 offset={`${blog.background.clouds.gradientStops[0]}%`} 139 - stop-color={blog.palette.environment.clouds}></stop> 139 + stop-color={blog.palette.clouds}></stop> 140 140 <stop 141 141 offset={`${blog.background.clouds.gradientStops[1]}%`} 142 - stop-color={`rgb(from ${blog.palette.environment.clouds} r g b / 0)`} 143 - ></stop> 144 - <stop 145 - offset="100%" 146 - stop-color={`rgb(from ${blog.palette.environment.clouds} r g b / 0)`} 147 - ></stop> 142 + stop-color={`rgb(from ${blog.palette.clouds} r g b / 0)`}></stop> 143 + <stop offset="100%" stop-color={`rgb(from ${blog.palette.clouds} r g b / 0)`}></stop> 148 144 </linearGradient> 149 145 </defs> 150 146
+3 -3
src/components/blog/background/Clouds.astro
··· 30 30 ...prev.output, 31 31 <Cloud 32 32 style={`--parallax-speed: ${blog.background.parallax.clouds}; 33 - width: ${width}px; 34 - height: ${height}px; 35 - top: ${y}px; 33 + width: ${width}rem; 34 + height: ${height}rem; 35 + top: ${y}rem; 36 36 left: calc(${x} * 200lvw - 100lvw); 37 37 position: absolute;`} 38 38 id={"cloud-" + i}
+9 -10
src/components/blog/background/Moon.astro
··· 8 8 9 9 <style> 10 10 svg { 11 - width: 200px; 12 - height: 200px; 13 - font-size: 200px; 11 + width: 20rem; 12 + height: 20rem; 13 + font-size: 20rem; 14 14 15 15 position: absolute; 16 - top: 300px; 17 - right: 10px; 16 + top: 30rem; 17 + right: 1rem; 18 18 } 19 19 </style> 20 20 ··· 32 32 </defs> 33 33 34 34 <!-- base --> 35 - <circle fill={blog.palette.environment.moon} cx="100" cy="100" r="100" 36 - ></circle> 35 + <circle fill={blog.palette.moon} cx="100" cy="100" r="100"></circle> 37 36 <!-- half shadow --> 38 37 <circle 39 - fill={blog.palette.environment.sky.night} 38 + fill={blog.palette.sky.night} 40 39 cx="100" 41 40 cy="100" 42 41 r="100" ··· 44 43 <!-- rotation shadow bulge thing --> 45 44 <ellipse 46 45 fill={phase < 0.25 || phase > 0.75 47 - ? blog.palette.environment.moon 48 - : blog.palette.environment.sky.night} 46 + ? blog.palette.moon 47 + : blog.palette.sky.night} 49 48 cx="100" 50 49 cy="100" 51 50 rx={50 * Math.cos(4 * Math.PI * phase) + 50}
+3 -3
src/components/blog/background/Stars.astro
··· 39 39 const prongs = Math.round( 40 40 blog.background.stars.prongs[0] + 41 41 Math.random() * 42 - (blog.background.stars.prongs[1] - blog.background.stars.prongs[0]), 42 + (blog.background.stars.prongs[1] - blog.background.stars.prongs[0]) 43 43 ); 44 44 45 45 return ( 46 46 <svg 47 47 style={`--parallax-speed: ${utils.getRandom(blog.background.parallax.star, sizeSeed)}; 48 - --size: ${blog.background.stars.size[0] + sizeSeed * (blog.background.stars.size[1] - blog.background.stars.size[0])}px; 48 + --size: ${blog.background.stars.size[0] + sizeSeed * (blog.background.stars.size[1] - blog.background.stars.size[0])}rem; 49 49 --x: ${Math.random()}; 50 50 --y: ${Math.random()}; 51 51 --rotate-speed: ${blog.background.stars.rotateSpeed[0] + Math.random() * (blog.background.stars.rotateSpeed[1] - blog.background.stars.rotateSpeed[0])}s; ··· 57 57 > 58 58 {new Array(prongs).fill(0).map((_, i) => ( 59 59 <polygon 60 - fill={blog.palette.environment.stars} 60 + fill={blog.palette.stars} 61 61 points="50 0, 75 50, 25 50" 62 62 transform={`rotate(${(i / prongs) * 360})`} 63 63 transform-origin="center"
+4 -4
src/components/blog/background/Sun.astro
··· 13 13 svg { 14 14 position: absolute; 15 15 border-radius: 100%; 16 - top: 150px; 17 - left: calc(100lvw * var(--sun-progress-percent) - 75px); 16 + top: 15rem; 17 + left: calc(100lvw * var(--sun-progress-percent) - 7.5rem); 18 18 z-index: -1; 19 19 20 20 animation: ··· 33 33 --sun-progress-percent: ${percent}`} 34 34 data-parallax 35 35 > 36 - <circle fill={blog.palette.environment.sun} cx="50" cy="50" r="35"></circle> 36 + <circle fill={blog.palette.sun} cx="50" cy="50" r="35"></circle> 37 37 38 38 { 39 39 new Array(prongs) 40 40 .fill(0) 41 41 .map((_, i) => ( 42 42 <polygon 43 - fill={blog.palette.environment.sun} 43 + fill={blog.palette.sun} 44 44 points="50 0, 55 10, 45 10" 45 45 transform={`rotate(${(i / prongs) * 360})`} 46 46 transform-origin="center"
-259
src/components/blog/post.css
··· 1 - .content { 2 - /* Custom Flags */ 3 - 4 - & blockquote { 5 - &[data-bq-flag--note], 6 - &[data-bq-flag--alert], 7 - &[data-bq-flag--info] { 8 - color: black; 9 - } 10 - 11 - &[data-bq-flag--note] { 12 - --accent: var(--rainbow-4); 13 - --icon: "๐Ÿ“"; 14 - --name: "Note"; 15 - } 16 - 17 - &[data-bq-flag--alert] { 18 - --accent: var(--rainbow-0); 19 - --icon: "๐Ÿšจ"; 20 - --name: "Alert"; 21 - } 22 - 23 - &[data-bq-flag--info] { 24 - --accent: var(--rainbow-5); 25 - --icon: "๐Ÿ“š"; 26 - --name: "Info"; 27 - } 28 - } 29 - 30 - & p, 31 - & div:has(> p) { 32 - &[data-para-flag--bg-red], 33 - &[data-para-flag--bg-orange], 34 - &[data-para-flag--bg-yellow], 35 - &[data-para-flag--bg-green], 36 - &[data-para-flag--bg-blue], 37 - &[data-para-flag--bg-purple] { 38 - /* contrasting colour */ 39 - color: black; 40 - } 41 - 42 - &[data-para-flag--bg-red] { 43 - background-color: var(--rainbow-0); 44 - } 45 - 46 - &[data-para-flag--bg-orange] { 47 - background-color: var(--rainbow-1); 48 - } 49 - 50 - &[data-para-flag--bg-yellow] { 51 - background-color: var(--rainbow-2); 52 - } 53 - 54 - &[data-para-flag--bg-green] { 55 - background-color: var(--rainbow-3); 56 - } 57 - 58 - &[data-para-flag--bg-blue] { 59 - background-color: var(--rainbow-4); 60 - } 61 - 62 - &[data-para-flag--bg-purple] { 63 - background-color: var(--rainbow-5); 64 - } 65 - } 66 - 67 - & img { 68 - &[data-img-flag--small="true"] { 69 - width: 50%; 70 - } 71 - 72 - &[data-img-flag--left="true"] { 73 - float: left; 74 - } 75 - 76 - &[data-img-flag--right="true"] { 77 - float: right; 78 - } 79 - 80 - &[data-img-flag--centre="true"] { 81 - margin-inline: auto; 82 - } 83 - } 84 - 85 - /* Headings */ 86 - 87 - & h2, 88 - & h3, 89 - & h4 { 90 - margin-block-start: 20px; 91 - margin-block-end: 20px; 92 - 93 - color: var(--typo-subheading); 94 - 95 - & + & { 96 - margin-block-start: 0; 97 - } 98 - 99 - :has(+ &) { 100 - margin-block-end: 0; 101 - } 102 - } 103 - 104 - & h2 { 105 - font-size: 2.2rem; 106 - } 107 - 108 - & h3 { 109 - font-size: 1.8rem; 110 - } 111 - 112 - & h4 { 113 - font-size: 1.5rem; 114 - } 115 - 116 - /* Paragraphs */ 117 - & p, 118 - & blockquote { 119 - clear: both; 120 - margin-block: 20px; 121 - } 122 - 123 - & div:has(> p) { 124 - margin-block: 10px; 125 - } 126 - 127 - /* Images */ 128 - & img { 129 - height: auto; /* fix height issues ?? */ 130 - margin: 10px; 131 - } 132 - 133 - & a { 134 - text-decoration: 2px underline; 135 - 136 - &:link { 137 - color: var(--typo-url); 138 - } 139 - &:visited { 140 - color: var(--typo-visited); 141 - } 142 - &:hover { 143 - text-decoration: 1px wavy underline; 144 - } 145 - &:active { 146 - color: var(--rainbow-3); 147 - } 148 - } 149 - 150 - /* Standard Lists */ 151 - & ul, 152 - & ol { 153 - margin-inline-start: 40px; 154 - & & { 155 - margin-inline-start: 20px; 156 - } 157 - } 158 - 159 - /* Blockquotes */ 160 - & blockquote { 161 - --accent: var(--bg-secondary); 162 - border-left: 2px solid hsl(from var(--accent) h s calc(l * 0.9)); 163 - padding: 10px 40px 10px 10px; 164 - margin: 10px; 165 - border-radius: 5px; 166 - background-color: var(--accent); 167 - width: fit-content; 168 - min-width: 200px; 169 - 170 - &::before { 171 - content: var(--icon) " " var(--name) / var(--name); 172 - } 173 - } 174 - 175 - /* Inline code */ 176 - :not(pre) > code { 177 - color: var(--typo-code); 178 - background-color: var(--bg-code); 179 - padding: 2px; 180 - border-radius: 5px; 181 - 182 - /* make blockquote code use a lighter version of the accent with a darker background */ 183 - :is(blockquote) & { 184 - color: hsl(from var(--accent) h calc(s * 0.8) calc(l * 1.4)); 185 - background-color: #00000080; 186 - } 187 - } 188 - 189 - /* Outline Code */ 190 - & pre:has(> code) { 191 - padding: 5px; 192 - border-radius: 10px; 193 - } 194 - 195 - .astro-code { 196 - background-color: var(--bg-code) !important; 197 - margin-block: 10px; 198 - padding: 0; 199 - position: relative; 200 - 201 - & code { 202 - display: block; 203 - padding: 10px; 204 - 205 - & span { 206 - color: light-dark(var(--shiki-light), var(--shiki-dark)) !important; 207 - } 208 - } 209 - } 210 - 211 - /* Check lists */ 212 - .task-list-item { 213 - list-style: none; 214 - } 215 - 216 - .task-list-item label { 217 - display: flex; 218 - margin-block-start: 5px; 219 - margin-block-end: 7.5px; 220 - 221 - gap: 5px; 222 - 223 - & input[type="checkbox"] { 224 - width: 25px; 225 - height: 25px; 226 - margin-inline-end: 5px; 227 - 228 - background: light-dark(rgb(0, 0, 0, 0.2), rgb(255, 255, 255, 0.4)); 229 - border-radius: 5px; 230 - border: 1px solid var(--typo-body); 231 - 232 - &:checked { 233 - --checkmark: url("../../assets/check.svg"); 234 - background: var(--checkmark) center/20px padding-box no-repeat 235 - var(--rainbow-2); 236 - } 237 - } 238 - } 239 - 240 - /* Table */ 241 - & table { 242 - border-collapse: collapse; 243 - border-spacing: 0; 244 - 245 - & th, 246 - & td { 247 - border: 1px solid white; 248 - padding: 5px; 249 - } 250 - 251 - & thead th { 252 - background-color: var(--bg-secondary); 253 - } 254 - 255 - & tbody tr:nth-child(2n) { 256 - background-color: #ffffff10; 257 - } 258 - } 259 - }
-90
src/components/generic/LightDarkToggle.astro
··· 1 - --- 2 - import Sun from "@/assets/sun.svg"; 3 - import Moon from "@/assets/moon.svg"; 4 - 5 - interface Props { 6 - colours: { 7 - bg: string; 8 - fg: string; 9 - }; 10 - } 11 - 12 - const { colours } = Astro.props; 13 - --- 14 - 15 - <button 16 - aria-label="toggle colour scheme" 17 - id="colour-toggle" 18 - style="visibility: hidden" 19 - > 20 - <Sun data-mode-light /> 21 - <Moon data-mode-dark /> 22 - </button> 23 - 24 - <style define:vars={colours}> 25 - #colour-toggle { 26 - background-color: var(--bg); 27 - 28 - border: none; 29 - border-radius: 50%; 30 - padding: 5px; 31 - 32 - width: 34px; 33 - height: 34px; 34 - 35 - & svg { 36 - fill: var(--fg); 37 - stroke: var(--fg); 38 - } 39 - } 40 - </style> 41 - 42 - <script> 43 - const root = document.querySelector(":root"); 44 - if (!(root instanceof HTMLElement)) throw new Error(":root is not html"); 45 - 46 - const button = document.getElementById("colour-toggle"); 47 - if (!button) throw new Error("No #colour-toggle element"); 48 - 49 - const modeToggled = { 50 - light: document.querySelectorAll("[data-mode-light]"), 51 - dark: document.querySelectorAll("[data-mode-dark]"), 52 - }; 53 - 54 - const cookies = document.cookie 55 - .split("; ") 56 - .reduce< 57 - Record<string, string> 58 - >((prev, cur) => ({ ...prev, [cur.split("=")[0]]: cur.split("=")[1] }), {}); 59 - 60 - const mediaMode = matchMedia("(prefers-color-scheme: light)").matches; 61 - const cookieMode = 62 - cookies["colour-mode"] === "light" 63 - ? true 64 - : cookies["colour-mode"] === "dark" 65 - ? false 66 - : undefined; 67 - let lightMode = cookieMode ?? mediaMode; 68 - 69 - const updateColourScheme = () => { 70 - root.style.colorScheme = lightMode ? "light" : "dark"; 71 - document.cookie = `colour-mode=${root.style.colorScheme};path=/`; 72 - 73 - modeToggled[lightMode ? "light" : "dark"].forEach((el) => { 74 - if (!(el instanceof SVGElement || el instanceof HTMLElement)) return; 75 - el.style.display = "block"; 76 - }); 77 - 78 - modeToggled[!lightMode ? "light" : "dark"].forEach((el) => { 79 - if (!(el instanceof SVGElement || el instanceof HTMLElement)) return; 80 - el.style.display = "none"; 81 - }); 82 - }; 83 - 84 - updateColourScheme(); 85 - button.addEventListener("click", () => { 86 - lightMode = !lightMode; 87 - updateColourScheme(); 88 - }); 89 - button.style.visibility = "visible"; 90 - </script>
+92
src/components/generic/Nav.astro
··· 1 + --- 2 + import type { nav } from "@/content.config"; 3 + import NavEntry from "./NavEntry.astro"; 4 + import Hamburger from "@/assets/hamburger.svg"; 5 + import X from "@/assets/x.svg"; 6 + 7 + interface Props { 8 + startOpen?: boolean; 9 + current: string; 10 + data: nav[]; 11 + } 12 + 13 + const { data, startOpen = false, current } = Astro.props; 14 + --- 15 + 16 + <button 17 + popovertarget="nav" 18 + popovertargetaction="show" 19 + aria-label="Nav Menu" 20 + id="nav-menu" 21 + > 22 + <Hamburger /> 23 + </button> 24 + <dialog closedby="any" open={startOpen} id="nav" popover> 25 + <div class="top"> 26 + <h1>{current}</h1> 27 + <button popovertarget="nav" popovertargetaction="hide" aria-label="close"> 28 + <X width={32} height={32} /> 29 + </button> 30 + </div> 31 + <NavEntry {data} /> 32 + </dialog> 33 + 34 + <style> 35 + button { 36 + background-color: transparent; 37 + border: none; 38 + & svg { 39 + stroke: white; 40 + } 41 + } 42 + 43 + #nav-menu { 44 + background-color: black; 45 + padding: 1rem; 46 + border-radius: 0 0 50% 0; 47 + } 48 + 49 + .top { 50 + display: flex; 51 + flex-direction: row; 52 + justify-content: space-between; 53 + } 54 + 55 + dialog { 56 + color: white; 57 + 58 + width: min(50vw, 20rem); 59 + height: 100vh; 60 + padding: 1rem; 61 + 62 + background: black; 63 + border: none; 64 + 65 + position: fixed; 66 + top: 0; 67 + transition: 68 + left 0.2s, 69 + display 0.2s allow-discrete; 70 + 71 + &:popover-open { 72 + /* Post-Entry (Normal) State */ 73 + left: 0; 74 + 75 + /* Pre-Entry State */ 76 + @starting-style { 77 + left: -100%; 78 + } 79 + } 80 + 81 + /* Exiting State */ 82 + &:not(:popover-open) { 83 + left: -100%; 84 + } 85 + } 86 + 87 + /* STUPID ISSUE (astro tries to add a tag to the backdrop) */ 88 + :global(::backdrop) { 89 + background: #00000080; 90 + backdrop-filter: blur(0.5rem); 91 + } 92 + </style>
+63
src/components/generic/NavEntry.astro
··· 1 + --- 2 + import type { nav } from "@/content.config"; 3 + 4 + interface Props { 5 + data: nav[]; 6 + root?: string; 7 + } 8 + 9 + const { data, root = "" } = Astro.props; 10 + --- 11 + 12 + <ul> 13 + { 14 + data.map((x) => ( 15 + <li> 16 + <a href={`${root}${x.slug}`}>{x.name}</a> 17 + {x.children && x.children.length > 0 ? ( 18 + <Astro.self root={`${root}${x.slug}`} data={x.children} /> 19 + ) : null} 20 + </li> 21 + )) 22 + } 23 + </ul> 24 + 25 + <style> 26 + li { 27 + list-style-type: "โ•บ "; 28 + margin-inline-start: 4rem; 29 + } 30 + 31 + a:link { 32 + color: #62A0EA; 33 + } 34 + 35 + a:visited { 36 + color: #DC8ADD; 37 + } 38 + 39 + a:focus, 40 + a:hover { 41 + text-decoration: none; 42 + color: #4040ff 43 + 44 + &:visited { 45 + color: #ff40ff; 46 + } 47 + } 48 + 49 + a:focus { 50 + outline: 0.2rem solid #62A0EA; 51 + outline-offset: 0; 52 + border-radius: 0.4rem; 53 + 54 + &:visited { 55 + outline-color: #DC8ADD; 56 + } 57 + } 58 + 59 + a:active { 60 + text-decoration: none; 61 + scale: 1.05; 62 + } 63 + </style>
+210
src/components/index/Map.astro
··· 1 + --- 2 + import mc_map_contents from "@/assets/mc_map_contents.png"; 3 + import mc_red from "@/assets/mc_red_banner.png"; 4 + import mc_cyan from "@/assets/mc_cyan_banner.png"; 5 + import mc_magenta from "@/assets/mc_magenta_banner.png"; 6 + import mc_blue from "@/assets/mc_blue_banner.png"; 7 + import Arrow from "@/assets/arrow.svg"; 8 + 9 + type colour = "red" | "cyan" | "magenta" | "blue"; 10 + type position = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; 11 + 12 + interface Location { 13 + colour: colour; 14 + name: string; 15 + href?: string; 16 + x: position; 17 + y: position; 18 + } 19 + 20 + interface Props { 21 + locations: Location[]; 22 + } 23 + 24 + const { locations } = Astro.props; 25 + 26 + const getSrc = (colour: colour) => { 27 + switch (colour) { 28 + case "red": 29 + return mc_red.src; 30 + case "cyan": 31 + return mc_cyan.src; 32 + case "magenta": 33 + return mc_magenta.src; 34 + case "blue": 35 + return mc_blue.src; 36 + } 37 + }; 38 + 39 + const getCssColour = (colour: colour) => { 40 + switch (colour) { 41 + case "red": 42 + return "#af2d25"; 43 + case "cyan": 44 + return "#159b9b"; 45 + case "magenta": 46 + return "#c64ebc"; 47 + case "blue": 48 + return "#3c43a9"; 49 + } 50 + }; 51 + 52 + const scale = 4; 53 + --- 54 + 55 + <div style=`--scale: ${scale}px;` class="map"> 56 + <img 57 + src={mc_map_contents.src} 58 + alt="" 59 + width={58 * scale} 60 + height={58 * scale} 61 + class="map-img" 62 + /> 63 + 64 + { 65 + locations.map((l) => { 66 + // calculate size of map region 67 + const mapSize = 64 * scale; 68 + 69 + interface XY { 70 + y: number; 71 + x: number; 72 + } 73 + 74 + // calculate position of banner 75 + const bannerPos: XY = { 76 + x: l.x * 8 * scale, 77 + y: l.y * 8 * scale, 78 + }; 79 + 80 + // calculate position of text 81 + // coords are inverted so that it doesnt overlap the map 82 + // and so that the line is based properly 83 + // const textPos: XY = { 84 + // x: mapSize + 16 + Math.floor(Math.random() * 30), 85 + // y: mapSize - 32 + Math.floor(Math.random() * 30) - 15, 86 + // }; 87 + 88 + const textPos: XY = { 89 + ...(l.x < 4 90 + ? { x: -132 - Math.floor(Math.random() * 50) } 91 + : { x: mapSize + 32 + Math.floor(Math.random() * 50) }), 92 + ...(l.y < 4 93 + ? { y: 16 + Math.floor(Math.random() * 50) - 25 } 94 + : { y: (mapSize / 4) * 3 + Math.floor(Math.random() * 50) - 25 }), 95 + }; 96 + 97 + // calculate coordinates of corners 98 + const bannerCorner: XY = { 99 + x: bannerPos.x < 128 ? bannerPos.x : bannerPos.x + 8 * scale, 100 + y: bannerPos.y < 128 ? bannerPos.y : bannerPos.y + 8 * scale, 101 + }; 102 + 103 + const textCorner: XY = { 104 + ...textPos, 105 + ...(l.x < 4 ? { x: textPos.x + 100 } : {}), 106 + ...{ y: textPos.y + 10 }, 107 + }; 108 + 109 + // calculate length and angle of line 110 + 111 + const lineLength: number = Math.sqrt( 112 + (bannerCorner.x - textCorner.x) ** 2 + 113 + (bannerCorner.y - textCorner.y) ** 2, 114 + ); 115 + 116 + const lineAngle: number = Math.atan2( 117 + bannerCorner.y - textCorner.y, 118 + bannerCorner.x - textCorner.x, 119 + ); 120 + 121 + return ( 122 + <a class="location" href={l.href ?? ""}> 123 + <img 124 + src={getSrc(l.colour)} 125 + alt="" 126 + width={8 * scale} 127 + height={8 * scale} 128 + class="marker" 129 + style={`--y: ${bannerPos.y}px; 130 + --x: ${bannerPos.x}px; 131 + --colour: ${getCssColour(l.colour)};`} 132 + /> 133 + <div 134 + style={`--y: ${textPos.y}px; 135 + --x: ${textPos.x}px; 136 + --colour: ${getCssColour(l.colour)}; 137 + text-align: ${l.x < 4 ? "right" : "left"};`} 138 + class="text" 139 + > 140 + {l.name} 141 + </div> 142 + <Arrow 143 + class="line" 144 + style={`--width: ${lineLength}px; 145 + --y: ${textCorner.y}px; 146 + --x: ${textCorner.x}px; 147 + --angle: ${lineAngle}rad; 148 + --colour: ${getCssColour(l.colour)}; 149 + --scaleY: ${!(l.x < 4 != l.y < 4) ? -1 : 1};`} 150 + /> 151 + </a> 152 + ); 153 + }) 154 + } 155 + </div> 156 + 157 + <style> 158 + img { 159 + display: block; 160 + position: absolute; 161 + &.map-img { 162 + top: calc(3 * var(--scale)); 163 + left: calc(3 * var(--scale)); 164 + } 165 + &.marker { 166 + top: var(--y); 167 + left: var(--x); 168 + .location:hover & { 169 + filter: drop-shadow(0 0 0.5rem var(--colour)); 170 + scale: 1.1; 171 + } 172 + } 173 + } 174 + 175 + .text { 176 + position: absolute; 177 + 178 + width: 10rem; 179 + height: 2rem; 180 + 181 + top: var(--y); 182 + left: var(--x); 183 + 184 + color: var(--colour); 185 + .location:hover & { 186 + filter: drop-shadow(0 0 0.5rem var(--colour)); 187 + } 188 + } 189 + 190 + .location { 191 + display: block; 192 + --speed: 100ms; 193 + transition: 194 + scale var(--speed), 195 + filter var(--speed); 196 + & * { 197 + transition: inherit; 198 + } 199 + } 200 + 201 + .map { 202 + box-sizing: border-box; 203 + width: calc(64 * var(--scale)); 204 + height: calc(64 * var(--scale)); 205 + background-image: url("../../assets/mc_map.png"); 206 + background-size: 100%; 207 + image-rendering: pixelated; 208 + position: relative; 209 + } 210 + </style>
-186
src/components/navigation/Nav.astro
··· 1 - --- 2 - import type { nav } from "@/content/config"; 3 - import { getEntry } from "astro:content"; 4 - 5 - import Sidebar from "./Sidebar.astro"; 6 - import Hamburger from "@/assets/hamburger.svg"; 7 - 8 - const data = (await getEntry("nav", "urls")?.then((x) => x.data)) ?? []; 9 - --- 10 - 11 - <nav> 12 - <h1>๐Ÿชค | vielle.dev</h1> 13 - <ul class="desktop"> 14 - { 15 - (() => { 16 - const a = (name: string, href: string) => <a {href}>{name}</a>; 17 - const render = ( 18 - name: string, 19 - children: nav[], 20 - popout: boolean = true, 21 - ) => { 22 - const list = ( 23 - <ul> 24 - {children.map((x) => ( 25 - <li> 26 - {x.children 27 - ? render(x.name, x.children, false) 28 - : a(x.name, x.url || "")} 29 - </li> 30 - ))} 31 - </ul> 32 - ); 33 - return popout ? ( 34 - <details name="nav"> 35 - <summary> 36 - <span>{name}</span> 37 - </summary> 38 - {list} 39 - </details> 40 - ) : ( 41 - <> 42 - <span>{name}</span> 43 - {list} 44 - </> 45 - ); 46 - }; 47 - return data.map((entry) => ( 48 - <li> 49 - {entry.children 50 - ? render(entry.name, entry.children) 51 - : a(entry.name, entry.url || "")} 52 - </li> 53 - )); 54 - })() 55 - } 56 - </ul> 57 - 58 - <button class="mobile" popovertarget="sidebar"><Hamburger /></button> 59 - 60 - <Sidebar /> 61 - </nav> 62 - 63 - <style> 64 - nav { 65 - background-color: white; 66 - color: black; 67 - border: 5px solid black; 68 - border-radius: 0 0 20px 20px; 69 - box-shadow: 0 10px; 70 - display: flex; 71 - flex-direction: row; 72 - align-items: center; 73 - justify-content: center; 74 - padding: 10px 40px; 75 - } 76 - 77 - nav > ul { 78 - display: flex; 79 - flex-direction: row; 80 - align-items: center; 81 - justify-content: center; 82 - gap: 10px; 83 - 84 - & > li { 85 - list-style-type: none; 86 - display: flex; 87 - flex-direction: row; 88 - align-items: center; 89 - justify-content: center; 90 - gap: 10px; 91 - &:not(:first-child)::before { 92 - content: ""; 93 - display: block; 94 - width: 5px; 95 - height: 5px; 96 - border-radius: 2.5px; 97 - background-color: currentColor; 98 - } 99 - } 100 - } 101 - 102 - details { 103 - position: relative; 104 - 105 - summary::marker { 106 - content: url(../../assets/arrow-right.svg); 107 - + { 108 - margin-left: 5px; 109 - } 110 - } 111 - &[open] > summary::marker { 112 - content: url(../../assets/arrow-down.svg); 113 - } 114 - } 115 - 116 - details > ul { 117 - background-color: white; 118 - border: 5px solid black; 119 - border-radius: 20px; 120 - box-shadow: 0 10px; 121 - 122 - padding: 10px 20px; 123 - width: max-content; 124 - 125 - ul { 126 - margin-left: 1em; 127 - } 128 - } 129 - 130 - /* positioning */ 131 - details[open] { 132 - anchor-name: --detail-anchor; 133 - > ul { 134 - position: absolute; 135 - 136 - /* fallback for no anchor support */ 137 - right: -20px; 138 - 139 - /* remove fallback when supported */ 140 - @supports (anchor-name: --supports-anchor) { 141 - position: fixed; 142 - right: unset; 143 - } 144 - 145 - /* anchor positioning. all properties should progressive enhance */ 146 - position-anchor: --detail-anchor; 147 - position-area: bottom span-right; 148 - position-try-fallbacks: flip-inline; 149 - position-try: flip-inline; 150 - } 151 - } 152 - 153 - h1 { 154 - margin-right: auto; 155 - font-size: 1.5rem; 156 - white-space: nowrap; 157 - } 158 - 159 - button:has(svg) { 160 - padding: 0; 161 - border: none; 162 - background-color: transparent; 163 - 164 - width: 2em; 165 - height: 2em; 166 - 167 - & svg { 168 - width: 100%; 169 - height: 100%; 170 - } 171 - } 172 - 173 - .mobile { 174 - display: none; 175 - } 176 - 177 - @media screen and (max-width: 650px) { 178 - .mobile { 179 - display: var(--display, block) !important; 180 - } 181 - 182 - .desktop { 183 - display: none !important; 184 - } 185 - } 186 - </style>
-100
src/components/navigation/Sidebar.astro
··· 1 - --- 2 - import type { nav } from "@/content/config"; 3 - import { getEntry } from "astro:content"; 4 - 5 - const data = (await getEntry("nav", "urls")?.then((x) => x.data)) ?? []; 6 - --- 7 - 8 - <aside id="sidebar" popover> 9 - <h2>๐Ÿชค | vielle.dev</h2> 10 - 11 - <nav> 12 - { 13 - (() => { 14 - const step = (entry: nav[]) => ( 15 - <ul> 16 - {entry.map((x) => ( 17 - <li> 18 - {x.url ? <a href={x.url}>{x.name}</a> : <span>{x.name}</span>} 19 - {x.children && step(x.children)} 20 - </li> 21 - ))} 22 - </ul> 23 - ); 24 - return step(data); 25 - })() 26 - } 27 - </nav> 28 - </aside> 29 - 30 - <style> 31 - aside { 32 - inset: auto; 33 - top: 0; 34 - right: 0; 35 - height: 100%; 36 - 37 - background-color: white; 38 - color: black; 39 - border: 5px solid black; 40 - border-radius: 20px 0 0 20px; 41 - box-shadow: 0 10px; 42 - padding: 10px 20px; 43 - 44 - & ul { 45 - padding-inline: 1em; 46 - } 47 - 48 - &::backdrop { 49 - background-color: #00000080; 50 - backdrop-filter: blur(15px); 51 - } 52 - 53 - /* animations */ 54 - --popover-animation-timing: 0.2s; 55 - @media (prefers-reduced-motion: reduce) { 56 - --popover-animation-timing: 0; 57 - } 58 - --popover-animation-easing: ease-in-out; 59 - 60 - transition: 61 - translate var(--popover-animation-timing, 0.2s) 62 - var(--popover-animation-easing, linear) allow-discrete, 63 - overlay var(--popover-animation-timing, 0.2s) 64 - var(--popover-animation-easing, linear) allow-discrete, 65 - display var(--popover-animation-timing, 0.2s) 66 - var(--popover-animation-easing, linear) allow-discrete; 67 - 68 - /* exit */ 69 - translate: 100% 0; 70 - /* base */ 71 - &:popover-open { 72 - translate: 0 0; 73 - /* enter */ 74 - @starting-style { 75 - translate: 100% 0; 76 - } 77 - } 78 - 79 - &::backdrop { 80 - transition: 81 - display var(--popover-animation-timing) 82 - var(--popover-animation-easing, linear) allow-discrete, 83 - overlay var(--popover-animation-timing, 0.2s) 84 - var(--popover-animation-easing, linear) allow-discrete, 85 - opacity var(--popover-animation-timing) 86 - var(--popover-animation-easing, linear) allow-discrete; 87 - 88 - /* exit */ 89 - opacity: 0; 90 - } 91 - /* base */ 92 - &:popover-open::backdrop { 93 - opacity: 1; 94 - /* enter */ 95 - @starting-style { 96 - opacity: 0; 97 - } 98 - } 99 - } 100 - </style>
+25 -70
src/config.ts
··· 1 1 export const blog = { 2 2 // overrideHour: 0, 3 3 post: { 4 - width: 300, 5 - xPadding: 20, 6 - yLeeway: 50, 7 - yGap: 200, 8 - topYGap: 350, 4 + width: 30, 5 + xPadding: 2, 6 + yLeeway: 5, 7 + yGap: 20, 8 + topYGap: 35, 9 9 drift: [0.1, 1], 10 10 timing: [10, 20], 11 11 }, ··· 19 19 20 20 clouds: { 21 21 count: 8, 22 - width: [400, 800], 23 - height: [150, 300], 24 - yGap: [150, 250], 22 + width: [40, 80], 23 + height: [15, 30], 24 + yGap: [15, 25], 25 25 26 26 bumpRadius: [20, 60], 27 27 gradientStops: [35, 80], ··· 29 29 30 30 stars: { 31 31 count: 40, 32 - size: [20, 50], 32 + size: [2, 5], 33 33 prongs: [4, 8], 34 34 rotateSpeed: [20, 40], 35 35 }, ··· 40 40 }, 41 41 balloons: { 42 42 numBalloons: [1, 3], 43 - length: [50, 150], 44 - offset: [-25, 25], 43 + length: [5, 15], 44 + offset: [-2.5, 2.5], 45 45 rotation: [-10, 10], 46 46 timing: [30, 45], 47 47 size: [ 48 - [50, 100], 49 - [100, 200], 48 + [5, 10], 49 + [10, 20], 50 50 ], 51 51 opacity: [0.6, 0.9], 52 52 time: [2, 5], 53 53 }, 54 54 palette: { 55 - environment: { 56 - sky: { 57 - // blue 58 - day: "#1E90FF", 59 - // black 60 - night: "#39375B", 61 - }, 62 - // yellow 63 - sun: "#FFEC51", 64 - // whites 65 - moon: "#E5D4ED", 66 - clouds: "#E5D4ED", 67 - stars: "#ffffff", 55 + sky: { 56 + // blue 57 + day: "#1E90FF", 58 + // black 59 + night: "#39375B" 68 60 }, 69 - 70 - post: { 71 - light: { 72 - background: { 73 - main: "#f2f6fc", 74 - secondary: "#e7e8ea", 75 - code: "#ffffff", 76 - }, 77 - typography: { 78 - body: "#070e21", 79 - heading: "#070e21", 80 - subheading: "#040710", 81 - url: "#1f3e98", 82 - visited: "#931f82", 83 - code: "#137B81", 84 - }, 85 - }, 86 - 87 - dark: { 88 - background: { 89 - main: "#262428", 90 - secondary: "#161418", 91 - code: "#303446", 92 - }, 93 - typography: { 94 - body: "#ffebff", 95 - heading: "#ffe8ff", 96 - subheading: "#ffe0ff", 97 - url: "#a8a8ff", 98 - visited: "#ff80ff", 99 - code: "#81c8be", 100 - }, 101 - }, 102 - 103 - rainbow: [ 104 - "#F09094", 105 - "#F6B379", 106 - "#F6E8A2", 107 - "#97BB77", 108 - "#C2D7FF", 109 - "#D784C9", 110 - ], 111 - }, 112 - }, 61 + // yellow 62 + sun: "#FFEC51", 63 + // whites 64 + moon: "#E5D4ED", 65 + clouds: "#E5D4ED", 66 + stars: "#ffffff", 67 + } 113 68 } as const; 114 69 115 70 export const utils = {
-50
src/content/config.ts
··· 1 - import { defineCollection, z } from "astro:content"; 2 - import { file, glob } from "astro/loaders"; 3 - 4 - const blog = defineCollection({ 5 - loader: glob({ pattern: "**/*.md", base: "./src/content/posts" }), 6 - schema: z.object({ 7 - title: z.string(), 8 - date: z.date(), 9 - colour: z.string(), 10 - // no alt (empty as decorative) 11 - image: z 12 - .string() 13 - .refine( 14 - (value) => value.endsWith(".png"), 15 - (val) => ({ 16 - message: `${val} must end with .png`, 17 - }), 18 - ) 19 - .optional(), 20 - hasMdx: z.boolean().default(false), 21 - }), 22 - }); 23 - 24 - const blogMdx = defineCollection({ 25 - loader: glob({ pattern: "**/*.mdx", base: "./src/content/posts" }), 26 - schema: z.object({ 27 - title: z.string(), 28 - }), 29 - }); 30 - 31 - export type nav = { 32 - name: string; 33 - url: string | false; 34 - children?: nav[]; 35 - }; 36 - 37 - const navSchema: z.ZodType<nav> = z.lazy(() => 38 - z.object({ 39 - name: z.string(), 40 - url: z.string().or(z.literal(false)), 41 - children: z.optional(z.array(navSchema)), 42 - }), 43 - ); 44 - 45 - const nav = defineCollection({ 46 - loader: file("src/content/navList.json"), 47 - schema: z.array(navSchema), 48 - }); 49 - 50 - export const collections = { blog, blogMdx, nav };
-76
src/content/navList.json
··· 1 - { 2 - "urls": [ 3 - { 4 - "url": "/", 5 - "name": "Home" 6 - }, 7 - { 8 - "url": "/blog", 9 - "name": "Blog" 10 - }, 11 - { 12 - "url": false, 13 - "name": "More", 14 - "children": [ 15 - { 16 - "url": "/rss.xml", 17 - "name": "RSS" 18 - }, 19 - { 20 - "url": "/ai", 21 - "name": "AI Usage" 22 - }, 23 - { 24 - "url": "/use", 25 - "name": "Things I Use" 26 - } 27 - ] 28 - }, 29 - { 30 - "url": false, 31 - "name": "Socials", 32 - "children": [ 33 - { 34 - "url": "https://pdsls.dev/at://did:plc:4zht3z4caxwrw3dlsybodywc", 35 - "name": "atproto (pdsls)", 36 - "children": [ 37 - { 38 - "url": "https://deer.social/profile/did:plc:4zht3z4caxwrw3dlsybodywc", 39 - "name": "Bluesky" 40 - }, 41 - { 42 - "url": "https://tangled.sh/@vielle.dev", 43 - "name": "Tangled.sh" 44 - } 45 - ] 46 - }, 47 - { 48 - "url": "https://what-if-doctor-who-was-yuri-yaoi.tumblr.com/", 49 - "name": "Tumblr" 50 - }, 51 - { 52 - "url": "https://github.com/afterlifepro/", 53 - "name": "Github" 54 - } 55 - ] 56 - }, 57 - { 58 - "url": false, 59 - "name": "Projects", 60 - "children": [ 61 - { 62 - "url": "https://dong.vielle.dev", 63 - "name": "Dong (web)" 64 - }, 65 - { 66 - "url": "https://saltire-the-gays.vielle.dev", 67 - "name": "Saltire the Gays" 68 - }, 69 - { 70 - "url": "https://afterlifepro.neocities.org", 71 - "name": "Neocities (old site)" 72 - } 73 - ] 74 - } 75 - ] 76 - }
-1
src/content/posts
··· 1 - ../../posts
+49
src/content.config.ts
··· 1 + import { defineCollection, z } from "astro:content"; 2 + import { file, glob } from "astro/loaders"; 3 + 4 + const blog = defineCollection({ 5 + loader: glob({ pattern: "**/*.md", base: "./src/posts" }), 6 + schema: z.object({ 7 + title: z.string(), 8 + date: z.date(), 9 + colour: z.string(), 10 + // no alt (empty as decorative) 11 + image: z 12 + .string() 13 + .refine( 14 + (value) => value.endsWith(".png"), 15 + (val) => ({ 16 + message: `${val} must end with .png`, 17 + }), 18 + ) 19 + .optional(), 20 + hasMdx: z.boolean().default(false), 21 + }), 22 + }); 23 + 24 + const blogMdx = defineCollection({ 25 + loader: glob({ pattern: "**/*.mdx", base: "./src/posts" }), 26 + schema: z.object({ 27 + title: z.string(), 28 + }), 29 + }); 30 + 31 + const baseNav = z.object({ 32 + slug: z.string(), 33 + name: z.string(), 34 + }); 35 + 36 + export type nav = z.infer<typeof baseNav> & { 37 + children?: nav[]; 38 + }; 39 + 40 + const navSchema: z.ZodType<nav> = baseNav.extend({ 41 + children: z.lazy(() => navSchema.array()), 42 + }); 43 + 44 + const nav = defineCollection({ 45 + loader: file("src/navList.json"), 46 + schema: navSchema, 47 + }); 48 + 49 + export const collections = { blog, blogMdx, nav };
+28
src/navList.json
··· 1 + [ 2 + { 3 + "slug": "/", 4 + "name": "Home", 5 + "children": [] 6 + }, 7 + { 8 + "slug": "/blog", 9 + "name": "Blog", 10 + "children": [] 11 + }, 12 + { 13 + "slug": "/testing", 14 + "name": "Testing", 15 + "children": [ 16 + { 17 + "slug": "/123", 18 + "name": "123", 19 + "children": [] 20 + }, 21 + { 22 + "slug": "/maoii", 23 + "name": "Me!", 24 + "children": [] 25 + } 26 + ] 27 + } 28 + ]
+6 -178
src/pages/blog/[id].astro
··· 1 1 --- 2 2 import Base from "@/Base.astro"; 3 - import Nav from "@/components/navigation/Nav.astro"; 4 - import LightDarkToggle from "@/components/generic/LightDarkToggle.astro"; 5 - import CodeHeading from "@/components/blog/CodeHeading.astro"; 6 - 7 - import { render } from "astro:content"; 8 3 import { getEntry } from "astro:content"; 9 - import { parse } from "node:path"; 10 - 11 - import { blog } from "@/config"; 12 - import "@/components/blog/post.css"; 13 - 14 - const { 15 - post: { light, dark, rainbow }, 16 - } = blog.palette; 17 - 18 4 const { id } = Astro.params; 19 - if (!id) return Astro.redirect("/404"); 5 + const r404 = Astro.redirect("/404"); 20 6 7 + if (!id) return r404; 21 8 const post = await getEntry("blog", id); 22 - if (!post) return Astro.redirect("/404"); 23 - 24 - const { 25 - data: { title, hasMdx, colour }, 26 - } = post; 27 - 28 - const Content = await (async () => { 29 - if (!hasMdx) return render(post).then((x) => x.Content); 30 - 31 - if (!post.filePath) throw new Error("Post does not have a filepath"); 32 - return import(`../../content/posts/${parse(post.filePath).name}.mdx`).then( 33 - (x) => x.Content, 34 - ); 35 - })(); 9 + if (!post) return r404; 36 10 --- 37 11 38 - <Base {title}> 39 - <Nav /> 40 - <header> 41 - <h1>{title}</h1> 42 - 43 - <LightDarkToggle 44 - colours={{ fg: "var(--bg-main)", bg: "var(--typo-body)" }} 45 - /> 46 - </header> 47 - 48 - <main style={`--accent: ${colour};`}> 49 - <div class="content"> 50 - <Content /> 51 - </div> 52 - </main> 12 + <Base title={post.data.title}> 13 + <h1>{post.data.title}</h1> 14 + <p>{JSON.stringify(post)}</p> 53 15 </Base> 54 - 55 - <CodeHeading colours={{ text: "var(--typo-body)", border: "var(--bg-main)" }} /> 56 - 57 - <script> 58 - document.querySelectorAll(".astro-code").forEach((code) => { 59 - if (!(code instanceof HTMLElement)) return; 60 - 61 - const heading = document.createElement("code-heading"); 62 - heading.setAttribute("contents", code.innerText); 63 - 64 - const lang = code.dataset["language"]; 65 - if (lang && lang !== "plaintext") { 66 - const langEl = document.createElement("span"); 67 - langEl.innerText = "." + lang; 68 - heading.append(langEl); 69 - } 70 - 71 - code.prepend(heading); 72 - }); 73 - </script> 74 - 75 - <!-- page styles --> 76 - <style> 77 - header { 78 - position: fixed; 79 - top: 0; 80 - width: 100%; 81 - z-index: 999; 82 - display: flex; 83 - align-items: center; 84 - justify-content: space-between; 85 - 86 - background-color: var(--bg-secondary); 87 - color: var(--typo-heading); 88 - padding-bottom: 5px; 89 - 90 - & > :global(:not(style, script):last-of-type) { 91 - margin-right: 10px; 92 - margin-top: 5px; 93 - } 94 - } 95 - 96 - body { 97 - background-color: var(--bg-main); 98 - color: var(--typo-body); 99 - } 100 - 101 - .content { 102 - padding-block: 4em; 103 - } 104 - 105 - .content, 106 - :global(.full-width), 107 - :global([data-para-flag--full-width]) { 108 - --padding-inline: 20px; 109 - --content-max-width: 60ch; 110 - --breakout-max-width: 80ch; 111 - 112 - --content-size: min( 113 - 100% - var(--padding-inline) * 2, 114 - var(--content-max-width) 115 - ); 116 - --breakout-size: calc( 117 - (var(--breakout-max-width) - var(--content-max-width)) / 2 118 - ); 119 - 120 - display: grid; 121 - grid-template-columns: 122 - [full-width-start] minmax(var(--padding-inline), 1fr) 123 - [breakout-start] minmax(0, var(--breakout-size)) 124 - [content-start] var(--content-size) [content-end] 125 - minmax(0, var(--breakout-size)) [breakout-end] 126 - minmax(var(--padding-inline), 1fr) [full-width-end]; 127 - 128 - & > :global(*) { 129 - grid-column: content; 130 - } 131 - 132 - & > :global(.breakout), 133 - & > :global([data-para-flag--breakout]) { 134 - grid-column: breakout; 135 - } 136 - 137 - & > :global(.full-width), 138 - & > :global([data-para-flag--full-width]) { 139 - grid-column: full-width; 140 - } 141 - } 142 - 143 - :global(#nav-menu) { 144 - height: 3em; 145 - aspect-ratio: 1; 146 - display: flex; 147 - justify-content: center; 148 - align-items: center; 149 - 150 - & :global(svg) { 151 - stroke: var(--typo-body); 152 - } 153 - } 154 - </style> 155 - 156 - <style 157 - set:html={` 158 - :root { 159 - color-scheme: ${ 160 - Astro.cookies.get("colour-mode")?.value === "light" 161 - ? "light" 162 - : Astro.cookies.get("colour-mode")?.value === "dark" 163 - ? "dark" 164 - : "light dark" 165 - }; 166 - 167 - --bg-main: light-dark(${light.background.main}, ${dark.background.main}); 168 - --bg-secondary: light-dark(${light.background.secondary}, ${dark.background.secondary}); 169 - --bg-code: light-dark(${light.background.code}, ${dark.background.code}); 170 - 171 - --typo-body: light-dark(${light.typography.body}, ${dark.typography.body}); 172 - --typo-heading: light-dark(${light.typography.heading}, ${dark.typography.heading}); 173 - --typo-subheading: light-dark(${light.typography.subheading}, ${dark.typography.subheading}); 174 - --typo-code: light-dark(${light.typography.code}, ${dark.typography.code}); 175 - 176 - --typo-url: light-dark(${light.typography.url}, ${dark.typography.url}); 177 - --typo-visited: light-dark(${light.typography.visited}, ${dark.typography.visited}); 178 - 179 - --rainbow-0: ${rainbow[0]}; 180 - --rainbow-1: ${rainbow[1]}; 181 - --rainbow-2: ${rainbow[2]}; 182 - --rainbow-3: ${rainbow[3]}; 183 - --rainbow-4: ${rainbow[4]}; 184 - --rainbow-5: ${rainbow[5]}; 185 - } 186 - `} 187 - ></style>
+15 -12
src/pages/blog/index.astro
··· 2 2 import Base from "@/Base.astro"; 3 3 import Post from "@/components/blog/Post.astro"; 4 4 import Background from "@/components/blog/Background.astro"; 5 - import Nav from "@/components/navigation/Nav.astro"; 5 + import Nav from "@/components/generic/Nav.astro"; 6 6 7 7 import Rss from "@/assets/rss.svg"; 8 8 ··· 10 10 import { blog } from "@/config"; 11 11 12 12 const posts = await getCollection("blog").then((x) => 13 - x.sort((a, b) => b.data.date.getTime() - a.data.date.getTime()), 13 + x.sort((a, b) => b.data.date.getTime() - a.data.date.getTime()) 14 14 ); 15 + const nav = await getCollection("nav").then((x) => x.map((x) => x.data)); 15 16 --- 16 17 17 18 <style> ··· 21 22 height: 2em; 22 23 aspect-ratio: 1; 23 24 padding: 0.2em; 24 - border-radius: 5px; 25 + border-radius: 0.5rem; 25 26 26 27 & svg { 27 28 width: 1.6em; ··· 30 31 } 31 32 32 33 heading { 34 + font-size: 1.6rem; 33 35 margin-bottom: var(--y-gap); 34 36 color: white; 35 37 ··· 42 44 justify-content: space-between; 43 45 44 46 & a { 45 - margin: 5px 10px; 47 + margin: 0.5rem 1rem; 46 48 } 47 49 } 48 50 49 51 .top-offset { 50 52 height: var(--top-gap); 51 53 } 52 - 53 - :global(#nav-menu) { 54 - background-color: black; 55 - padding: 10px; 56 - border-radius: 0 0 50% 0; 57 - } 58 54 </style> 59 55 60 56 <Base title="Blog"> 61 - <Nav /> 62 57 <Background /> 63 58 <main> 64 - <div class="top-offset" style={`--top-gap: ${blog.post.topYGap}px;`}></div> 59 + <heading style={`--y-gap: ${blog.post.yGap}rem`}> 60 + <Nav data={nav} current="Blog" /> 61 + 62 + <a href="/rss.xml" aria-label="Rss Feed"> 63 + <Rss width="1.6em" height="1.6em" /> 64 + </a> 65 + </heading> 66 + 67 + <div class="top-offset" style={`--top-gap: ${blog.post.topYGap}rem;`}></div> 65 68 66 69 { 67 70 posts.map((x, i) => (
+51 -12
src/pages/index.astro
··· 1 1 --- 2 + // import Map from "@/components/map.astro" 2 3 import Base from "@/Base.astro"; 3 - import Nav from "@/components/navigation/Nav.astro"; 4 + import Map from "@/components/index/Map.astro"; 4 5 --- 5 6 6 - <Base> 7 - <Nav /> 7 + <Base title="home"> 8 + <style slot="head"> 9 + body { 10 + width: 100vw; 11 + height: 100vh; 12 + display: flex; 13 + align-items: center; 14 + justify-content: center; 15 + flex-direction: column; 16 + gap: 5rem; 17 + padding: 0; 18 + margin: 0; 19 + background-color: #011627; 20 + color: #f8f8f2; 21 + } 22 + </style> 23 + <h1>vielle.dev ๐Ÿชค | wip</h1> 24 + <Map 25 + locations={[ 26 + { 27 + colour: "red", 28 + name: "Blog", 29 + href: "/blog", 30 + x: 6, 31 + y: 2, 32 + }, 33 + { 34 + colour: "magenta", 35 + name: "Projects", 36 + href: "/projects", 37 + x: 6, 38 + y: 5, 39 + }, 40 + { 41 + colour: "blue", 42 + name: "Hobbies", 43 + href: "/hobbies", 44 + x: 1, 45 + y: 4, 46 + }, 47 + { 48 + colour: "cyan", 49 + name: "Linktree", 50 + href: "/linktree", 51 + x: 3, 52 + y: 2, 53 + }, 54 + ]} 55 + /> 8 56 </Base> 9 - 10 - <style> 11 - body { 12 - width: 100vw; 13 - height: 100vh; 14 - background-color: #011627; 15 - color: #f8f8f2; 16 - } 17 - </style>
+1
src/posts
··· 1 + ../posts
+5
svelte.config.js
··· 1 + import { vitePreprocess } from "@astrojs/svelte"; 2 + 3 + export default { 4 + preprocess: vitePreprocess(), 5 + };
+86
wrangler.toml
··· 1 + #:schema node_modules/wrangler/config-schema.json 2 + name = "astral-powers-v2" 3 + compatibility_date = "2025-01-09" 4 + compatibility_flags = ["nodejs_compat"] 5 + pages_build_output_dir = "./dist" 6 + 7 + # Automatically place your workloads in an optimal location to minimize latency. 8 + # If you are running back-end logic in a Pages Function, running it closer to your back-end infrastructure 9 + # rather than the end user may result in better performance. 10 + # Docs: https://developers.cloudflare.com/pages/functions/smart-placement/#smart-placement 11 + # [placement] 12 + # mode = "smart" 13 + 14 + # Variable bindings. These are arbitrary, plaintext strings (similar to environment variables) 15 + # Docs: 16 + # - https://developers.cloudflare.com/pages/functions/bindings/#environment-variables 17 + # Note: Use secrets to store sensitive data. 18 + # - https://developers.cloudflare.com/pages/functions/bindings/#secrets 19 + # [vars] 20 + # MY_VARIABLE = "production_value" 21 + 22 + # Bind the Workers AI model catalog. Run machine learning models, powered by serverless GPUs, on Cloudflareโ€™s global network 23 + # Docs: https://developers.cloudflare.com/pages/functions/bindings/#workers-ai 24 + # [ai] 25 + # binding = "AI" 26 + 27 + # Bind a D1 database. D1 is Cloudflareโ€™s native serverless SQL database. 28 + # Docs: https://developers.cloudflare.com/pages/functions/bindings/#d1-databases 29 + # [[d1_databases]] 30 + # binding = "MY_DB" 31 + # database_name = "my-database" 32 + # database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 33 + 34 + # Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model. 35 + # Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps. 36 + # Docs: https://developers.cloudflare.com/workers/runtime-apis/durable-objects 37 + # [[durable_objects.bindings]] 38 + # name = "MY_DURABLE_OBJECT" 39 + # class_name = "MyDurableObject" 40 + # script_name = 'my-durable-object' 41 + 42 + # Bind a KV Namespace. Use KV as persistent storage for small key-value pairs. 43 + # Docs: https://developers.cloudflare.com/pages/functions/bindings/#kv-namespaces 44 + # [[kv_namespaces]] 45 + # binding = "MY_KV_NAMESPACE" 46 + # id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 47 + 48 + # Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer. 49 + # Docs: https://developers.cloudflare.com/pages/functions/bindings/#queue-producers 50 + # [[queues.producers]] 51 + # binding = "MY_QUEUE" 52 + # queue = "my-queue" 53 + 54 + # Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files. 55 + # Docs: https://developers.cloudflare.com/pages/functions/bindings/#r2-buckets 56 + # [[r2_buckets]] 57 + # binding = "MY_BUCKET" 58 + # bucket_name = "my-bucket" 59 + 60 + # Bind another Worker service. Use this binding to call another Worker without network overhead. 61 + # Docs: https://developers.cloudflare.com/pages/functions/bindings/#service-bindings 62 + # [[services]] 63 + # binding = "MY_SERVICE" 64 + # service = "my-service" 65 + 66 + # To use different bindings for preview and production environments, follow the examples below. 67 + # When using environment-specific overrides for bindings, ALL bindings must be specified on a per-environment basis. 68 + # Docs: https://developers.cloudflare.com/pages/functions/wrangler-configuration#environment-specific-overrides 69 + 70 + ######## PREVIEW environment config ######## 71 + 72 + # [env.preview.vars] 73 + # API_KEY = "xyz789" 74 + 75 + # [[env.preview.kv_namespaces]] 76 + # binding = "MY_KV_NAMESPACE" 77 + # id = "<PREVIEW_NAMESPACE_ID>" 78 + 79 + ######## PRODUCTION environment config ######## 80 + 81 + # [env.production.vars] 82 + # API_KEY = "abc123" 83 + 84 + # [[env.production.kv_namespaces]] 85 + # binding = "MY_KV_NAMESPACE" 86 + # id = "<PRODUCTION_NAMESPACE_ID>"