diff --git a/astro.config.mjs b/astro.config.mjs
index d4b3bb7..bb64f98 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -1,13 +1,12 @@
// @ts-check
import mdx from '@astrojs/mdx';
-import preact from '@astrojs/preact';
+import react from '@astrojs/react';
+import tailwindcss from '@tailwindcss/vite';
import expressiveCode from 'astro-expressive-code';
import { defineConfig } from 'astro/config';
-import remarkCodeFile from './src/plugins/remarkCodeFile';
import remarkToc from 'remark-toc';
-
-import tailwindcss from '@tailwindcss/vite';
+import remarkCodeFile from './src/plugins/remarkCodeFile';
// https://astro.build/config
export default defineConfig({
@@ -19,15 +18,13 @@
expressiveCode({
themes: ["github-dark", "github-light"],
}),
- preact(),
mdx({
remarkPlugins: [remarkToc, remarkCodeFile],
}),
+ react()
],
markdown: {
remarkPlugins: [remarkCodeFile],
},
-
-
});
diff --git a/package.json b/package.json
index 594fcff..aadf799 100644
--- a/package.json
+++ b/package.json
@@ -10,13 +10,16 @@
},
"dependencies": {
"@astrojs/mdx": "^4.3.13",
- "@astrojs/preact": "^4.1.3",
+ "@astrojs/react": "^4.4.2",
"@expressive-code/plugin-collapsible-sections": "^0.41.6",
"@expressive-code/plugin-line-numbers": "^0.41.6",
"@tailwindcss/vite": "^4.1.18",
+ "@types/react": "^19.2.10",
+ "@types/react-dom": "^19.2.3",
"astro": "^5.16.5",
"astro-expressive-code": "^0.41.5",
- "preact": "^10.28.0",
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4",
"remark-toc": "^9.0.0",
"tailwindcss": "^4.1.18",
"unist-util-visit": "^5.0.0"
@@ -25,4 +28,4 @@
"@biomejs/biome": "2.3.8",
"daisyui": "^5.5.14"
}
-}
\ No newline at end of file
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4667186..6b01188 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,9 +11,9 @@
'@astrojs/mdx':
specifier: ^4.3.13
version: 4.3.13(astro@5.16.5(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(typescript@5.9.3))
- '@astrojs/preact':
- specifier: ^4.1.3
- version: 4.1.3(@babel/core@7.28.5)(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)(preact@10.28.0)
+ '@astrojs/react':
+ specifier: ^4.4.2
+ version: 4.4.2(@types/node@25.0.2)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
'@expressive-code/plugin-collapsible-sections':
specifier: ^0.41.6
version: 0.41.6
@@ -23,15 +23,24 @@
'@tailwindcss/vite':
specifier: ^4.1.18
version: 4.1.18(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))
+ '@types/react':
+ specifier: ^19.2.10
+ version: 19.2.10
+ '@types/react-dom':
+ specifier: ^19.2.3
+ version: 19.2.3(@types/react@19.2.10)
astro:
specifier: ^5.16.5
version: 5.16.5(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(typescript@5.9.3)
astro-expressive-code:
specifier: ^0.41.5
version: 0.41.5(astro@5.16.5(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(typescript@5.9.3))
- preact:
- specifier: ^10.28.0
- version: 10.28.0
+ react:
+ specifier: ^19.2.4
+ version: 19.2.4
+ react-dom:
+ specifier: ^19.2.4
+ version: 19.2.4(react@19.2.4)
remark-toc:
specifier: ^9.0.0
version: 9.0.0
@@ -66,16 +75,19 @@
peerDependencies:
astro: ^5.0.0
- '@astrojs/preact@4.1.3':
- resolution: {integrity: sha512-Ph416wbgyumkmYr7erZ83l/d+LXdZethlHRRCbgoKEn8wo3Rkq13shKFp0QYXYSDYxVaA6UBdkdimeowy/lMLQ==}
- engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
- peerDependencies:
- preact: ^10.6.5
-
'@astrojs/prism@3.3.0':
resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==}
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+ '@astrojs/react@4.4.2':
+ resolution: {integrity: sha512-1tl95bpGfuaDMDn8O3x/5Dxii1HPvzjvpL2YTuqOOrQehs60I2DKiDgh1jrKc7G8lv+LQT5H15V6QONQ+9waeQ==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+ peerDependencies:
+ '@types/react': ^17.0.50 || ^18.0.21 || ^19.0.0
+ '@types/react-dom': ^17.0.17 || ^18.0.6 || ^19.0.0
+ react: ^17.0.2 || ^18.0.0 || ^19.0.0
+ react-dom: ^17.0.2 || ^18.0.0 || ^19.0.0
+
'@astrojs/telemetry@3.3.0':
resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==}
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
@@ -96,10 +108,6 @@
resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==}
engines: {node: '>=6.9.0'}
- '@babel/helper-annotate-as-pure@7.27.3':
- resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
- engines: {node: '>=6.9.0'}
-
'@babel/helper-compilation-targets@7.27.2':
resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
engines: {node: '>=6.9.0'}
@@ -143,20 +151,14 @@
engines: {node: '>=6.0.0'}
hasBin: true
- '@babel/plugin-syntax-jsx@7.27.1':
- resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==}
+ '@babel/plugin-transform-react-jsx-self@7.27.1':
+ resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-react-jsx-development@7.27.1':
- resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==}
- engines: {node: '>=6.9.0'}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/plugin-transform-react-jsx@7.27.1':
- resolution: {integrity: sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==}
+ '@babel/plugin-transform-react-jsx-source@7.27.1':
+ resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@@ -573,40 +575,8 @@
'@oslojs/encoding@1.1.0':
resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
- '@preact/preset-vite@2.10.2':
- resolution: {integrity: sha512-K9wHlJOtkE+cGqlyQ5v9kL3Ge0Ql4LlIZjkUTL+1zf3nNdF88F9UZN6VTV8jdzBX9Fl7WSzeNMSDG7qECPmSmg==}
- peerDependencies:
- '@babel/core': 7.x
- vite: 2.x || 3.x || 4.x || 5.x || 6.x || 7.x
-
- '@preact/signals-core@1.12.1':
- resolution: {integrity: sha512-BwbTXpj+9QutoZLQvbttRg5x3l5468qaV2kufh+51yha1c53ep5dY4kTuZR35+3pAZxpfQerGJiQqg34ZNZ6uA==}
-
- '@preact/signals@2.5.1':
- resolution: {integrity: sha512-VPjk5YFt7i11Fi4UK0tzaEe5xLwfhUxXL3l89ocxQ5aPz7bRo8M5+N73LjBMPklyXKYKz6YsNo4Smp8n6nplng==}
- peerDependencies:
- preact: '>= 10.25.0 || >=11.0.0-0'
-
- '@prefresh/babel-plugin@0.5.2':
- resolution: {integrity: sha512-AOl4HG6dAxWkJ5ndPHBgBa49oo/9bOiJuRDKHLSTyH+Fd9x00shTXpdiTj1W41l6oQIwUOAgJeHMn4QwIDpHkA==}
-
- '@prefresh/core@1.5.9':
- resolution: {integrity: sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==}
- peerDependencies:
- preact: ^10.0.0 || ^11.0.0-0
-
- '@prefresh/utils@1.2.1':
- resolution: {integrity: sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==}
-
- '@prefresh/vite@2.4.11':
- resolution: {integrity: sha512-/XjURQqdRiCG3NpMmWqE9kJwrg9IchIOWHzulCfqg2sRe/8oQ1g5De7xrk9lbqPIQLn7ntBkKdqWXIj4E9YXyg==}
- peerDependencies:
- preact: ^10.4.0 || ^11.0.0-0
- vite: '>=2.0.0'
-
- '@rollup/pluginutils@4.2.1':
- resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==}
- engines: {node: '>= 8.0.0'}
+ '@rolldown/pluginutils@1.0.0-beta.27':
+ resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
'@rollup/pluginutils@5.3.0':
resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==}
@@ -841,6 +811,18 @@
peerDependencies:
vite: ^5.2.0 || ^6 || ^7
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
@@ -871,6 +853,14 @@
'@types/node@25.0.2':
resolution: {integrity: sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==}
+ '@types/react-dom@19.2.3':
+ resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
+ peerDependencies:
+ '@types/react': ^19.2.0
+
+ '@types/react@19.2.10':
+ resolution: {integrity: sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==}
+
'@types/ungap__structured-clone@1.2.0':
resolution: {integrity: sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==}
@@ -883,6 +873,12 @@
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+ '@vitejs/plugin-react@4.7.0':
+ resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -940,11 +936,6 @@
resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
engines: {node: '>= 0.4'}
- babel-plugin-transform-hook-names@1.0.2:
- resolution: {integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==}
- peerDependencies:
- '@babel/core': ^7.12.10
-
bail@2.0.2:
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
@@ -1075,6 +1066,9 @@
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
daisyui@5.5.14:
resolution: {integrity: sha512-L47rvw7I7hK68TA97VB8Ee0woHew+/ohR6Lx6Ah/krfISOqcG4My7poNpX5Mo5/ytMxiR40fEaz6njzDi7cuSg==}
@@ -1310,10 +1304,6 @@
hastscript@9.0.1:
resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
- he@1.2.0:
- resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
- hasBin: true
-
html-escaper@3.0.3:
resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
@@ -1391,9 +1381,6 @@
resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
engines: {node: '>=6'}
- kolorist@1.8.0:
- resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
-
lightningcss-android-arm64@1.30.2:
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
engines: {node: '>= 12.0.0'}
@@ -1673,9 +1660,6 @@
node-fetch-native@1.6.7:
resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
- node-html-parser@6.1.13:
- resolution: {integrity: sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==}
-
node-mock-http@1.0.4:
resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==}
@@ -1756,14 +1740,6 @@
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
- preact-render-to-string@6.6.4:
- resolution: {integrity: sha512-Bn6eQZ5SQ5loVEcC/mZmKT7HzO5Z/+vYzxfE/W2N468oSoNMJVdFGApF0GyXq0lDthuyXKTmtZ8k20NpYjr6Rw==}
- peerDependencies:
- preact: '>=10 || >= 11.0.0-0'
-
- preact@10.28.0:
- resolution: {integrity: sha512-rytDAoiXr3+t6OIP3WGlDd0ouCUG1iCWzkcY3++Nreuoi17y6T5i/zRhe6uYfoVcxq6YU+sBtJouuRDsq8vvqA==}
-
prismjs@1.30.0:
resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
engines: {node: '>=6'}
@@ -1778,6 +1754,19 @@
radix3@1.1.2:
resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
+ react-dom@19.2.4:
+ resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==}
+ peerDependencies:
+ react: ^19.2.4
+
+ react-refresh@0.17.0:
+ resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
+ engines: {node: '>=0.10.0'}
+
+ react@19.2.4:
+ resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==}
+ engines: {node: '>=0.10.0'}
+
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
@@ -1868,6 +1857,9 @@
sax@1.4.3:
resolution: {integrity: sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==}
+ scheduler@0.27.0:
+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@@ -1884,9 +1876,6 @@
shiki@3.20.0:
resolution: {integrity: sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg==}
- simple-code-frame@1.3.0:
- resolution: {integrity: sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w==}
-
sisteransi@1.0.5:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
@@ -1905,10 +1894,6 @@
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
- stack-trace@1.0.0-pre2:
- resolution: {integrity: sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==}
- engines: {node: '>=16'}
-
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -2119,11 +2104,6 @@
vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
- vite-prerender-plugin@0.5.12:
- resolution: {integrity: sha512-EiwhbMn+flg14EysbLTmZSzq8NGTxhytgK3bf4aGRF1evWLGwZiHiUJ1KZDvbxgKbMf2pG6fJWGEa3UZXOnR1g==}
- peerDependencies:
- vite: 5.x || 6.x || 7.x
-
vite@6.4.1:
resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -2277,15 +2257,20 @@
transitivePeerDependencies:
- supports-color
- '@astrojs/preact@4.1.3(@babel/core@7.28.5)(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)(preact@10.28.0)':
+ '@astrojs/prism@3.3.0':
dependencies:
- '@preact/preset-vite': 2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))
- '@preact/signals': 2.5.1(preact@10.28.0)
- preact: 10.28.0
- preact-render-to-string: 6.6.4(preact@10.28.0)
+ prismjs: 1.30.0
+
+ '@astrojs/react@4.4.2(@types/node@25.0.2)(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
+ dependencies:
+ '@types/react': 19.2.10
+ '@types/react-dom': 19.2.3(@types/react@19.2.10)
+ '@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ ultrahtml: 1.6.0
vite: 6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)
transitivePeerDependencies:
- - '@babel/core'
- '@types/node'
- jiti
- less
@@ -2299,10 +2284,6 @@
- tsx
- yaml
- '@astrojs/prism@3.3.0':
- dependencies:
- prismjs: 1.30.0
-
'@astrojs/telemetry@3.3.0':
dependencies:
ci-info: 4.3.1
@@ -2351,10 +2332,6 @@
'@jridgewell/trace-mapping': 0.3.31
jsesc: 3.1.0
- '@babel/helper-annotate-as-pure@7.27.3':
- dependencies:
- '@babel/types': 7.28.5
-
'@babel/helper-compilation-targets@7.27.2':
dependencies:
'@babel/compat-data': 7.28.5
@@ -2398,28 +2375,15 @@
dependencies:
'@babel/types': 7.28.5
- '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)':
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.28.5)':
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
- '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5)
- transitivePeerDependencies:
- - supports-color
-
- '@babel/plugin-transform-react-jsx@7.27.1(@babel/core@7.28.5)':
- dependencies:
- '@babel/core': 7.28.5
- '@babel/helper-annotate-as-pure': 7.27.3
- '@babel/helper-module-imports': 7.27.1
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5)
- '@babel/types': 7.28.5
- transitivePeerDependencies:
- - supports-color
'@babel/template@7.27.2':
dependencies:
@@ -2761,53 +2725,7 @@
'@oslojs/encoding@1.1.0': {}
- '@preact/preset-vite@2.10.2(@babel/core@7.28.5)(preact@10.28.0)(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))':
- dependencies:
- '@babel/core': 7.28.5
- '@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.5)
- '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.5)
- '@prefresh/vite': 2.4.11(preact@10.28.0)(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))
- '@rollup/pluginutils': 4.2.1
- babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.5)
- debug: 4.4.3
- picocolors: 1.1.1
- vite: 6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)
- vite-prerender-plugin: 0.5.12(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))
- transitivePeerDependencies:
- - preact
- - supports-color
-
- '@preact/signals-core@1.12.1': {}
-
- '@preact/signals@2.5.1(preact@10.28.0)':
- dependencies:
- '@preact/signals-core': 1.12.1
- preact: 10.28.0
-
- '@prefresh/babel-plugin@0.5.2': {}
-
- '@prefresh/core@1.5.9(preact@10.28.0)':
- dependencies:
- preact: 10.28.0
-
- '@prefresh/utils@1.2.1': {}
-
- '@prefresh/vite@2.4.11(preact@10.28.0)(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))':
- dependencies:
- '@babel/core': 7.28.5
- '@prefresh/babel-plugin': 0.5.2
- '@prefresh/core': 1.5.9(preact@10.28.0)
- '@prefresh/utils': 1.2.1
- '@rollup/pluginutils': 4.2.1
- preact: 10.28.0
- vite: 6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)
- transitivePeerDependencies:
- - supports-color
-
- '@rollup/pluginutils@4.2.1':
- dependencies:
- estree-walker: 2.0.2
- picomatch: 2.3.1
+ '@rolldown/pluginutils@1.0.0-beta.27': {}
'@rollup/pluginutils@5.3.0(rollup@4.53.3)':
dependencies:
@@ -2988,6 +2906,27 @@
tailwindcss: 4.1.18
vite: 6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.28.0
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.28.5
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+
+ '@types/babel__traverse@7.28.0':
+ dependencies:
+ '@babel/types': 7.28.5
+
'@types/debug@4.1.12':
dependencies:
'@types/ms': 2.1.0
@@ -3022,6 +2961,14 @@
dependencies:
undici-types: 7.16.0
+ '@types/react-dom@19.2.3(@types/react@19.2.10)':
+ dependencies:
+ '@types/react': 19.2.10
+
+ '@types/react@19.2.10':
+ dependencies:
+ csstype: 3.2.3
+
'@types/ungap__structured-clone@1.2.0': {}
'@types/unist@2.0.11': {}
@@ -3030,6 +2977,18 @@
'@ungap/structured-clone@1.3.0': {}
+ '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2))':
+ dependencies:
+ '@babel/core': 7.28.5
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5)
+ '@rolldown/pluginutils': 1.0.0-beta.27
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.17.0
+ vite: 6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)
+ transitivePeerDependencies:
+ - supports-color
+
acorn-jsx@5.3.2(acorn@8.15.0):
dependencies:
acorn: 8.15.0
@@ -3168,10 +3127,6 @@
axobject-query@4.1.0: {}
- babel-plugin-transform-hook-names@1.0.2(@babel/core@7.28.5):
- dependencies:
- '@babel/core': 7.28.5
-
bail@2.0.2: {}
base-64@1.0.0: {}
@@ -3281,6 +3236,8 @@
dependencies:
css-tree: 2.2.1
+ csstype@3.2.3: {}
+
daisyui@5.5.14: {}
debug@4.4.3:
@@ -3649,8 +3606,6 @@
property-information: 7.1.0
space-separated-tokens: 2.0.2
- he@1.2.0: {}
-
html-escaper@3.0.3: {}
html-void-elements@3.0.0: {}
@@ -3702,8 +3657,6 @@
kleur@3.0.3: {}
- kolorist@1.8.0: {}
-
lightningcss-android-arm64@1.30.2:
optional: true
@@ -4236,11 +4189,6 @@
node-fetch-native@1.6.7: {}
- node-html-parser@6.1.13:
- dependencies:
- css-select: 5.2.2
- he: 1.2.0
-
node-mock-http@1.0.4: {}
node-releases@2.0.27: {}
@@ -4329,12 +4277,6 @@
picocolors: 1.1.1
source-map-js: 1.2.1
- preact-render-to-string@6.6.4(preact@10.28.0):
- dependencies:
- preact: 10.28.0
-
- preact@10.28.0: {}
-
prismjs@1.30.0: {}
prompts@2.4.2:
@@ -4346,6 +4288,15 @@
radix3@1.1.2: {}
+ react-dom@19.2.4(react@19.2.4):
+ dependencies:
+ react: 19.2.4
+ scheduler: 0.27.0
+
+ react-refresh@0.17.0: {}
+
+ react@19.2.4: {}
+
readdirp@4.1.2: {}
recma-build-jsx@1.0.0:
@@ -4534,6 +4485,8 @@
sax@1.4.3: {}
+ scheduler@0.27.0: {}
+
semver@6.3.1: {}
semver@7.7.3: {}
@@ -4581,10 +4534,6 @@
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
- simple-code-frame@1.3.0:
- dependencies:
- kolorist: 1.8.0
-
sisteransi@1.0.5: {}
smol-toml@1.5.2: {}
@@ -4595,8 +4544,6 @@
space-separated-tokens@2.0.2: {}
- stack-trace@1.0.0-pre2: {}
-
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
@@ -4781,16 +4728,6 @@
'@types/unist': 3.0.3
vfile-message: 4.0.3
- vite-prerender-plugin@0.5.12(vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)):
- dependencies:
- kolorist: 1.8.0
- magic-string: 0.30.21
- node-html-parser: 6.1.13
- simple-code-frame: 1.3.0
- source-map: 0.7.6
- stack-trace: 1.0.0-pre2
- vite: 6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2)
-
vite@6.4.1(@types/node@25.0.2)(jiti@2.6.1)(lightningcss@1.30.2):
dependencies:
esbuild: 0.25.12
diff --git a/src/components/PmaLink.tsx b/src/components/PmaLink.tsx
new file mode 100644
index 0000000..f03ca73
--- /dev/null
+++ b/src/components/PmaLink.tsx
@@ -0,0 +1,29 @@
+import { usePhpMyAdminConnectionState } from "@/hooks/connection";
+import { useMemo } from "react";
+
+type Props = {
+ title?: string;
+};
+export default function PmaLink(props: Props) {
+ const { url, state } = usePhpMyAdminConnectionState();
+
+ const classState = useMemo(() => {
+ switch (state) {
+ case "established":
+ return "status-success";
+ case "failed":
+ return "status-error";
+ case "checking":
+ return "status-primary";
+ }
+ }, [state]);
+
+ const statusClass = useMemo(() => `status ${classState}`, [classState]);
+
+ return (
+
+
+ {props.title ?? "phpMyAdmin"}
+
+ );
+}
diff --git a/src/components/RenderFile.tsx b/src/components/RenderFile.tsx
index fe9cd0d..4ce9e98 100644
--- a/src/components/RenderFile.tsx
+++ b/src/components/RenderFile.tsx
@@ -1,5 +1,5 @@
import readRawText from "@/lib/getRawText";
-import { useEffect, useState } from "preact/hooks";
+import { useEffect, useState } from "react";
type RenderHtmlProps = {
path: string;
diff --git a/src/hooks/connection.ts b/src/hooks/connection.ts
new file mode 100644
index 0000000..c26a550
--- /dev/null
+++ b/src/hooks/connection.ts
@@ -0,0 +1,67 @@
+import { useLayoutEffect, useState } from "react";
+
+const { WEB_PORT = 8080, PHPMYADMIN_PORT = 8081 } = import.meta.env;
+
+export async function checkConnection(
+ url: string,
+ timeout?: number,
+): Promise {
+ const controller = new AbortController();
+ if (timeout) {
+ setTimeout(() => controller.abort(), timeout);
+ }
+
+ console.log(`Checking connection to ${url} ...`);
+
+ try {
+ const response = await fetch(url, {
+ signal: controller.signal,
+ });
+
+ return response.status !== 404;
+ } catch (e) {
+ const error = e as Error;
+
+ // check cors error
+ if (error.name === "TypeError") {
+ // return true;
+ }
+
+ return false;
+ }
+}
+
+export type ConnectionState = "established" | "failed" | "checking";
+export type ConnectionContextValue = {
+ url: string;
+ state: ConnectionState;
+};
+
+export function useConnectionState(url: string): ConnectionContextValue {
+ const [state, setState] = useState("checking");
+
+ useLayoutEffect(() => {
+ setState("checking");
+
+ checkConnection(url)
+ .then((isRunning) => {
+ setState(isRunning ? "established" : "failed");
+ })
+ .catch(() => setState("failed"));
+ }, [url]);
+
+ return {
+ url,
+ state,
+ };
+}
+
+export function useDockerWebConnectionState(): ConnectionContextValue {
+ const host = window.location.hostname;
+ return useConnectionState(`http://${host}:${WEB_PORT}`);
+}
+
+export function usePhpMyAdminConnectionState(): ConnectionContextValue {
+ const host = window.location.hostname;
+ return useConnectionState(`http://${host}:${PHPMYADMIN_PORT}`);
+}
diff --git a/src/pages/sql/015-phpmyadmin.mdx b/src/pages/sql/015-phpmyadmin.mdx
new file mode 100644
index 0000000..8a213dc
--- /dev/null
+++ b/src/pages/sql/015-phpmyadmin.mdx
@@ -0,0 +1,13 @@
+---
+layout: "@/layouts/MarkdownLayout.astro"
+---
+
+import PmaLink from "@/components/PmaLink.tsx";
+
+# {title}
+
+export const title = "PhpMyAdmin";
+
+このドキュメントでは、PhpMyAdminを使うことができるようになっています。
+
+
diff --git a/tsconfig.json b/tsconfig.json
index cea96c7..2485b64 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,9 +3,18 @@
"compilerOptions": {
"baseUrl": ".",
"paths": {
- "@/*": ["src/*"]
- }
+ "@/*": [
+ "src/*"
+ ]
+ },
+ "jsx": "react-jsx",
+ "jsxImportSource": "react"
},
- "include": [".astro/types.d.ts", "**/*"],
- "exclude": ["dist"]
-}
+ "include": [
+ ".astro/types.d.ts",
+ "**/*"
+ ],
+ "exclude": [
+ "dist"
+ ]
+}
\ No newline at end of file