Compare commits

..

4 Commits

33 changed files with 1094 additions and 433 deletions

View File

@ -7,25 +7,29 @@
"@fastify/static": "^8.1.1", "@fastify/static": "^8.1.1",
"@mdx-js/rollup": "^3.1.0", "@mdx-js/rollup": "^3.1.0",
"@sindresorhus/slugify": "^2.2.1", "@sindresorhus/slugify": "^2.2.1",
"@tailwindcss/typography": "^0.5.16",
"@universal-middleware/core": "^0.4.7", "@universal-middleware/core": "^0.4.7",
"@universal-middleware/fastify": "^0.5.16", "@universal-middleware/fastify": "^0.5.16",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"fastify": "^5.3.0", "fastify": "^5.3.0",
"prismjs": "^1.30.0",
"solid-heroicons": "^3.2.4", "solid-heroicons": "^3.2.4",
"solid-highlight": "^0.1.26",
"solid-js": "^1.9.5", "solid-js": "^1.9.5",
"solid-jsx": "^1.1.4", "solid-jsx": "^1.1.4",
"solid-mdx": "^0.0.7", "solid-mdx": "^0.0.7",
"solid-toast": "^0.5.0",
"telefunc": "^0.2.3", "telefunc": "^0.2.3",
"terracotta": "^1.0.6", "terracotta": "^1.0.6",
"vike": "^0.4.228", "vike": "^0.4.228",
"vike-solid": "^0.7.9", "vike-solid": "^0.7.9",
"vite-plugin-prismjs": "^0.0.11",
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "1.9.4", "@biomejs/biome": "1.9.4",
"@eslint/js": "^9.24.0", "@eslint/js": "^9.24.0",
"@tailwindcss/vite": "^4.1.3", "@tailwindcss/vite": "^4.1.3",
"@types/node": "^18.19.86", "@types/node": "^18.19.86",
"@types/prismjs": "^1.26.5",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "^9.24.0", "eslint": "^9.24.0",
"eslint-config-prettier": "^10.1.2", "eslint-config-prettier": "^10.1.2",
@ -303,6 +307,8 @@
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+7S63t5zhYjslUGb8NcgLpFXD+Kq1F/zt5Xv5qTv7HaFTG/DHyHD9GA6ieNAxhgyA4IcKa/zy7Xx4Oad2/wuhw=="], "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+7S63t5zhYjslUGb8NcgLpFXD+Kq1F/zt5Xv5qTv7HaFTG/DHyHD9GA6ieNAxhgyA4IcKa/zy7Xx4Oad2/wuhw=="],
"@tailwindcss/typography": ["@tailwindcss/typography@0.5.16", "", { "dependencies": { "lodash.castarray": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA=="],
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.4", "", { "dependencies": { "@tailwindcss/node": "4.1.4", "@tailwindcss/oxide": "4.1.4", "tailwindcss": "4.1.4" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-4UQeMrONbvrsXKXXp/uxmdEN5JIJ9RkH7YVzs6AMxC/KC1+Np7WZBaNIco7TEjlkthqxZbt8pU/ipD+hKjm80A=="], "@tailwindcss/vite": ["@tailwindcss/vite@4.1.4", "", { "dependencies": { "@tailwindcss/node": "4.1.4", "@tailwindcss/oxide": "4.1.4", "tailwindcss": "4.1.4" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-4UQeMrONbvrsXKXXp/uxmdEN5JIJ9RkH7YVzs6AMxC/KC1+Np7WZBaNIco7TEjlkthqxZbt8pU/ipD+hKjm80A=="],
"@ts-morph/common": ["@ts-morph/common@0.20.0", "", { "dependencies": { "fast-glob": "^3.2.12", "minimatch": "^7.4.3", "mkdirp": "^2.1.6", "path-browserify": "^1.0.1" } }, "sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q=="], "@ts-morph/common": ["@ts-morph/common@0.20.0", "", { "dependencies": { "fast-glob": "^3.2.12", "minimatch": "^7.4.3", "mkdirp": "^2.1.6", "path-browserify": "^1.0.1" } }, "sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q=="],
@ -333,6 +339,8 @@
"@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="], "@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="],
"@types/prismjs": ["@types/prismjs@1.26.5", "", {}, "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ=="],
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.30.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.30.1", "@typescript-eslint/type-utils": "8.30.1", "@typescript-eslint/utils": "8.30.1", "@typescript-eslint/visitor-keys": "8.30.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.30.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.30.1", "@typescript-eslint/type-utils": "8.30.1", "@typescript-eslint/utils": "8.30.1", "@typescript-eslint/visitor-keys": "8.30.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q=="],
@ -383,6 +391,8 @@
"babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.39.7", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2", "validate-html-nesting": "^1.2.1" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-8GzVmFla7jaTNWW8W+lTMl9YGva4/06CtwJjySnkYtt8G1v9weCzc2SuF1DfrudcCNb2Doetc1FRg33swBYZCA=="], "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.39.7", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2", "validate-html-nesting": "^1.2.1" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-8GzVmFla7jaTNWW8W+lTMl9YGva4/06CtwJjySnkYtt8G1v9weCzc2SuF1DfrudcCNb2Doetc1FRg33swBYZCA=="],
"babel-plugin-prismjs": ["babel-plugin-prismjs@2.1.0", "", { "peerDependencies": { "prismjs": "^1.18.0" } }, "sha512-ehzSKYfeAz4U78zi/sfwsjDPlq0LvDKxNefcZTJ/iKBu+plsHsLqZhUeGf1+82LAcA35UZGbU6ksEx2Utphc/g=="],
"babel-preset-solid": ["babel-preset-solid@1.9.5", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.39.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-85I3osODJ1LvZbv8wFozROV1vXq32BubqHXAGu73A//TRs3NLI1OFP83AQBUTSQHwgZQmARjHlJciym3we+V+w=="], "babel-preset-solid": ["babel-preset-solid@1.9.5", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.39.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-85I3osODJ1LvZbv8wFozROV1vXq32BubqHXAGu73A//TRs3NLI1OFP83AQBUTSQHwgZQmARjHlJciym3we+V+w=="],
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
@ -441,6 +451,8 @@
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="], "debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="],
@ -685,6 +697,10 @@
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
"lodash.castarray": ["lodash.castarray@4.4.0", "", {}, "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="],
"lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="],
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
@ -831,6 +847,8 @@
"postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
"postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="],
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
"prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="], "prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="],
@ -915,8 +933,6 @@
"solid-heroicons": ["solid-heroicons@3.2.4", "", { "dependencies": { "solid-js": "^1.7.6" } }, "sha512-u6BMdFLvkJnvUGYzdFcWp1wvJ4hb9Y1zd3AbZ9D3bUmmiy9jBzNZX+RcqBCI2EKRvdQwAb1UB9bkESfqfhayDg=="], "solid-heroicons": ["solid-heroicons@3.2.4", "", { "dependencies": { "solid-js": "^1.7.6" } }, "sha512-u6BMdFLvkJnvUGYzdFcWp1wvJ4hb9Y1zd3AbZ9D3bUmmiy9jBzNZX+RcqBCI2EKRvdQwAb1UB9bkESfqfhayDg=="],
"solid-highlight": ["solid-highlight@0.1.26", "", { "peerDependencies": { "prismjs": "^1.29.0", "solid-js": "^1.8.0" } }, "sha512-Iw1mi3vE+YCBBBU/+HHc5y8VNULaGXUX4OK2c9TbzegOGCitzW0uNIvb0s3S0KoVv7Uma/KadWHNFXkwZCwPgQ=="],
"solid-js": ["solid-js@1.9.5", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "^1.1.0", "seroval-plugins": "^1.1.0" } }, "sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw=="], "solid-js": ["solid-js@1.9.5", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "^1.1.0", "seroval-plugins": "^1.1.0" } }, "sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw=="],
"solid-jsx": ["solid-jsx@1.1.4", "", { "peerDependencies": { "solid-js": ">=1.4.0" } }, "sha512-A4E9cB+wZpHZrXzv3+OWr6zaGS0FjD/UAKqbI38R1JwogjlBXdSGC2PgaIMisnGYKL3oJ55FPLv4QRkENmdbWQ=="], "solid-jsx": ["solid-jsx@1.1.4", "", { "peerDependencies": { "solid-js": ">=1.4.0" } }, "sha512-A4E9cB+wZpHZrXzv3+OWr6zaGS0FjD/UAKqbI38R1JwogjlBXdSGC2PgaIMisnGYKL3oJ55FPLv4QRkENmdbWQ=="],
@ -925,6 +941,8 @@
"solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="], "solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="],
"solid-toast": ["solid-toast@0.5.0", "", { "peerDependencies": { "solid-js": "^1.5.4" } }, "sha512-t770JakjyS2P9b8Qa1zMLOD51KYKWXbTAyJePVUoYex5c5FH5S/HtUBUbZAWFcqRCKmAE8KhyIiCvDZA8bOnxQ=="],
"solid-use": ["solid-use@0.9.1", "", { "peerDependencies": { "solid-js": "^1.7" } }, "sha512-UwvXDVPlrrbj/9ewG9ys5uL2IO4jSiwys2KPzK4zsnAcmEl7iDafZWW1Mo4BSEWOmQCGK6IvpmGHo1aou8iOFw=="], "solid-use": ["solid-use@0.9.1", "", { "peerDependencies": { "solid-js": "^1.7" } }, "sha512-UwvXDVPlrrbj/9ewG9ys5uL2IO4jSiwys2KPzK4zsnAcmEl7iDafZWW1Mo4BSEWOmQCGK6IvpmGHo1aou8iOFw=="],
"sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="], "sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="],
@ -1025,6 +1043,8 @@
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
"validate-html-nesting": ["validate-html-nesting@1.2.2", "", {}, "sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg=="], "validate-html-nesting": ["validate-html-nesting@1.2.2", "", {}, "sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg=="],
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
@ -1037,6 +1057,8 @@
"vite": ["vite@6.3.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.3", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.12" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg=="], "vite": ["vite@6.3.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.3", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.12" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg=="],
"vite-plugin-prismjs": ["vite-plugin-prismjs@0.0.11", "", { "dependencies": { "@babel/core": "^7.15.5", "babel-plugin-prismjs": "^2.1.0" } }, "sha512-20NBQxg/zH+3FTrlU6BQTob720xkuXNYtrx7psAQ4E6pMcRDeLEK77QU9kXURU587+f2To7ASH1JVTGbXVV/vQ=="],
"vite-plugin-solid": ["vite-plugin-solid@2.11.6", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-Sl5CTqJTGyEeOsmdH6BOgalIZlwH3t4/y0RQuFLMGnvWMBvxb4+lq7x3BSiAw6etf0QexfNJW7HSOO/Qf7pigg=="], "vite-plugin-solid": ["vite-plugin-solid@2.11.6", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-Sl5CTqJTGyEeOsmdH6BOgalIZlwH3t4/y0RQuFLMGnvWMBvxb4+lq7x3BSiAw6etf0QexfNJW7HSOO/Qf7pigg=="],
"vitefu": ["vitefu@1.0.6", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA=="], "vitefu": ["vitefu@1.0.6", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" }, "optionalPeers": ["vite"] }, "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA=="],

View File

@ -9,7 +9,7 @@ const variantStyles = {
secondary: secondary:
"bg-slate-800 font-medium text-white hover:bg-slate-700 focus:outline-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white/50 active:text-slate-400", "bg-slate-800 font-medium text-white hover:bg-slate-700 focus:outline-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white/50 active:text-slate-400",
ghost: ghost:
"bg-transparent font-medium text-slate-900 dark:text-slate-400 hover:bg-slate-100 focus:outline-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-300/50 active:bg-slate-200", "bg-transparent font-medium text-slate-900 hover:bg-slate-100 focus:outline-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-300/50 active:bg-slate-200",
}; };
const sizeStyles = { const sizeStyles = {

View File

@ -5,22 +5,19 @@ import clsx from "clsx";
const styles = { const styles = {
note: { note: {
container: container: "bg-violet-50",
"bg-violet-50 dark:bg-violet-800/60 dark:ring-1 dark:ring-violet-300/10", title: "text-violet-900",
title: "text-violet-900 dark:text-violet-400", body: "text-slate-800 [--tw-prose-background:var(--color-slate-50)] prose-a:text-slate-900 prose-code:text-slate-900",
body: "text-slate-800 [--tw-prose-background:var(--color-slate-50)] prose-a:text-slate-900 prose-code:text-slate-900 dark:text-slate-300 dark:prose-code:text-slate-300",
}, },
warning: { warning: {
container: container: "bg-amber-50",
"bg-amber-50 dark:bg-amber-800/60 dark:ring-1 dark:ring-amber-300/10", title: "text-amber-900",
title: "text-amber-900 dark:text-amber-500", body: "text-slate-800 [--tw-prose-underline:var(--color-slate-400)] [--tw-prose-background:var(--color-slate-50)] prose-a:text-slate-900 prose-code:text-slate-900",
body: "text-slate-800 [--tw-prose-underline:var(--color-slate-400)] [--tw-prose-background:var(--color-slate-50)] prose-a:text-slate-900 prose-code:text-slate-900 dark:text-slate-300 dark:[--tw-prose-underline:var(--color-slate-700)] dark:prose-code:text-slate-300",
}, },
question: { question: {
container: container: "bg-amber-50",
"bg-amber-50 dark:bg-amber-800/60 dark:ring-1 dark:ring-amber-300/10", title: "text-amber-900",
title: "text-amber-900 dark:text-amber-500", body: "text-slate-800 [--tw-prose-underline:var(--color-slate-400)] [--tw-prose-background:var(--color-slate-50)] prose-a:text-slate-900 prose-code:text-slate-900",
body: "text-slate-800 [--tw-prose-underline:var(--color-slate-400)] [--tw-prose-background:var(--color-slate-50)] prose-a:text-slate-900 prose-code:text-slate-900 dark:text-slate-300 dark:[--tw-prose-underline:var(--color-slate-700)] dark:prose-code:text-slate-300",
}, },
}; };

View File

@ -42,9 +42,7 @@ export function Toggle(props: ToggleProps) {
/> />
</span> </span>
<span class="ml-2 text-sm text-slate-700 dark:text-slate-300"> <span class="ml-2 text-sm text-slate-700">{props.label}</span>
{props.label}
</span>
</label> </label>
</div> </div>
); );

View File

@ -0,0 +1,361 @@
import type { JSX, ComponentProps, ParentComponent } from "solid-js";
import { createEffect, createMemo, mergeProps, on, splitProps } from "solid-js";
import * as Prismjs from "prismjs";
/**
* @see https://prismjs.com/#supported-languages
*/
export const Language = {
JAVASCRIPT: "javascript",
HTML: "html",
CSS: "css",
MARKUP: "markup",
XML: "xml",
SVG: "svg",
ABAP: "abap",
ABNF: "abnf",
ACTION_SCRIPT: "actionscript",
ADA: "ada",
AGDA: "agda",
AL: "al",
ANTLR4: "antlr4",
G4: "g4",
APACHE_CONFIGURATION: "apacheconf",
APEX: "apex",
APL: "apl",
APPLESCRIPT: "applescript",
AQL: "aql",
ARDUINO: "arduino",
ARFF: "arff",
ARM_ASSEMBLY: "armasm",
ARTURO: "arturo",
ASCIIDOC: "asciidoc",
ASP_NET: "aspnet",
ASSEMBLY_6502: "asm6502",
ASSEMBLY_ATMEL_AVR: "asmatmel",
AUTO_HOTKEY: "autohotkey",
AUTO_IT: "autoit",
AVI_SYNTH: "avisynth",
AVRO_IDL: "avro-idl",
AWK: "awk",
BASH: "bash",
BASIC: "basic",
BATCH: "batch",
BBCODE: "bbcode",
BBJ: "bbj",
BICEP: "bicep",
BIRB: "birb",
BISON: "bison",
BNF: "bnf",
BQN: "bqn",
BRAINFUCK: "brainfuck",
BRIGHT_SCRIPT: "brightscript",
BRO: "bro",
BSL: "bsl",
C: "c",
CSHARP: "csharp",
CPP: "cpp",
CF_SCRIPT: "cfscript",
CHAI_SCRIPT: "chaiscript",
CIL: "cil",
CILK_C: "cilkc",
CILK_CPP: "cilkcpp",
CLOJURE: "clojure",
CMAKE: "cmake",
COBOL: "cobol",
COFFEE_SCRIPT: "coffeescript",
CONCURNAS: "concurnas",
CONTENT_SECURITY_POLICY: "csp",
COOKLANG: "cooklang",
Coq: "coq",
CRYSTAL: "crystal",
CSS_EXTRAS: "css-extras",
CSV: "csv",
CUE: "cue",
CYPHER: "cypher",
D: "d",
DART: "dart",
DATA_WEAVE: "dataweave",
DAX: "dax",
DHALL: "dhall",
DIFF: "diff",
DJANGO: "django",
JINJA2: "jinja2",
DNS_ZONE_FILE: "dns-zone-file",
DOCKER: "docker",
DOT: "dot",
EBNF: "ebnf",
EDITOR_CONFIG: "editorconfig",
EIFFEL: "eiffel",
EJS: "ejs",
ELIXIR: "elixir",
ELM: "elm",
EMBEDDED_LUA_TEMPLATING: "etlua",
ERB: "erb",
ERLANG: "erlang",
EXCEL_FORMULA: "excel-formula",
FSHARP: "fsharp",
FACTOR: "factor",
FALSE: "false",
FIRESTORE_SECURITY_RULES: "firestore-security-rules",
FLOW: "flow",
FORTRAN: "fortran",
FREEMARKER_TEMPLATE_LANGUAGE: "ftl",
GAMEMAKER_LANGUAGE: "gml",
GAP: "gap",
GCODE: "gcode",
GD_SCRIPT: "gdscript",
GEDCOM: "gedcom",
GETTEXT: "gettext",
GHERKIN: "gherkin",
GIT: "git",
GLSL: "glsl",
GN: "gn",
GNU_LINKER_SCRIPT: "linker-script",
GO: "go",
GO_MODULE: "go-module",
GRADLE: "gradle",
GRAPHQL: "graphql",
GROOVY: "groovy",
HAML: "haml",
HANDLEBARS: "handlebars",
HASKELL: "haskell",
HAXE: "haxe",
HCL: "hcl",
HLSL: "hlsl",
HOON: "hoon",
HTTP: "http",
HTTP_PUBLIC_KEY_PINS: "hpkp",
HTTP_STRICT_TRANSPORT_SECURITY: "hsts",
ICHIGOJAM: "ichigojam",
ICON: "icon",
ICU_MESSAGE_FORMAT: "icu-message-format",
IDRIS: "idris",
IGNORE: "ignore",
INFORM_7: "inform7",
INI: "ini",
IO: "io",
J: "j",
JAVA: "java",
JAVADOC: "javadoc",
JAVADOC_LIKE: "javadoclike",
JAVA_STACK_TRACE: "javastacktrace",
JEXL: "jexl",
JOLIE: "jolie",
JQ: "jq",
JSDOC: "jsdoc",
JS_EXTRAS: "js-extras",
JSON: "json",
JSON5: "json5",
JSONP: "jsonp",
JS_STACK_TRACE: "jsstacktrace",
JS_TEMPLATES: "js-templates",
JULIA: "julia",
KEEPALIVED_CONFIGURE: "keepalived",
KEYMAN: "keyman",
KOTLIN: "kotlin",
KUMIR: "kumir",
KUSTO: "kusto",
LATEX: "latex",
LATTE: "latte",
LESS: "less",
LILYPOND: "lilypond",
LIQUID: "liquid",
LISP: "lisp",
LIVESCRIPT: "livescript",
LLVM: "llvm",
LOG: "log",
LOLCODE: "lolcode",
LUA: "lua",
MAGMA: "magma",
MAKEFILE: "makefile",
MARKDOWN: "markdown",
MARKUP_TEMPLATING: "markup-templating",
MATA: "mata",
MATLAB: "matlab",
MAXSCRIPT: "maxscript",
MEL: "mel",
MERMAID: "mermaid",
METAFONT: "metafont",
MIZAR: "mizar",
MONGODB: "mongodb",
MONKEY: "monkey",
MOONSCRIPT: "moonscript",
N1QL: "n1ql",
N4JS: "n4js",
NAND_TO_TETRIS_HDL: "nand2tetris",
NANINOVEL_SCRIPT: "naniscript",
NASM: "nasm",
NEON: "neon",
NEVOD: "nevod",
NGINX: "nginx",
NIM: "nim",
NIX: "nix",
NSIS: "nsis",
OBJECTIVE_C: "objectivec",
OCAML: "ocaml",
ODIN: "odin",
OPENCL: "opencl",
OPENQASM: "openqasm",
OZ: "oz",
PARI_GP: "parigp",
PARSER: "parser",
PASCAL: "pascal",
PASCALIGO: "pascaligo",
PATROL_SCRIPTING_LANGUAGE: "psl",
PC_AXIS: "pcaxis",
PEOPLECODE: "peoplecode",
PERL: "perl",
PHP: "php",
PHP_DOC: "phpdoc",
PHP_EXTRAS: "php-extras",
PLANT_UML: "plant-uml",
PL_SQL: "plsql",
POWERQUERY: "powerquery",
POWERSHELL: "powershell",
PROCESSING: "processing",
PROLOG: "prolog",
PROMQL: "promql",
PROPERTIES: "properties",
PROTOBUF: "protobuf",
PUG: "pug",
PUPPET: "puppet",
PURE: "pure",
PUREBASIC: "purebasic",
PURESCRIPT: "purescript",
PYTHON: "python",
QSHARP: "qsharp",
Q: "q",
QML: "qml",
QORE: "qore",
R: "r",
RACKET: "racket",
RAZOR: "razor",
REACT_JSX: "jsx",
REACT_TSX: "tsx",
REASON: "reason",
REGEX: "regex",
REGO: "rego",
RENPY: "renpy",
RESCRIPT: "rescript",
REST: "rest",
RIP: "rip",
ROBOCONF: "roboconf",
ROBOT_FRAMEWORK: "robotframework",
RUBY: "ruby",
RUST: "rust",
SAS: "sas",
SASS: "sass",
SCSS: "scss",
SCALA: "scala",
SCHEME: "scheme",
SHELL_SESSION: "shell-session",
SMALI: "smali",
SMALLTALK: "smalltalk",
SMARTY: "smarty",
SML: "sml",
SOLIDITY: "solidity",
SOLUTION_FILE: "solution-file",
SOY: "soy",
SPARQL: "sparql",
SPLUNK_SPL: "splunk-spl",
SQF: "sqf",
SQL: "sql",
SQUIRREL: "squirrel",
STAN: "stan",
STATA_ADO: "stata",
STRUCTURED_TEXT: "iecst",
STYLUS: "stylus",
SUPERCOLLIDER: "supercollider",
SWIFT: "swift",
SYSTEMD: "systemd",
T4_TEMPLATING: "t4-templating",
T4_CSHARP: "t4-cs",
T4_VB: "t4-vb",
TAP: "tap",
TCL: "tcl",
TEMPLATE_TOOLKIT_2: "tt2",
TEXTILE: "textile",
TOML: "toml",
TREMOR: "tremor",
TURTLE: "turtle",
TWIG: "twig",
TYPESCRIPT: "typescript",
TYPOSCRIPT: "typoscript",
UNREALSCRIPT: "unrealscript",
UO_RAZOR_SCRIPT: "uorazor",
URI: "uri",
V: "v",
VALA: "vala",
VB_NET: "vbnet",
VELOCITY: "velocity",
VERILOG: "verilog",
VHDL: "vhdl",
VIM: "vim",
VISUAL_BASIC: "visual-basic",
WARP_SCRIPT: "warpscript",
WEB_ASSEMBLY: "wasm",
WEB_IDL: "web-idl",
WGSL: "wgsl",
WIKI: "wiki",
WOLFRAM: "wolfram",
WREN: "wren",
XEORA: "xeora",
XML_DOC: "xml-doc",
XOJO: "xojo",
XQUERY: "xquery",
YAML: "yaml",
YANG: "yang",
ZIG: "zig",
} as const;
export type Language = (typeof Language)[keyof typeof Language];
type Props = {
language: string;
} & (
| (ComponentProps<"code"> & { code?: never })
| (Omit<JSX.IntrinsicElements["code"], "children"> & { code: string })
);
export const Highlight: ParentComponent<Props> = (_props) => {
const props = mergeProps({ language: "javascript" }, _props);
const [, rest] = splitProps(props, [
"language",
"children",
"class",
"innerHTML",
]);
const languageClass = createMemo(() => `language-${props.language}`);
const highlightedCode = createMemo<string | undefined>(() => {
const childrenString = props.children?.toString();
if (!childrenString) {
return;
}
const grammar = Prismjs.languages[props.language];
if (!grammar) {
return;
}
const result = Prismjs.highlight(childrenString, grammar, props.language);
return result;
});
createEffect(
on([languageClass, highlightedCode], () => {
Prismjs.highlightAll();
}),
);
return (
<pre>
<code
class={`${languageClass()} ${props.class || ""}`}
innerHTML={highlightedCode()}
{...rest}
>
{props.code || props.children}
</code>
</pre>
);
};

View File

@ -34,7 +34,7 @@ function LogomarkPaths() {
export function Logo(props: JSX.IntrinsicElements["svg"]) { export function Logo(props: JSX.IntrinsicElements["svg"]) {
return ( return (
<svg view-box="0 0 58 38" {...props}> <svg viewBox="0 0 58 38" {...props}>
<title>Memento Dev</title> <title>Memento Dev</title>
<LogomarkPaths /> <LogomarkPaths />
</svg> </svg>

View File

@ -31,20 +31,20 @@ function PageLink(props: PageLinkProps) {
return ( return (
<div {...cleanProps(props, "dir", "title")}> <div {...cleanProps(props, "dir", "title")}>
<dt class="font-display text-sm font-medium text-slate-900 dark:text-white"> <dt class="font-display text-sm font-medium text-slate-900">
{props.dir === "next" ? "Suivant" : "Précédent"} {props.dir === "next" ? "Suivant" : "Précédent"}
</dt> </dt>
<dd class="mt-1"> <dd class="mt-1">
<Link <Link
href={props.href} href={props.href}
class={clsx( class={clsx(
"flex items-center gap-x-2 text-base font-semibold text-slate-500 hover:text-slate-600 dark:text-slate-400 dark:hover:text-slate-300", "flex items-center gap-x-2 text-base font-semibold text-slate-500 hover:text-slate-600",
props.dir === "previous" && "flex-row-reverse", props.dir === "previous" && "flex-row-reverse",
)} )}
> >
<p class="flex flex-col gap-0"> <p class="flex flex-col gap-0">
{pageCategory && ( {pageCategory && (
<span class="text-violet-600 dark:text-violet-400 text-sm mb-1 leading-3"> <span class="text-violet-600 text-sm mb-1 leading-3">
{pageCategory.title} {pageCategory.title}
</span> </span>
)} )}
@ -89,7 +89,7 @@ export function PrevNextLinks() {
if (!nextPage && !previousPage) return null; if (!nextPage && !previousPage) return null;
return ( return (
<dl class="mt-12 flex gap-4 border-t border-slate-200 pt-6 dark:border-slate-800"> <dl class="mt-12 flex gap-4 border-t border-slate-200 pt-6">
{previousPage && <PageLink dir="previous" {...previousPage} />} {previousPage && <PageLink dir="previous" {...previousPage} />}
{nextPage && <PageLink class="ml-auto text-right" {...nextPage} />} {nextPage && <PageLink class="ml-auto text-right" {...nextPage} />}
</dl> </dl>

View File

@ -16,19 +16,17 @@ export function Prose(props: ProseProps) {
component={Component} component={Component}
class={clsx( class={clsx(
props.class, props.class,
"prose max-w-none prose-slate dark:text-slate-400 dark:prose-invert", "prose max-w-none prose-slate",
// headings // headings
"prose-headings:scroll-mt-28 prose-headings:font-display prose-headings:font-normal lg:prose-headings:scroll-mt-[8.5rem]", "prose-headings:scroll-mt-28 prose-headings:font-display prose-headings:font-normal lg:prose-headings:scroll-mt-[8.5rem]",
// lead // lead
"prose-lead:text-slate-500 dark:prose-lead:text-slate-400", "prose-lead:text-slate-500",
// links // links
"prose-a:font-semibold dark:prose-a:text-violet-400", "prose-a:font-semibold",
// link underline // link underline
"dark:[--tw-prose-background:var(--color-slate-900)] prose-a:no-underline prose-a:shadow-[inset_0_-2px_0_0_var(--tw-prose-background,#fff),inset_0_calc(-1*(var(--tw-prose-underline-size,4px)+2px))_0_0_var(--tw-prose-underline,var(--color-violet-300))] prose-a:hover:[--tw-prose-underline-size:6px] dark:prose-a:shadow-[inset_0_calc(-1*var(--tw-prose-underline-size,2px))_0_0_var(--tw-prose-underline,var(--color-violet-800))] dark:prose-a:hover:[--tw-prose-underline-size:6px]", "prose-a:no-underline prose-a:shadow-[inset_0_-2px_0_0_var(--tw-prose-background,#fff),inset_0_calc(-1*(var(--tw-prose-underline-size,4px)+2px))_0_0_var(--tw-prose-underline,var(--color-violet-300))] prose-a:hover:[--tw-prose-underline-size:6px]",
// pre // pre
"prose-pre:rounded-xl prose-pre:bg-slate-900 prose-pre:shadow-lg dark:prose-pre:bg-slate-800/60 dark:prose-pre:ring-1 dark:prose-pre:shadow-none dark:prose-pre:ring-slate-300/10", "prose-pre:rounded-xl prose-pre:bg-slate-900 prose-pre:shadow-lg",
// hr
"dark:prose-hr:border-slate-800",
)} )}
{...props} {...props}
/> />

View File

@ -25,21 +25,19 @@ type QuickLinkProps = {
export function QuickLink(props: QuickLinkProps) { export function QuickLink(props: QuickLinkProps) {
return ( return (
<div class="group relative rounded-xl border border-slate-200 dark:border-slate-800"> <div class="group relative rounded-xl border border-slate-200">
<div class="absolute -inset-px rounded-xl border-2 border-transparent opacity-0 [background:linear-gradient(var(--quick-links-hover-bg,var(--color-violet-50)),var(--quick-links-hover-bg,var(--color-violet-50)))_padding-box,linear-gradient(to_top,var(--color-indigo-400),var(--color-cyan-400),var(--color-violet-500))_border-box] group-hover:opacity-100 dark:[--quick-links-hover-bg:var(--color-slate-800)]" /> <div class="absolute -inset-px rounded-xl border-2 border-transparent opacity-0 [background:linear-gradient(var(--quick-links-hover-bg,var(--color-violet-50)),var(--quick-links-hover-bg,var(--color-violet-50)))_padding-box,linear-gradient(to_top,var(--color-indigo-400),var(--color-cyan-400),var(--color-violet-500))_border-box] group-hover:opacity-100" />
<div class="relative overflow-hidden rounded-xl p-6"> <div class="relative overflow-hidden rounded-xl p-6">
<Icon icon={props.icon} class="h-8 w-8" /> <Icon icon={props.icon} class="h-8 w-8" />
<h2 class="mt-4 font-display text-base text-slate-900 dark:text-white"> <h2 class="mt-4 font-display text-base text-slate-900">
<Link href={props.href}> <Link href={props.href}>
<span class="absolute -inset-px rounded-xl" /> <span class="absolute -inset-px rounded-xl" />
{props.title} {props.title}
</Link> </Link>
</h2> </h2>
<p class="mt-1 text-sm text-slate-700 dark:text-slate-400"> <p class="mt-1 text-sm text-slate-700">{props.description}</p>
{props.description}
</p>
</div> </div>
</div> </div>
); );

View File

@ -1,9 +1,9 @@
import { fileURLToPath } from "node:url";
import { dirname } from "node:path";
import { createHandler } from "@universal-middleware/fastify"; import { createHandler } from "@universal-middleware/fastify";
import { telefuncHandler } from "./server/telefunc-handler"; import { telefuncHandler } from "./server/telefunc-handler";
import { vikeHandler } from "./server/vike-handler"; import { vikeHandler } from "./server/vike-handler";
import { createDevMiddleware } from "vike/server";
import { fileURLToPath } from "node:url";
import { dirname } from "node:path";
import { config } from "./config"; import { config } from "./config";
import Fastify from "fastify"; import Fastify from "fastify";
@ -27,17 +27,13 @@ async function startServer() {
wildcard: false, wildcard: false,
}); });
} else { } else {
// Instantiate Vite's development server and integrate its middleware to our server. const { devMiddleware } = await createDevMiddleware({
// ⚠️ We should instantiate it *only* in development. (It isn't needed in production root,
// and would unnecessarily bloat our server in production.) viteConfig: {
const vite = await import("vite"); server: { hmr: { port: config.HMR_PORT } },
const viteDevMiddleware = ( },
await vite.createServer({ });
root, app.use(devMiddleware);
server: { middlewareMode: true, hmr: { port: config.HMR_PORT } },
})
).middlewares;
app.use(viteDevMiddleware);
} }
app.post<{ Body: string }>("/_telefunc", createHandler(telefuncHandler)()); app.post<{ Body: string }>("/_telefunc", createHandler(telefuncHandler)());

View File

@ -1,39 +1,43 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon"; import type { IconColor } from "@/components/Icon";
import React from "react";
export function LightbulbIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) { import { Gradient } from "@/components/Icon";
return (
<> type GradientProps = {
<defs> id: string;
<Gradient id={`${id}-gradient`} color={color} gradientTransform="matrix(0 21 -21 0 20 11)" /> color?: IconColor;
<Gradient id={`${id}-gradient-dark`} color={color} gradientTransform="matrix(0 24.5001 -19.2498 0 16 5.5)" /> };
</defs>
<LightMode> export function LightbulbIcon(props: GradientProps) {
<circle cx={20} cy={20} r={12} fill={`url(#${id}-gradient)`} /> return (
<path <>
fillRule="evenodd" <defs>
clipRule="evenodd" <Gradient
d="M20 24.995c0-1.855 1.094-3.501 2.427-4.792C24.61 18.087 26 15.07 26 12.231 26 7.133 21.523 3 16 3S6 7.133 6 12.23c0 2.84 1.389 5.857 3.573 7.973C10.906 21.494 12 23.14 12 24.995V27a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-2.005Z" id={`${props.id}-gradient`}
className="fill-[var(--icon-background)]" color={props.color}
fillOpacity={0.5} gradientTransform="matrix(0 21 -21 0 20 11)"
/> />
<path <Gradient
d="M25 12.23c0 2.536-1.254 5.303-3.269 7.255l1.391 1.436c2.354-2.28 3.878-5.547 3.878-8.69h-2ZM16 4c5.047 0 9 3.759 9 8.23h2C27 6.508 21.998 2 16 2v2Zm-9 8.23C7 7.76 10.953 4 16 4V2C10.002 2 5 6.507 5 12.23h2Zm3.269 7.255C8.254 17.533 7 14.766 7 12.23H5c0 3.143 1.523 6.41 3.877 8.69l1.392-1.436ZM13 27v-2.005h-2V27h2Zm1 1a1 1 0 0 1-1-1h-2a3 3 0 0 0 3 3v-2Zm4 0h-4v2h4v-2Zm1-1a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2Zm0-2.005V27h2v-2.005h-2ZM8.877 20.921C10.132 22.136 11 23.538 11 24.995h2c0-2.253-1.32-4.143-2.731-5.51L8.877 20.92Zm12.854-1.436C20.32 20.852 19 22.742 19 24.995h2c0-1.457.869-2.859 2.122-4.074l-1.391-1.436Z" id={`${props.id}-gradient-dark`}
className="fill-[var(--icon-foreground)]" color={props.color}
/> gradientTransform="matrix(0 24.5001 -19.2498 0 16 5.5)"
<path />
d="M20 26a1 1 0 1 0 0-2v2Zm-8-2a1 1 0 1 0 0 2v-2Zm2 0h-2v2h2v-2Zm1 1V13.5h-2V25h2Zm-5-11.5v1h2v-1h-2Zm3.5 4.5h5v-2h-5v2Zm8.5-3.5v-1h-2v1h2ZM20 24h-2v2h2v-2Zm-2 0h-4v2h4v-2Zm-1-10.5V25h2V13.5h-2Zm2.5-2.5a2.5 2.5 0 0 0-2.5 2.5h2a.5.5 0 0 1 .5-.5v-2Zm2.5 2.5a2.5 2.5 0 0 0-2.5-2.5v2a.5.5 0 0 1 .5.5h2ZM18.5 18a3.5 3.5 0 0 0 3.5-3.5h-2a1.5 1.5 0 0 1-1.5 1.5v2ZM10 14.5a3.5 3.5 0 0 0 3.5 3.5v-2a1.5 1.5 0 0 1-1.5-1.5h-2Zm2.5-3.5a2.5 2.5 0 0 0-2.5 2.5h2a.5.5 0 0 1 .5-.5v-2Zm2.5 2.5a2.5 2.5 0 0 0-2.5-2.5v2a.5.5 0 0 1 .5.5h2Z" </defs>
className="fill-[var(--icon-foreground)]" <circle cx={20} cy={20} r={12} fill={`url(#${props.id}-gradient)`} />
/> <path
</LightMode> fill-rule="evenodd"
<DarkMode> clip-rule="evenodd"
<path d="M20 24.995c0-1.855 1.094-3.501 2.427-4.792C24.61 18.087 26 15.07 26 12.231 26 7.133 21.523 3 16 3S6 7.133 6 12.23c0 2.84 1.389 5.857 3.573 7.973C10.906 21.494 12 23.14 12 24.995V27a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-2.005Z"
fillRule="evenodd" class="fill-[var(--icon-background)]"
clipRule="evenodd" fill-opacity={0.5}
d="M16 2C10.002 2 5 6.507 5 12.23c0 3.144 1.523 6.411 3.877 8.691.75.727 1.363 1.52 1.734 2.353.185.415.574.726 1.028.726H12a1 1 0 0 0 1-1v-4.5a.5.5 0 0 0-.5-.5A3.5 3.5 0 0 1 9 14.5V14a3 3 0 1 1 6 0v9a1 1 0 1 0 2 0v-9a3 3 0 1 1 6 0v.5a3.5 3.5 0 0 1-3.5 3.5.5.5 0 0 0-.5.5V23a1 1 0 0 0 1 1h.36c.455 0 .844-.311 1.03-.726.37-.833.982-1.626 1.732-2.353 2.354-2.28 3.878-5.547 3.878-8.69C27 6.507 21.998 2 16 2Zm5 25a1 1 0 0 0-1-1h-8a1 1 0 0 0-1 1 3 3 0 0 0 3 3h4a3 3 0 0 0 3-3Zm-8-13v1.5a.5.5 0 0 1-.5.5 1.5 1.5 0 0 1-1.5-1.5V14a1 1 0 1 1 2 0Zm6.5 2a.5.5 0 0 1-.5-.5V14a1 1 0 1 1 2 0v.5a1.5 1.5 0 0 1-1.5 1.5Z" />
fill={`url(#${id}-gradient-dark)`} <path
/> d="M25 12.23c0 2.536-1.254 5.303-3.269 7.255l1.391 1.436c2.354-2.28 3.878-5.547 3.878-8.69h-2ZM16 4c5.047 0 9 3.759 9 8.23h2C27 6.508 21.998 2 16 2v2Zm-9 8.23C7 7.76 10.953 4 16 4V2C10.002 2 5 6.507 5 12.23h2Zm3.269 7.255C8.254 17.533 7 14.766 7 12.23H5c0 3.143 1.523 6.41 3.877 8.69l1.392-1.436ZM13 27v-2.005h-2V27h2Zm1 1a1 1 0 0 1-1-1h-2a3 3 0 0 0 3 3v-2Zm4 0h-4v2h4v-2Zm1-1a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2Zm0-2.005V27h2v-2.005h-2ZM8.877 20.921C10.132 22.136 11 23.538 11 24.995h2c0-2.253-1.32-4.143-2.731-5.51L8.877 20.92Zm12.854-1.436C20.32 20.852 19 22.742 19 24.995h2c0-1.457.869-2.859 2.122-4.074l-1.391-1.436Z"
</DarkMode> class="fill-[var(--icon-foreground)]"
</> />
); <path
d="M20 26a1 1 0 1 0 0-2v2Zm-8-2a1 1 0 1 0 0 2v-2Zm2 0h-2v2h2v-2Zm1 1V13.5h-2V25h2Zm-5-11.5v1h2v-1h-2Zm3.5 4.5h5v-2h-5v2Zm8.5-3.5v-1h-2v1h2ZM20 24h-2v2h2v-2Zm-2 0h-4v2h4v-2Zm-1-10.5V25h2V13.5h-2Zm2.5-2.5a2.5 2.5 0 0 0-2.5 2.5h2a.5.5 0 0 1 .5-.5v-2Zm2.5 2.5a2.5 2.5 0 0 0-2.5-2.5v2a.5.5 0 0 1 .5.5h2ZM18.5 18a3.5 3.5 0 0 0 3.5-3.5h-2a1.5 1.5 0 0 1-1.5 1.5v2ZM10 14.5a3.5 3.5 0 0 0 3.5 3.5v-2a1.5 1.5 0 0 1-1.5-1.5h-2Zm2.5-3.5a2.5 2.5 0 0 0-2.5 2.5h2a.5.5 0 0 1 .5-.5v-2Zm2.5 2.5a2.5 2.5 0 0 0-2.5-2.5v2a.5.5 0 0 1 .5.5h2Z"
class="fill-[var(--icon-foreground)]"
/>
</>
);
} }

View File

@ -1,48 +1,57 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon"; import type { IconColor } from "@/components/Icon";
import React from "react";
export function PluginsIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) { import { Gradient } from "@/components/Icon";
return (
<> type GradientProps = {
<defs> id: string;
<Gradient id={`${id}-gradient`} color={color} gradientTransform="matrix(0 21 -21 0 20 11)" /> color?: IconColor;
<Gradient id={`${id}-gradient-dark-1`} color={color} gradientTransform="matrix(0 22.75 -22.75 0 16 6.25)" /> };
<Gradient id={`${id}-gradient-dark-2`} color={color} gradientTransform="matrix(0 14 -14 0 16 10)" />
</defs> export function PluginsIcon(props: GradientProps) {
<LightMode> return (
<circle cx={20} cy={20} r={12} fill={`url(#${id}-gradient)`} /> <>
<g <defs>
fillOpacity={0.5} <Gradient
className="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]" id={`${props.id}-gradient`}
strokeWidth={2} color={props.color}
strokeLinecap="round" gradientTransform="matrix(0 21 -21 0 20 11)"
strokeLinejoin="round" />
> <Gradient
<path d="M3 9v14l12 6V15L3 9Z" /> id={`${props.id}-gradient-dark-1`}
<path d="M27 9v14l-12 6V15l12-6Z" /> color={props.color}
</g> gradientTransform="matrix(0 22.75 -22.75 0 16 6.25)"
<path d="M11 4h8v2l6 3-10 6L5 9l6-3V4Z" fillOpacity={0.5} className="fill-[var(--icon-background)]" /> />
<g <Gradient
className="stroke-[color:var(--icon-foreground)]" id={`${props.id}-gradient-dark-2`}
strokeWidth={2} color={props.color}
strokeLinecap="round" gradientTransform="matrix(0 14 -14 0 16 10)"
strokeLinejoin="round" />
> </defs>
<path d="M20 5.5 27 9l-12 6L3 9l7-3.5" /> <circle cx={20} cy={20} r={12} fill={`url(#${props.id}-gradient)`} />
<path d="M20 5c0 1.105-2.239 2-5 2s-5-.895-5-2m10 0c0-1.105-2.239-2-5-2s-5 .895-5 2m10 0v3c0 1.105-2.239 2-5 2s-5-.895-5-2V5" /> <g
</g> fill-opacity={0.5}
</LightMode> class="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]"
<DarkMode strokeWidth={2} strokeLinecap="round" strokeLinejoin="round"> stroke-width={2}
<path stroke-linecap="round"
d="M17.676 3.38a3.887 3.887 0 0 0-3.352 0l-9 4.288C3.907 8.342 3 9.806 3 11.416v9.168c0 1.61.907 3.073 2.324 3.748l9 4.288a3.887 3.887 0 0 0 3.352 0l9-4.288C28.093 23.657 29 22.194 29 20.584v-9.168c0-1.61-.907-3.074-2.324-3.748l-9-4.288Z" stroke-linejoin="round"
stroke={`url(#${id}-gradient-dark-1)`} >
/> <path d="M3 9v14l12 6V15L3 9Z" />
<path <path d="M27 9v14l-12 6V15l12-6Z" />
d="M16.406 8.087a.989.989 0 0 0-.812 0l-7 3.598A1.012 1.012 0 0 0 8 12.61v6.78c0 .4.233.762.594.925l7 3.598a.989.989 0 0 0 .812 0l7-3.598c.361-.163.594-.525.594-.925v-6.78c0-.4-.233-.762-.594-.925l-7-3.598Z" </g>
fill={`url(#${id}-gradient-dark-2)`} <path
stroke={`url(#${id}-gradient-dark-2)`} d="M11 4h8v2l6 3-10 6L5 9l6-3V4Z"
/> fill-opacity={0.5}
</DarkMode> class="fill-[var(--icon-background)]"
</> />
); <g
class="stroke-[color:var(--icon-foreground)]"
stroke-width={2}
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M20 5.5 27 9l-12 6L3 9l7-3.5" />
<path d="M20 5c0 1.105-2.239 2-5 2s-5-.895-5-2m10 0c0-1.105-2.239-2-5-2s-5 .895-5 2m10 0v3c0 1.105-2.239 2-5 2s-5-.895-5-2V5" />
</g>
</>
);
} }

View File

@ -1,36 +1,40 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon"; import type { IconColor } from "@/components/Icon";
import React from "react";
export function PresetsIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) { import { Gradient } from "@/components/Icon";
return (
<> type GradientProps = {
<defs> id: string;
<Gradient id={`${id}-gradient`} color={color} gradientTransform="matrix(0 21 -21 0 20 3)" /> color?: IconColor;
<Gradient id={`${id}-gradient-dark`} color={color} gradientTransform="matrix(0 22.75 -22.75 0 16 6.25)" /> };
</defs>
<LightMode> export function PresetsIcon(props: GradientProps) {
<circle cx={20} cy={12} r={12} fill={`url(#${id}-gradient)`} /> return (
<g <>
className="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]" <defs>
fillOpacity={0.5} <Gradient
strokeWidth={2} id={`${props.id}-gradient`}
strokeLinecap="round" color={props.color}
strokeLinejoin="round" gradientTransform="matrix(0 21 -21 0 20 3)"
> />
<path d="M3 5v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2Z" /> <Gradient
<path d="M18 17v10a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2V17a2 2 0 0 0-2-2h-7a2 2 0 0 0-2 2Z" /> id={`${props.id}-gradient-dark`}
<path d="M18 5v4a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2h-7a2 2 0 0 0-2 2Z" /> color={props.color}
<path d="M3 25v2a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2v-2a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2Z" /> gradientTransform="matrix(0 22.75 -22.75 0 16 6.25)"
</g> />
</LightMode> </defs>
<DarkMode fill={`url(#${id}-gradient-dark)`}> <circle cx={20} cy={12} r={12} fill={`url(#${props.id}-gradient)`} />
<path <g
fillRule="evenodd" class="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]"
clipRule="evenodd" fill-opacity={0.5}
d="M3 17V4a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1Zm16 10v-9a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-6a2 2 0 0 1-2-2Zm0-23v5a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1h-8a1 1 0 0 0-1 1ZM3 28v-3a1 1 0 0 1 1-1h9a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1Z" stroke-width={2}
/> stroke-linecap="round"
<path d="M2 4v13h2V4H2Zm2-2a2 2 0 0 0-2 2h2V2Zm8 0H4v2h8V2Zm2 2a2 2 0 0 0-2-2v2h2Zm0 13V4h-2v13h2Zm-2 2a2 2 0 0 0 2-2h-2v2Zm-8 0h8v-2H4v2Zm-2-2a2 2 0 0 0 2 2v-2H2Zm16 1v9h2v-9h-2Zm3-3a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1v-2Zm6 0h-6v2h6v-2Zm3 3a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2Zm0 9v-9h-2v9h2Zm-3 3a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2Zm-6 0h6v-2h-6v2Zm-3-3a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1h-2Zm2-18V4h-2v5h2Zm0 0h-2a2 2 0 0 0 2 2V9Zm8 0h-8v2h8V9Zm0 0v2a2 2 0 0 0 2-2h-2Zm0-5v5h2V4h-2Zm0 0h2a2 2 0 0 0-2-2v2Zm-8 0h8V2h-8v2Zm0 0V2a2 2 0 0 0-2 2h2ZM2 25v3h2v-3H2Zm2-2a2 2 0 0 0-2 2h2v-2Zm9 0H4v2h9v-2Zm2 2a2 2 0 0 0-2-2v2h2Zm0 3v-3h-2v3h2Zm-2 2a2 2 0 0 0 2-2h-2v2Zm-9 0h9v-2H4v2Zm-2-2a2 2 0 0 0 2 2v-2H2Z" /> stroke-linejoin="round"
</DarkMode> >
</> <path d="M3 5v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2Z" />
); <path d="M18 17v10a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2V17a2 2 0 0 0-2-2h-7a2 2 0 0 0-2 2Z" />
<path d="M18 5v4a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2h-7a2 2 0 0 0-2 2Z" />
<path d="M3 25v2a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2v-2a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2Z" />
</g>
</>
);
} }

View File

@ -1,48 +1,52 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon"; import type { IconColor } from "@/components/Icon";
import React from "react";
export function QuestionIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) { import { Gradient } from "@/components/Icon";
return (
<> type GradientProps = {
<defs> id: string;
<Gradient id={`${id}-gradient`} color={color} gradientTransform="rotate(65.924 1.519 20.92) scale(25.7391)" /> color?: IconColor;
<Gradient id={`${id}-gradient-dark`} color={color} gradientTransform="matrix(0 24.5 -24.5 0 16 5.5)" /> };
</defs>
<LightMode> export function QuestionIcon(props: GradientProps) {
<circle cx={20} cy={20} r={12} fill={`url(#${id}-gradient)`} /> return (
<path <>
d="M3 16c0 7.18 5.82 13 13 13s13-5.82 13-13S23.18 3 16 3 3 8.82 3 16Z" <defs>
fillOpacity={0.5} <Gradient
className="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]" id={`${props.id}-gradient`}
strokeWidth={2} color={props.color}
strokeLinecap="round" gradientTransform="rotate(65.924 1.519 20.92) scale(25.7391)"
strokeLinejoin="round" />
/> <Gradient
<path id={`${props.id}-gradient-dark`}
d="m 16.39 14.617 l 1.179 -3.999 C 17.38 9.304 16.133 9.127 15.469 10.645 C 15.306 11.269 14.71 11.12 14.71 10.537 a 1.66 1.66 5 1 1 3.808 0.217 l -1.5182 5.4314 a 0.602 0.602 5 0 1 -1.1795 -0.1032 Z" color={props.color}
className="fill-[var(--icon-foreground)] stroke-[color:var(--icon-foreground)]" gradientTransform="matrix(0 24.5 -24.5 0 16 5.5)"
strokeWidth={2} />
strokeLinecap="round" </defs>
strokeLinejoin="round" <circle cx={20} cy={20} r={12} fill={`url(#${props.id}-gradient)`} />
/> <path
<path d="M3 16c0 7.18 5.82 13 13 13s13-5.82 13-13S23.18 3 16 3 3 8.82 3 16Z"
d="M16 23a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z" fill-opacity={0.5}
fillOpacity={0.5} class="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]"
stroke="currentColor" stroke-width={2}
className="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]" stroke-linecap="round"
strokeWidth={2} stroke-linejoin="round"
strokeLinecap="round" />
strokeLinejoin="round" <path
/> d="m 16.39 14.617 l 1.179 -3.999 C 17.38 9.304 16.133 9.127 15.469 10.645 C 15.306 11.269 14.71 11.12 14.71 10.537 a 1.66 1.66 5 1 1 3.808 0.217 l -1.5182 5.4314 a 0.602 0.602 5 0 1 -1.1795 -0.1032 Z"
</LightMode> class="fill-[var(--icon-foreground)] stroke-[color:var(--icon-foreground)]"
<DarkMode> stroke-width={2}
<path stroke-linecap="round"
fillRule="evenodd" stroke-linejoin="round"
clipRule="evenodd" />
d="M2 16C2 8.268 8.268 2 16 2s14 6.268 14 14-6.268 14-14 14S2 23.732 2 16Zm11.386-4.85a2.66 2.66 0 1 1 5.228 0l-1.039 5.543a1.602 1.602 0 0 1-3.15 0l-1.04-5.543ZM16 20a2 2 0 1 0 0 4 2 2 0 0 0 0-4Z" <path
fill={`url(#${id}-gradient-dark)`} d="M16 23a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"
/> fill-opacity={0.5}
</DarkMode> stroke="currentColor"
</> class="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]"
); stroke-width={2}
stroke-linecap="round"
stroke-linejoin="round"
/>
</>
);
} }

View File

@ -1,52 +1,56 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon"; import type { IconColor } from "@/components/Icon";
import React from "react";
export function ThemingIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) { import { Gradient } from "@/components/Icon";
return (
<> type GradientProps = {
<defs> id: string;
<Gradient id={`${id}-gradient`} color={color} gradientTransform="matrix(0 21 -21 0 12 11)" /> color?: IconColor;
<Gradient id={`${id}-gradient-dark`} color={color} gradientTransform="matrix(0 24.5 -24.5 0 16 5.5)" /> };
</defs>
<LightMode> export function ThemingIcon(props: GradientProps) {
<circle cx={12} cy={20} r={12} fill={`url(#${id}-gradient)`} /> return (
<path <>
d="M27 12.13 19.87 5 13 11.87v14.26l14-14Z" <defs>
className="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]" <Gradient
fillOpacity={0.5} id={`${props.id}-gradient`}
strokeWidth={2} color={props.color}
strokeLinecap="round" gradientTransform="matrix(0 21 -21 0 12 11)"
strokeLinejoin="round" />
/> <Gradient
<path id={`${props.id}-gradient-dark`}
d="M3 3h10v22a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V3Z" color={props.color}
className="fill-[var(--icon-background)]" gradientTransform="matrix(0 24.5 -24.5 0 16 5.5)"
fillOpacity={0.5} />
/> </defs>
<path <circle cx={12} cy={20} r={12} fill={`url(#${props.id}-gradient)`} />
d="M3 9v16a4 4 0 0 0 4 4h2a4 4 0 0 0 4-4V9M3 9V3h10v6M3 9h10M3 15h10M3 21h10" <path
className="stroke-[color:var(--icon-foreground)]" d="M27 12.13 19.87 5 13 11.87v14.26l14-14Z"
strokeWidth={2} class="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]"
strokeLinecap="round" fill-opacity={0.5}
strokeLinejoin="round" stroke-width={2}
/> stroke-linecap="round"
<path stroke-linejoin="round"
d="M29 29V19h-8.5L13 26c0 1.5-2.5 3-5 3h21Z" />
fillOpacity={0.5} <path
className="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]" d="M3 3h10v22a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V3Z"
strokeWidth={2} class="fill-[var(--icon-background)]"
strokeLinecap="round" fill-opacity={0.5}
strokeLinejoin="round" />
/> <path
</LightMode> d="M3 9v16a4 4 0 0 0 4 4h2a4 4 0 0 0 4-4V9M3 9V3h10v6M3 9h10M3 15h10M3 21h10"
<DarkMode> class="stroke-[color:var(--icon-foreground)]"
<path stroke-width={2}
fillRule="evenodd" stroke-linecap="round"
clipRule="evenodd" stroke-linejoin="round"
d="M3 2a1 1 0 0 0-1 1v21a6 6 0 0 0 12 0V3a1 1 0 0 0-1-1H3Zm16.752 3.293a1 1 0 0 0-1.593.244l-1.045 2A1 1 0 0 0 17 8v13a1 1 0 0 0 1.71.705l7.999-8.045a1 1 0 0 0-.002-1.412l-6.955-6.955ZM26 18a1 1 0 0 0-.707.293l-10 10A1 1 0 0 0 16 30h13a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1h-3ZM5 18a1 1 0 1 0 0 2h6a1 1 0 1 0 0-2H5Zm-1-5a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2H5a1 1 0 0 1-1-1Zm1-7a1 1 0 0 0 0 2h6a1 1 0 1 0 0-2H5Z" />
fill={`url(#${id}-gradient-dark)`} <path
/> d="M29 29V19h-8.5L13 26c0 1.5-2.5 3-5 3h21Z"
</DarkMode> fill-opacity={0.5}
</> class="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]"
); stroke-width={2}
stroke-linecap="round"
stroke-linejoin="round"
/>
</>
);
} }

View File

@ -1,48 +1,52 @@
import { DarkMode, Gradient, LightMode } from "@syntax/Icon"; import type { IconColor } from "@/components/Icon";
import React from "react";
export function WarningIcon({ id, color }: { id: string; color?: React.ComponentProps<typeof Gradient>["color"] }) { import { Gradient } from "@/components/Icon";
return (
<> type GradientProps = {
<defs> id: string;
<Gradient id={`${id}-gradient`} color={color} gradientTransform="rotate(65.924 1.519 20.92) scale(25.7391)" /> color?: IconColor;
<Gradient id={`${id}-gradient-dark`} color={color} gradientTransform="matrix(0 24.5 -24.5 0 16 5.5)" /> };
</defs>
<LightMode> export function WarningIcon(props: GradientProps) {
<circle cx={20} cy={20} r={12} fill={`url(#${id}-gradient)`} /> return (
<path <>
d="M3 16c0 7.18 5.82 13 13 13s13-5.82 13-13S23.18 3 16 3 3 8.82 3 16Z" <defs>
fillOpacity={0.5} <Gradient
className="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]" id={`${props.id}-gradient`}
strokeWidth={2} color={props.color}
strokeLinecap="round" gradientTransform="rotate(65.924 1.519 20.92) scale(25.7391)"
strokeLinejoin="round" />
/> <Gradient
<path id={`${props.id}-gradient-dark`}
d="m15.408 16.509-1.04-5.543a1.66 1.66 0 1 1 3.263 0l-1.039 5.543a.602.602 0 0 1-1.184 0Z" color={props.color}
className="fill-[var(--icon-foreground)] stroke-[color:var(--icon-foreground)]" gradientTransform="matrix(0 24.5 -24.5 0 16 5.5)"
strokeWidth={2} />
strokeLinecap="round" </defs>
strokeLinejoin="round" <circle cx={20} cy={20} r={12} fill={`url(#${props.id}-gradient)`} />
/> <path
<path d="M3 16c0 7.18 5.82 13 13 13s13-5.82 13-13S23.18 3 16 3 3 8.82 3 16Z"
d="M16 23a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z" fill-opacity={0.5}
fillOpacity={0.5} class="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]"
stroke="currentColor" stroke-width={2}
className="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]" stroke-linecap="round"
strokeWidth={2} stroke-linejoin="round"
strokeLinecap="round" />
strokeLinejoin="round" <path
/> d="m15.408 16.509-1.04-5.543a1.66 1.66 0 1 1 3.263 0l-1.039 5.543a.602.602 0 0 1-1.184 0Z"
</LightMode> class="fill-[var(--icon-foreground)] stroke-[color:var(--icon-foreground)]"
<DarkMode> stroke-width={2}
<path stroke-linecap="round"
fillRule="evenodd" stroke-linejoin="round"
clipRule="evenodd" />
d="M2 16C2 8.268 8.268 2 16 2s14 6.268 14 14-6.268 14-14 14S2 23.732 2 16Zm11.386-4.85a2.66 2.66 0 1 1 5.228 0l-1.039 5.543a1.602 1.602 0 0 1-3.15 0l-1.04-5.543ZM16 20a2 2 0 1 0 0 4 2 2 0 0 0 0-4Z" <path
fill={`url(#${id}-gradient-dark)`} d="M16 23a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"
/> fill-opacity={0.5}
</DarkMode> stroke="currentColor"
</> class="fill-[var(--icon-background)] stroke-[color:var(--icon-foreground)]"
); stroke-width={2}
stroke-linecap="round"
stroke-linejoin="round"
/>
</>
);
} }

BIN
app/images/blur-cyan.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
app/images/blur-indigo.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

View File

@ -1,38 +1,74 @@
import { type Node } from "@markdoc/markdoc"; import type { JSXElement } from "solid-js";
import { TableOfContents } from "@syntax/TableOfContents"; import { TableOfContents } from "@/partials/TableOfContents";
import { PrevNextLinks } from "@/components/PrevNextLinks"; import { PrevNextLinks } from "@/components/PrevNextLinks";
import { collectSections } from "@/lib/sections"; import { usePageContext } from "vike-solid/usePageContext";
import { DocsHeader } from "@syntax/DocsHeader"; import { collectSections } from "@/libs/sections";
import { navigation } from "@/libs/navigation";
import { Prose } from "@/components/Prose"; import { Prose } from "@/components/Prose";
export function DocsLayout({ type DocsLayoutProps = {
children, children: JSXElement;
frontmatter: { title }, title?: string;
estimatedReadingTime, // frontmatter: { title?: string };
nodes,
}: {
children: React.ReactNode;
frontmatter: { title?: string };
estimatedReadingTime?: string; estimatedReadingTime?: string;
nodes: Array<Node>; // nodes: Array<Node>;
}) { };
const tableOfContents = collectSections(nodes);
export function DocsLayout(props: DocsLayoutProps) {
// const tableOfContents = collectSections(nodes);
return ( return (
<> <>
<div class="max-w-2xl min-w-0 flex-auto px-4 py-16 lg:max-w-none lg:pr-0 lg:pl-8 xl:px-16 grow"> <div class="max-w-2xl min-w-0 flex-auto px-4 py-16 lg:max-w-none lg:pr-0 lg:pl-8 xl:px-16 grow">
<article> <article>
<DocsHeader <DocsHeader
title={title} title={props.title}
estimatedReadingTime={estimatedReadingTime} estimatedReadingTime={props.estimatedReadingTime}
/> />
<Prose>{children}</Prose> <Prose>{props.children}</Prose>
</article> </article>
<PrevNextLinks /> <PrevNextLinks />
</div> </div>
<TableOfContents tableOfContents={tableOfContents} /> {/* <TableOfContents tableOfContents={tableOfContents} /> */}
</> </>
); );
} }
type DocsHeaderProps = {
title?: string;
estimatedReadingTime?: string;
};
export function DocsHeader(props: DocsHeaderProps) {
const { urlPathname } = usePageContext();
const section = navigation.find((section) =>
section.links.find((link) => link.href === urlPathname),
);
if (!props.title && !section) {
return null;
}
return (
<header class="mb-9 space-y-1">
{section && (
<p class="font-display text-sm font-medium text-violet-500">
{section.title}
</p>
)}
{props.title && (
<h1 class="font-display text-3xl tracking-tight text-slate-900">
{props.title}
</h1>
)}
{/* {props.estimatedReadingTime && (
<p class="text-sm text-slate-500 inline-flex items-center gap-1">
<ClockIcon class="w-4" /> {props.estimatedReadingTime}
</p>
)} */}
</header>
);
}

View File

@ -1,52 +1,161 @@
import type { JSX } from "solid-js"; import type { JSX, JSXElement } from "solid-js";
import "./tailwind.css";
// import { CookiesContainer } from "@/components/common/Cookies";
import { MobileNavigation } from "@/partials/MobileNavigation";
import { usePageContext } from "vike-solid/usePageContext";
// import { ThemeProvider } from "@/providers/ThemeProvider";
// import { clientOnly } from "vike-react/clientOnly";
import { createEffect, createSignal } from "solid-js";
import { HeroSection } from "@/partials/HeroSection";
import { Navigation } from "@/partials/Navigation";
import { Link } from "@/components/Link"; import { Link } from "@/components/Link";
import logoUrl from "@/assets/logo.svg"; import { Logo } from "@/components/Logo";
import { Toaster } from "solid-toast";
import clsx from "clsx";
export default function LayoutDefault(props: { children?: JSX.Element }) { // import "./style.css";
import "./tailwind.css";
import { DocsLayout } from "./DocsLayout";
// import "./prism.css";
// import "unfonts.css";
// const Search = clientOnly(() => import("@/components/Search").then((module) => module.Search));
function Search() {
return null;
}
function GitHubIcon(props: JSX.IntrinsicElements["svg"]) {
return ( return (
<div class={"flex max-w-5xl m-auto"}> <svg aria-hidden="true" viewBox="0 0 16 16" {...props}>
<Sidebar> <path d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" />
<Logo /> </svg>
<Link href="/">Welcome</Link>
<Link href="/todo">Todo</Link>
<Link href="/star-wars">Data Fetching</Link>
{""}
</Sidebar>
<Content>{props.children}</Content>
</div>
); );
} }
function Sidebar(props: { children: JSX.Element }) { function Header() {
const [isScrolled, setIsScrolled] = createSignal(false);
createEffect(() => {
function onScroll() {
setIsScrolled(window.scrollY > 0);
}
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
return () => {
window.removeEventListener("scroll", onScroll);
};
}, []);
return ( return (
<div <header
id="sidebar" class={clsx(
class={"p-5 flex flex-col shrink-0 border-r-2 border-r-gray-200"} "sticky top-0 z-50 flex flex-none flex-wrap items-center justify-between bg-white px-4 py-5 shadow-md shadow-slate-900/5 transition duration-500 sm:px-6 lg:px-8",
)}
> >
{props.children} <div class="mr-6 flex lg:hidden">
</div> <MobileNavigation />
);
}
function Content(props: { children: JSX.Element }) {
return (
<div id="page-container">
<div id="page-content" class={"p-5 pb-12 min-h-screen"}>
{props.children}
</div> </div>
</div>
<div class="relative flex grow basis-0 items-center">
<Link href="/" aria-label="Home page" class="flex items-center gap-2">
<Logo class="h-9 w-auto" />
<span class="hidden lg:inline text-2xl font-bold -tracking-tight text-slate-900">
Memento Dev
</span>
</Link>
</div>
<div class="-my-5 mr-6 sm:mr-8 md:mr-0">
{/* <Search fallback={<div class="h-6 w-6 animate-pulse rounded-full bg-slate-200" />} /> */}
<div class="h-6 w-6 animate-pulse rounded-full bg-slate-200" />
</div>
<div class="relative flex basis-0 justify-end gap-6 sm:gap-8 md:grow">
<Link
href="https://github.com/GauthierWebDev/memento-dev"
class="group"
aria-label="GitHub"
>
<GitHubIcon class="h-6 w-6 fill-slate-400 group-hover:fill-slate-500" />
</Link>
</div>
</header>
); );
} }
function Logo() { function Footer() {
return ( return (
<div class={"p-5 mb-2"}> <footer class="bg-slate-50 text-slate-700">
<a href="/"> <div class="mx-auto w-full flex flex-col max-w-8xl sm:px-2 lg:px-8 xl:px-12 py-8">
<img src={logoUrl} height={64} width={64} alt="logo" /> <section>
</a> <header class="flex items-center gap-2 mb-2">
</div> <Logo class="h-8 w-auto" />
<h2 class="font-display text-2xl">Memento Dev</h2>
</header>
<p>
Plateforme de ressources et documentations synthétiques et concises,
conçue pour les développeurs ou passionnés de l&lsquo;informatique
en quête de savoir.
</p>
</section>
<hr class="my-6 border-slate-200" />
<section>
<header class="flex items-center gap-2">
<h2 class="font-display">
&copy; 2022 - {new Date().getFullYear()} Memento Dev. Tous droits
réservés
</h2>
</header>
<p class="text-sm text-slate-500">
Memento Dev est une plateforme open-source, développée par{" "}
<Link href="https://gauthierdaniels.fr" class="font-bold">
Gauthier Daniels
</Link>
, soutenue et maintenue par une communauté de contributeurs
passionnés.
</p>
</section>
</div>
</footer>
);
}
type DefaultLayoutProps = {
children: JSXElement;
};
export default function DefaultLayout(props: DefaultLayoutProps) {
const { urlPathname } = usePageContext();
const isHomePage = urlPathname === "/";
return (
<>
<div class="flex w-full flex-col font-sans">
<Header />
{isHomePage && <HeroSection />}
<div class="relative mx-auto w-full flex max-w-8xl flex-auto justify-center sm:px-2 lg:px-8 xl:px-12">
<div class="hidden lg:relative lg:block lg:flex-none">
<div class="absolute inset-y-0 right-0 w-[50vw] bg-slate-50" />
<div class="absolute top-16 right-0 bottom-0 hidden h-12 w-px bg-linear-to-t from-slate-800" />
<div class="absolute top-28 right-0 bottom-0 hidden w-px bg-slate-800" />
<div class="sticky top-[4.75rem] -ml-0.5 h-[calc(100vh-4.75rem)] w-64 overflow-x-hidden overflow-y-auto py-16 pr-8 pl-0.5 xl:w-72 xl:pr-16">
<Navigation />
</div>
</div>
<DocsLayout>{props.children}</DocsLayout>
</div>
<Footer />
</div>
<Toaster />
</>
); );
} }

55
app/layouts/prism.css Normal file
View File

@ -0,0 +1,55 @@
pre[class*="language-"] {
color: var(--color-slate-50);
}
.token.tag,
.token.class-name,
.token.selector,
.token.selector .class,
.token.selector.class,
.token.function {
color: var(--color-pink-400);
}
.token.attr-name,
.token.keyword,
.token.rule,
.token.pseudo-class,
.token.important {
color: var(--color-slate-300);
}
.token.module {
color: var(--color-pink-400);
}
.token.attr-value,
.token.class,
.token.string,
.token.property {
color: var(--color-sky-300);
}
.token.punctuation,
.token.attr-equals {
color: var(--color-slate-500);
}
.token.unit,
.language-css .token.function {
color: var(--color-teal-200);
}
.token.comment,
.token.operator,
.token.combinator {
color: var(--color-slate-400);
}
.prism-code {
margin: 0;
}
.prism-code + .prism-code {
margin-bottom: 1rem;
}

View File

@ -27,3 +27,9 @@ body {
body.page-is-transitioning #page-content { body.page-is-transitioning #page-content {
opacity: 0; opacity: 0;
} }
#root {
height: 100%;
width: 100%;
display: flex;
}

View File

@ -1,2 +1,47 @@
@import "./prism.css";
@import "./style.css"; @import "./style.css";
@import "tailwindcss"; @import "tailwindcss";
@plugin '@tailwindcss/typography';
@theme {
--text-*: initial;
--text-xs: 0.75rem;
--text-xs--line-height: 1rem;
--text-sm: 0.875rem;
--text-sm--line-height: 1.5rem;
--text-base: 1rem;
--text-base--line-height: 2rem;
--text-lg: 1.125rem;
--text-lg--line-height: 1.75rem;
--text-xl: 1.25rem;
--text-xl--line-height: 2rem;
--text-2xl: 1.5rem;
--text-2xl--line-height: 2.5rem;
--text-3xl: 2rem;
--text-3xl--line-height: 2.5rem;
--text-4xl: 2.5rem;
--text-4xl--line-height: 3rem;
--text-5xl: 3rem;
--text-5xl--line-height: 3.5rem;
--text-6xl: 3.75rem;
--text-6xl--line-height: 1;
--text-7xl: 4.5rem;
--text-7xl--line-height: 1;
--text-8xl: 6rem;
--text-8xl--line-height: 1;
--text-9xl: 8rem;
--text-9xl--line-height: 1;
--font-sans: "Inter";
--font-display: "Lexend";
--font-display--font-feature-settings: "ss01";
--container-8xl: 88rem;
}
@layer base {
[inert] ::-webkit-scrollbar {
display: none;
}
}

View File

@ -12,25 +12,29 @@
"@fastify/static": "^8.1.1", "@fastify/static": "^8.1.1",
"@mdx-js/rollup": "^3.1.0", "@mdx-js/rollup": "^3.1.0",
"@sindresorhus/slugify": "^2.2.1", "@sindresorhus/slugify": "^2.2.1",
"@tailwindcss/typography": "^0.5.16",
"@universal-middleware/core": "^0.4.7", "@universal-middleware/core": "^0.4.7",
"@universal-middleware/fastify": "^0.5.16", "@universal-middleware/fastify": "^0.5.16",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"fastify": "^5.3.0", "fastify": "^5.3.0",
"prismjs": "^1.30.0",
"solid-heroicons": "^3.2.4", "solid-heroicons": "^3.2.4",
"solid-highlight": "^0.1.26",
"solid-js": "^1.9.5", "solid-js": "^1.9.5",
"solid-jsx": "^1.1.4", "solid-jsx": "^1.1.4",
"solid-mdx": "^0.0.7", "solid-mdx": "^0.0.7",
"solid-toast": "^0.5.0",
"telefunc": "^0.2.3", "telefunc": "^0.2.3",
"terracotta": "^1.0.6", "terracotta": "^1.0.6",
"vike": "^0.4.228", "vike": "^0.4.228",
"vike-solid": "^0.7.9" "vike-solid": "^0.7.9",
"vite-plugin-prismjs": "^0.0.11"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "1.9.4", "@biomejs/biome": "1.9.4",
"@eslint/js": "^9.24.0", "@eslint/js": "^9.24.0",
"@tailwindcss/vite": "^4.1.3", "@tailwindcss/vite": "^4.1.3",
"@types/node": "^18.19.86", "@types/node": "^18.19.86",
"@types/prismjs": "^1.26.5",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "^9.24.0", "eslint": "^9.24.0",
"eslint-config-prettier": "^10.1.2", "eslint-config-prettier": "^10.1.2",

View File

@ -3,19 +3,30 @@
// https://vike.dev/Head // https://vike.dev/Head
export default function HeadDefault() { export default function HeadDefault() {
return ( return (
<> <>
<script <script
async async
src={`https://www.googletagmanager.com/gtag/js?id=${import.meta.env.PUBLIC_ENV__GOOGLE_ANALYTICS}`} src={`https://www.googletagmanager.com/gtag/js?id=${import.meta.env.PUBLIC_ENV__GOOGLE_ANALYTICS}`}
/> />
<script <script
innerHTML={`window.dataLayer = window.dataLayer || []; innerHTML={`window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);} function gtag(){dataLayer.push(arguments);}
gtag('js', new Date()); gtag('js', new Date());
gtag('config', '${import.meta.env.PUBLIC_ENV__GOOGLE_ANALYTICS}');`} gtag('config', '${import.meta.env.PUBLIC_ENV__GOOGLE_ANALYTICS}');`}
/> />
</>
); <link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossorigin="anonymous"
/>
<link
href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Lexend:wght@100..900&display=swap"
rel="stylesheet"
/>
</>
);
} }

View File

@ -1,18 +1,25 @@
import type { Config } from "vike/types"; import type { Config } from "vike/types";
import Layout from "@/layouts/LayoutDefault";
import vikeSolid from "vike-solid/config"; import vikeSolid from "vike-solid/config";
import Layout from "../layouts/LayoutDefault.js";
// Default config (can be overridden by pages) // Default config (can be overridden by pages)
// https://vike.dev/config // https://vike.dev/config
export default { export default {
// https://vike.dev/Layout // https://vike.dev/Layout
// @ts-ignore
Layout, Layout,
// https://vike.dev/head-tags // https://vike.dev/head-tags
title: "My Vike App", title: "My Vike App",
description: "Demo showcasing Vike", description: "Demo showcasing Vike",
htmlAttributes: {
class: "h-full antialiased",
},
bodyAttributes: {
class: "flex min-h-full bg-white dark:bg-slate-900",
},
prerender: true, prerender: true,

View File

@ -1,10 +1,10 @@
export default function Page() { export default function Page() {
return ( return (
<> <>
<h1 class={"font-bold text-3xl pb-4"}>My Vike app</h1> <h1>My Vike app</h1>
This page is: This page is:
<ul> <ul>
<li>Rendered to HTML.</li> <li>Rendered to HTMLs.</li>
</ul> </ul>
</> </>
); );

View File

@ -2,9 +2,9 @@ import type { JSX } from "solid-js";
import blurIndigoImage from "@/images/blur-indigo.webp"; import blurIndigoImage from "@/images/blur-indigo.webp";
import blurCyanImage from "@/images/blur-cyan.webp"; import blurCyanImage from "@/images/blur-cyan.webp";
import { Highlight } from "@/components/Highlight";
import { HeroBackground } from "./HeroBackground"; import { HeroBackground } from "./HeroBackground";
import { Button } from "@/components/Button"; import { Button } from "@/components/Button";
import { Highlight } from "solid-highlight";
import { Image } from "@/components/Image"; import { Image } from "@/components/Image";
import { For } from "solid-js"; import { For } from "solid-js";
import clsx from "clsx"; import clsx from "clsx";
@ -34,7 +34,7 @@ function TrafficLightsIcon(props: JSX.IntrinsicElements["svg"]) {
); );
} }
export function Hero() { export function HeroSection() {
return ( return (
<div class="overflow-hidden bg-slate-900 dark:mt-[-4.75rem] dark:-mb-32 dark:pt-[4.75rem] dark:pb-32"> <div class="overflow-hidden bg-slate-900 dark:mt-[-4.75rem] dark:-mb-32 dark:pt-[4.75rem] dark:pb-32">
<div class="py-16 sm:px-2 lg:relative lg:px-0 lg:py-20"> <div class="py-16 sm:px-2 lg:relative lg:px-0 lg:py-20">
@ -132,23 +132,7 @@ export function Hero() {
</For> </For>
</div> </div>
<Highlight language={codeLanguage}>{code}</Highlight> <Highlight language={codeLanguage} code={code} />
{/* <Highlight code={code} language={codeLanguage} theme={{ plain: {}, styles: [] }}>
{({ class, style, tokens, getLineProps, getTokenProps }) => (
<pre class={clsx(class, "flex overflow-x-auto pb-6")} style={style}>
<code class="px-4">
{tokens.map((line, lineIndex) => (
<div key={lineIndex} {...getLineProps({ line })}>
{line.map((token, tokenIndex) => (
<span key={tokenIndex} {...getTokenProps({ token })} />
))}
</div>
))}
</code>
</pre>
)}
</Highlight> */}
</div> </div>
</div> </div>
</div> </div>

View File

@ -70,7 +70,7 @@ export function MobileNavigation() {
class="fixed inset-0 z-50 flex items-start overflow-y-auto bg-slate-900/50 pr-10 backdrop-blur-sm lg:hidden" class="fixed inset-0 z-50 flex items-start overflow-y-auto bg-slate-900/50 pr-10 backdrop-blur-sm lg:hidden"
aria-label="Navigation" aria-label="Navigation"
> >
<DialogPanel class="min-h-full w-full max-w-xs bg-white px-4 pt-5 pb-12 sm:px-6 dark:bg-slate-900"> <DialogPanel class="min-h-full w-full max-w-xs bg-white px-4 pt-5 pb-12 sm:px-6">
<div class="flex items-center"> <div class="flex items-center">
<button <button
type="button" type="button"

View File

@ -27,9 +27,7 @@ function NavigationItem(props: NavigationItemProps) {
<h2 <h2
class={clsx( class={clsx(
"font-display font-medium cursor-pointer", "font-display font-medium cursor-pointer",
isOpened() isOpened() ? "text-violet-600" : "text-slate-900",
? "text-violet-600 dark:text-violet-200"
: "text-slate-900 dark:text-white ",
)} )}
> >
<button <button
@ -54,14 +52,11 @@ function NavigationItem(props: NavigationItemProps) {
{props.section.title} {props.section.title}
<span class="text-slate-400 dark:text-slate-500"> <span class="text-slate-400"> ({props.section.links.length})</span>
{" "}
({props.section.links.length})
</span>
</button> </button>
</h2> </h2>
{isOpened() && ( {isOpened() && (
<ul class="!mt-0 ml-2 space-y-1 border-l-2 border-slate-100 lg:mt-4 lg:space-y-2 lg:border-slate-200 dark:border-slate-800 mb-4"> <ul class="!mt-0 ml-2 space-y-1 border-l-2 border-slate-100 lg:mt-4 lg:space-y-2 lg:border-slate-200">
<For each={props.section.links}> <For each={props.section.links}>
{(link) => ( {(link) => (
<li class="relative"> <li class="relative">
@ -139,20 +134,17 @@ function NavigationSubItem(props: NavigationSubItemProps) {
props.link.href !== urlPathname && "before:hidden", props.link.href !== urlPathname && "before:hidden",
isOpened() isOpened()
? "text-violet-500 before:bg-violet-500" ? "text-violet-500 before:bg-violet-500"
: "text-slate-500 before:bg-slate-300 hover:text-slate-600 hover:before:block dark:text-slate-400 dark:before:bg-slate-700 dark:hover:text-slate-300", : "text-slate-500 before:bg-slate-300 hover:text-slate-600 hover:before:block",
)} )}
> >
{props.link.title} {props.link.title}
{props.link.subitems.length > 0 && ( {props.link.subitems.length > 0 && (
<span class="text-slate-400 dark:text-slate-500"> <span class="text-slate-400"> ({props.link.subitems.length})</span>
{" "}
({props.link.subitems.length})
</span>
)} )}
</Link> </Link>
</span> </span>
{props.link.subitems.length > 0 && isOpened() && ( {props.link.subitems.length > 0 && isOpened() && (
<ul class="ml-4 border-l-2 border-slate-100 space-y-1 lg:space-y-2 lg:border-slate-200 dark:border-slate-800 mb-4"> <ul class="ml-4 border-l-2 border-slate-100 space-y-1 lg:space-y-2 lg:border-slate-200 mb-4">
<For each={props.link.subitems}> <For each={props.link.subitems}>
{(subitem) => ( {(subitem) => (
<li class="relative"> <li class="relative">
@ -163,7 +155,7 @@ function NavigationSubItem(props: NavigationSubItemProps) {
"block w-full pl-3.5 before:pointer-events-none before:absolute before:top-1/2 before:-left-1 before:h-1.5 before:w-1.5 before:-translate-y-1/2 before:rounded-full", "block w-full pl-3.5 before:pointer-events-none before:absolute before:top-1/2 before:-left-1 before:h-1.5 before:w-1.5 before:-translate-y-1/2 before:rounded-full",
subitem.href === urlPathname subitem.href === urlPathname
? "font-semibold text-violet-500 before:bg-violet-500" ? "font-semibold text-violet-500 before:bg-violet-500"
: "text-slate-500 before:hidden before:bg-slate-300 hover:text-slate-600 hover:before:block dark:text-slate-400 dark:before:bg-slate-700 dark:hover:text-slate-300", : "text-slate-500 before:hidden before:bg-slate-300 hover:text-slate-600 hover:before:block",
)} )}
> >
{subitem.title} {subitem.title}
@ -208,7 +200,7 @@ export function Navigation(props: {
<nav class={clsx("text-base lg:text-sm", props.class)}> <nav class={clsx("text-base lg:text-sm", props.class)}>
<ul class="space-y-4"> <ul class="space-y-4">
<li> <li>
<h2 class="font-display font-bold text-base text-slate-900 dark:text-white"> <h2 class="font-display font-bold text-base text-slate-900">
{firstSections[0]?.type} {firstSections[0]?.type}
</h2> </h2>
<For each={firstSections}> <For each={firstSections}>
@ -224,7 +216,7 @@ export function Navigation(props: {
<For each={Object.entries(filteredSections)}> <For each={Object.entries(filteredSections)}>
{([type, sections]) => ( {([type, sections]) => (
<li> <li>
<h2 class="font-display font-bold text-base text-slate-900 dark:text-white"> <h2 class="font-display font-bold text-base text-slate-900">
{type} {type}
</h2> </h2>
@ -241,7 +233,7 @@ export function Navigation(props: {
</For> </For>
<li> <li>
<h2 class="font-display font-bold text-base text-slate-900 dark:text-white"> <h2 class="font-display font-bold text-base text-slate-900">
{lastSections[0]?.type} {lastSections[0]?.type}
</h2> </h2>
<For each={lastSections}> <For each={lastSections}>

View File

@ -65,7 +65,7 @@ export function TableOfContents(props: TableOfContentsProps) {
<> <>
<h2 <h2
id="on-this-page-title" id="on-this-page-title"
class="font-display text-sm font-medium text-slate-900 dark:text-white" class="font-display text-sm font-medium text-slate-900"
> >
Table des matières Table des matières
</h2> </h2>

View File

@ -1,3 +1,4 @@
import prismjsVitePlugin from "vite-plugin-prismjs";
import tailwindcss from "@tailwindcss/vite"; import tailwindcss from "@tailwindcss/vite";
import { telefunc } from "telefunc/vite"; import { telefunc } from "telefunc/vite";
import vikeSolid from "vike-solid/vite"; import vikeSolid from "vike-solid/vite";
@ -10,6 +11,18 @@ const __dirname = path.resolve();
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
prismjsVitePlugin({
languages: [
"javascript",
"typescript",
"tsx",
"jsx",
"css",
"html",
"bash",
"nginx",
],
}),
vike(), vike(),
vikeSolid(), vikeSolid(),
mdx({ jsxImportSource: "solid-jsx", providerImportSource: "solid-mdx" }), mdx({ jsxImportSource: "solid-jsx", providerImportSource: "solid-mdx" }),

View File

@ -1,15 +1,15 @@
{ {
"$schema": "./app/node_modules/@biomejs/biome/configuration_schema.json", "$schema": "./app/node_modules/@biomejs/biome/configuration_schema.json",
"organizeImports": { "organizeImports": {
"enabled": true "enabled": true
}, },
"linter": { "linter": {
"enabled": true, "enabled": true,
"rules": { "rules": {
"recommended": true "recommended": true
} }
}, },
"files": { "files": {
"ignore": ["dist/**", "*.js", "*.cjs", "*.mjs", "*.spec.ts"] "ignore": ["dist/**", "*.js", "*.cjs", "*.mjs", "*.spec.ts", "*.css"]
} }
} }