From ef70a9a3ba6ba04dbb0d613b397caf21a96e9083 Mon Sep 17 00:00:00 2001 From: Crokily Date: Fri, 12 Sep 2025 16:14:44 +1000 Subject: [PATCH 1/8] chore: Upgrade Tailwind CSS to v4.1.13 and update PostCSS configuration --- app/globals.css | 53 ++- package.json | 3 +- pnpm-lock.yaml | 778 +++++++++++++++++++++++---------------------- postcss.config.mjs | 2 +- tailwind.config.ts | 19 -- 5 files changed, 436 insertions(+), 419 deletions(-) delete mode 100644 tailwind.config.ts diff --git a/app/globals.css b/app/globals.css index 13d40b8..a8352cd 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,27 +1,48 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import 'tailwindcss'; -:root { - --background: #ffffff; - --foreground: #171717; +@theme { + --color-background: var(--background); + --color-foreground: var(--foreground); } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; +/* + The default border color has changed to `currentcolor` in Tailwind CSS v4, + so we've added these compatibility styles to make sure everything still + looks the same as it did with Tailwind CSS v3. + + If we ever want to remove these styles, we need to add an explicit border + color utility to any element that depends on these defaults. +*/ +@layer base { + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + border-color: var(--color-gray-200, currentcolor); } } -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; +@utility text-balance { + text-wrap: balance; } @layer utilities { - .text-balance { - text-wrap: balance; + :root { + --background: #ffffff; + --foreground: #171717; + } + + @media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } + } + + body { + color: var(--foreground); + background: var(--background); + font-family: Arial, Helvetica, sans-serif; } } diff --git a/package.json b/package.json index 1db3ab5..c44a489 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "remark-gfm": "^4.0.1" }, "devDependencies": { + "@tailwindcss/postcss": "^4.1.13", "@types/node": "^24.3.1", "@types/react": "^19.1.12", "@types/react-dom": "^19.1.9", @@ -25,7 +26,7 @@ "eslint-config-next": "^15.5.3", "next-contentlayer": "^0.3.4", "postcss": "^8.5.6", - "tailwindcss": "^3.4.17", + "tailwindcss": "^4.1.13", "typescript": "^5.6.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 60a54a9..34390d8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,6 +27,9 @@ importers: specifier: ^4.0.1 version: 4.0.1 devDependencies: + '@tailwindcss/postcss': + specifier: ^4.1.13 + version: 4.1.13 '@types/node': specifier: ^24.3.1 version: 24.3.1 @@ -41,10 +44,10 @@ importers: version: 0.3.4(esbuild@0.18.20) eslint: specifier: ^9.35.0 - version: 9.35.0(jiti@1.21.7) + version: 9.35.0(jiti@2.5.1) eslint-config-next: specifier: ^15.5.3 - version: 15.5.3(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) + version: 15.5.3(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) next-contentlayer: specifier: ^0.3.4 version: 0.3.4(contentlayer@0.3.4(esbuild@0.18.20))(esbuild@0.18.20)(next@15.5.3(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(react-dom@19.1.1(react@19.1.1))(react@19.1.1) @@ -52,8 +55,8 @@ importers: specifier: ^8.5.6 version: 8.5.6 tailwindcss: - specifier: ^3.4.17 - version: 3.4.17 + specifier: ^4.1.13 + version: 4.1.13 typescript: specifier: ^5.6.3 version: 5.9.2 @@ -465,13 +468,16 @@ packages: cpu: [x64] os: [win32] - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -687,10 +693,6 @@ packages: resolution: {integrity: sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==} engines: {node: '>=14'} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -730,6 +732,94 @@ packages: '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@tailwindcss/node@4.1.13': + resolution: {integrity: sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==} + + '@tailwindcss/oxide-android-arm64@4.1.13': + resolution: {integrity: sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.13': + resolution: {integrity: sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.13': + resolution: {integrity: sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.13': + resolution: {integrity: sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13': + resolution: {integrity: sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.13': + resolution: {integrity: sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.13': + resolution: {integrity: sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.13': + resolution: {integrity: sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.13': + resolution: {integrity: sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.13': + resolution: {integrity: sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.13': + resolution: {integrity: sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.13': + resolution: {integrity: sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.13': + resolution: {integrity: sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==} + engines: {node: '>= 10'} + + '@tailwindcss/postcss@4.1.13': + resolution: {integrity: sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==} + '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -966,28 +1056,14 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - - any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} - arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -1098,10 +1174,6 @@ packages: camel-case@4.1.2: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - camelcase-css@2.0.1: - resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} - engines: {node: '>= 6'} - caniuse-lite@1.0.30001741: resolution: {integrity: sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==} @@ -1128,6 +1200,10 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} @@ -1157,10 +1233,6 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - comment-json@4.2.5: resolution: {integrity: sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==} engines: {node: '>= 6'} @@ -1180,11 +1252,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -1249,16 +1316,10 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} - dlv@1.1.3: - resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -1267,15 +1328,16 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enhanced-resolve@5.18.3: + resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} + engines: {node: '>=10.13.0'} + es-abstract@1.24.0: resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} engines: {node: '>= 0.4'} @@ -1537,10 +1599,6 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} - format@0.2.2: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} @@ -1597,10 +1655,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -1613,6 +1667,9 @@ packages: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -1876,11 +1933,8 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - jiti@1.21.7: - resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + jiti@2.5.1: + resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==} hasBin: true js-tokens@4.0.0: @@ -1936,12 +1990,69 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lilconfig@3.1.3: - resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} - engines: {node: '>=14'} + lightningcss-darwin-arm64@1.30.1: + resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + lightningcss-darwin-x64@1.30.1: + resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.1: + resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.1: + resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.1: + resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.1: + resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.1: + resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.1: + resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.1: + resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.1: + resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.1: + resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==} + engines: {node: '>= 12.0.0'} locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -1966,8 +2077,8 @@ packages: lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + magic-string@0.30.19: + resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} markdown-extensions@1.1.1: resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} @@ -2249,6 +2360,15 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + minizlib@3.0.2: + resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==} + engines: {node: '>= 18'} + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -2256,9 +2376,6 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2321,10 +2438,6 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -2373,9 +2486,6 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -2400,10 +2510,6 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} @@ -2418,55 +2524,10 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} - pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - - pirates@4.0.7: - resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} - engines: {node: '>= 6'} - possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} - postcss-import@15.1.0: - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} - peerDependencies: - postcss: ^8.0.0 - - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 - - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true - - postcss-nested@6.2.0: - resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.2.14 - - postcss-selector-parser@6.1.2: - resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} - engines: {node: '>=4'} - - postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} @@ -2508,9 +2569,6 @@ packages: resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} engines: {node: '>=0.10.0'} - read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2660,10 +2718,6 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -2699,10 +2753,6 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - string.prototype.includes@2.0.1: resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} engines: {node: '>= 0.4'} @@ -2733,10 +2783,6 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} - engines: {node: '>=12'} - strip-bom-string@1.0.0: resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} engines: {node: '>=0.10.0'} @@ -2765,11 +2811,6 @@ packages: babel-plugin-macros: optional: true - sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -2778,17 +2819,16 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tailwindcss@3.4.17: - resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} - engines: {node: '>=14.0.0'} - hasBin: true + tailwindcss@4.1.13: + resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==} - thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} + tapable@2.2.3: + resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==} + engines: {node: '>=6'} - thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + tar@7.4.3: + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} + engines: {node: '>=18'} tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} @@ -2813,9 +2853,6 @@ packages: peerDependencies: typescript: '>=4.8.4' - ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - ts-pattern@4.3.0: resolution: {integrity: sha512-pefrkcd4lmIVR0LA49Imjf9DYLK8vtWhqBPA3Ya1ir8xCW0O2yjL9dsCVvI7pCodLC5q7smNpEtDR2yVulQxOg==} @@ -2912,9 +2949,6 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -2975,14 +3009,14 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + yaml@2.8.1: resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} engines: {node: '>= 14.6'} @@ -3228,9 +3262,9 @@ snapshots: '@esbuild/win32-x64@0.18.20': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.35.0(jiti@1.21.7))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.35.0(jiti@2.5.1))': dependencies: - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -3383,20 +3417,20 @@ snapshots: '@img/sharp-win32-x64@0.34.3': optional: true - '@isaacs/cliui@8.0.2': + '@isaacs/fs-minipass@4.0.1': dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.2 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 + minipass: 7.1.2 '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -3614,9 +3648,6 @@ snapshots: '@opentelemetry/semantic-conventions@1.37.0': {} - '@pkgjs/parseargs@0.11.0': - optional: true - '@protobufjs/aspromise@1.1.2': {} '@protobufjs/base64@1.1.2': {} @@ -3648,6 +3679,78 @@ snapshots: dependencies: tslib: 2.8.1 + '@tailwindcss/node@4.1.13': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.18.3 + jiti: 2.5.1 + lightningcss: 1.30.1 + magic-string: 0.30.19 + source-map-js: 1.2.1 + tailwindcss: 4.1.13 + + '@tailwindcss/oxide-android-arm64@4.1.13': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.13': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.13': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.13': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.13': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.13': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.13': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.13': + optional: true + + '@tailwindcss/oxide@4.1.13': + dependencies: + detect-libc: 2.0.4 + tar: 7.4.3 + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.13 + '@tailwindcss/oxide-darwin-arm64': 4.1.13 + '@tailwindcss/oxide-darwin-x64': 4.1.13 + '@tailwindcss/oxide-freebsd-x64': 4.1.13 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.13 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.13 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.13 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.13 + '@tailwindcss/oxide-linux-x64-musl': 4.1.13 + '@tailwindcss/oxide-wasm32-wasi': 4.1.13 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.13 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.13 + + '@tailwindcss/postcss@4.1.13': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.1.13 + '@tailwindcss/oxide': 4.1.13 + postcss: 8.5.6 + tailwindcss: 4.1.13 + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -3711,15 +3814,15 @@ snapshots: '@types/unist@3.0.3': {} - '@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2))(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) '@typescript-eslint/scope-manager': 8.43.0 - '@typescript-eslint/type-utils': 8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) - '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) + '@typescript-eslint/type-utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.43.0 - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -3728,14 +3831,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2)': + '@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@typescript-eslint/scope-manager': 8.43.0 '@typescript-eslint/types': 8.43.0 '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.43.0 debug: 4.4.1 - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -3758,13 +3861,13 @@ snapshots: dependencies: typescript: 5.9.2 - '@typescript-eslint/type-utils@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2)': + '@typescript-eslint/type-utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@typescript-eslint/types': 8.43.0 '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) + '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) debug: 4.4.1 - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: @@ -3788,13 +3891,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2)': + '@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@1.21.7)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) '@typescript-eslint/scope-manager': 8.43.0 '@typescript-eslint/types': 8.43.0 '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -3880,23 +3983,15 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.3: {} - - any-promise@1.3.0: {} - anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - arg@5.0.2: {} - argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -4033,8 +4128,6 @@ snapshots: pascal-case: 3.1.2 tslib: 2.8.1 - camelcase-css@2.0.1: {} - caniuse-lite@1.0.30001741: {} ccount@2.0.1: {} @@ -4064,6 +4157,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chownr@3.0.0: {} + client-only@0.0.1: {} clipanion@3.2.1(typanion@3.14.0): @@ -4096,8 +4191,6 @@ snapshots: comma-separated-tokens@2.0.3: {} - commander@4.1.1: {} - comment-json@4.2.5: dependencies: array-timsort: 1.0.3 @@ -4130,8 +4223,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - cssesc@3.0.0: {} - csstype@3.1.3: {} damerau-levenshtein@1.0.8: {} @@ -4184,19 +4275,14 @@ snapshots: dequal@2.0.3: {} - detect-libc@2.0.4: - optional: true + detect-libc@2.0.4: {} devlop@1.1.0: dependencies: dequal: 2.0.3 - didyoumean@1.2.2: {} - diff@5.2.0: {} - dlv@1.1.3: {} - doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -4207,12 +4293,15 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - eastasianwidth@0.2.0: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} + enhanced-resolve@5.18.3: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.3 + es-abstract@1.24.0: dependencies: array-buffer-byte-length: 1.0.2 @@ -4345,19 +4434,19 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-next@15.5.3(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2): + eslint-config-next@15.5.3(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2): dependencies: '@next/eslint-plugin-next': 15.5.3 '@rushstack/eslint-patch': 1.12.0 - '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2))(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) - eslint: 9.35.0(jiti@1.21.7) + '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.35.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@1.21.7)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@1.21.7)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.35.0(jiti@1.21.7)) - eslint-plugin-react: 7.37.5(eslint@9.35.0(jiti@1.21.7)) - eslint-plugin-react-hooks: 5.2.0(eslint@9.35.0(jiti@1.21.7)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-react: 7.37.5(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-react-hooks: 5.2.0(eslint@9.35.0(jiti@2.5.1)) optionalDependencies: typescript: 5.9.2 transitivePeerDependencies: @@ -4373,33 +4462,33 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@1.21.7)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@1.21.7)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@1.21.7)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) - eslint: 9.35.0(jiti@1.21.7) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.35.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@1.21.7)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@1.21.7)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -4408,9 +4497,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@1.21.7)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.35.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -4422,13 +4511,13 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@1.21.7))(typescript@5.9.2) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.35.0(jiti@1.21.7)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.35.0(jiti@2.5.1)): dependencies: aria-query: 5.3.2 array-includes: 3.1.9 @@ -4438,7 +4527,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -4447,11 +4536,11 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-react-hooks@5.2.0(eslint@9.35.0(jiti@1.21.7)): + eslint-plugin-react-hooks@5.2.0(eslint@9.35.0(jiti@2.5.1)): dependencies: - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) - eslint-plugin-react@7.37.5(eslint@9.35.0(jiti@1.21.7)): + eslint-plugin-react@7.37.5(eslint@9.35.0(jiti@2.5.1)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -4459,7 +4548,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.35.0(jiti@1.21.7) + eslint: 9.35.0(jiti@2.5.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -4482,9 +4571,9 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.35.0(jiti@1.21.7): + eslint@9.35.0(jiti@2.5.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@1.21.7)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 '@eslint/config-helpers': 0.3.1 @@ -4520,7 +4609,7 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 1.21.7 + jiti: 2.5.1 transitivePeerDependencies: - supports-color @@ -4646,11 +4735,6 @@ snapshots: dependencies: is-callable: 1.2.7 - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - format@0.2.2: {} formdata-polyfill@4.0.10: @@ -4715,15 +4799,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.4.5: - dependencies: - foreground-child: 3.3.1 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - globals@14.0.0: {} globalthis@1.0.4: @@ -4733,6 +4808,8 @@ snapshots: gopd@1.2.0: {} + graceful-fs@4.2.11: {} + graphemer@1.4.0: {} gray-matter@4.0.3: @@ -5042,13 +5119,7 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jiti@1.21.7: {} + jiti@2.5.1: {} js-tokens@4.0.0: {} @@ -5099,9 +5170,50 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@3.1.3: {} + lightningcss-darwin-arm64@1.30.1: + optional: true + + lightningcss-darwin-x64@1.30.1: + optional: true - lines-and-columns@1.2.4: {} + lightningcss-freebsd-x64@1.30.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.1: + optional: true + + lightningcss-linux-arm64-gnu@1.30.1: + optional: true + + lightningcss-linux-arm64-musl@1.30.1: + optional: true + + lightningcss-linux-x64-gnu@1.30.1: + optional: true + + lightningcss-linux-x64-musl@1.30.1: + optional: true + + lightningcss-win32-arm64-msvc@1.30.1: + optional: true + + lightningcss-win32-x64-msvc@1.30.1: + optional: true + + lightningcss@1.30.1: + dependencies: + detect-libc: 2.0.4 + optionalDependencies: + lightningcss-darwin-arm64: 1.30.1 + lightningcss-darwin-x64: 1.30.1 + lightningcss-freebsd-x64: 1.30.1 + lightningcss-linux-arm-gnueabihf: 1.30.1 + lightningcss-linux-arm64-gnu: 1.30.1 + lightningcss-linux-arm64-musl: 1.30.1 + lightningcss-linux-x64-gnu: 1.30.1 + lightningcss-linux-x64-musl: 1.30.1 + lightningcss-win32-arm64-msvc: 1.30.1 + lightningcss-win32-x64-msvc: 1.30.1 locate-path@6.0.0: dependencies: @@ -5123,7 +5235,9 @@ snapshots: dependencies: tslib: 2.8.1 - lru-cache@10.4.3: {} + magic-string@0.30.19: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 markdown-extensions@1.1.1: {} @@ -5782,16 +5896,16 @@ snapshots: minipass@7.1.2: {} + minizlib@3.0.2: + dependencies: + minipass: 7.1.2 + + mkdirp@3.0.1: {} + mri@1.2.0: {} ms@2.1.3: {} - mz@2.7.0: - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - nanoid@3.3.11: {} napi-postinstall@0.3.3: {} @@ -5853,8 +5967,6 @@ snapshots: object-assign@4.1.1: {} - object-hash@3.0.0: {} - object-inspect@1.13.4: {} object-keys@1.1.1: {} @@ -5920,8 +6032,6 @@ snapshots: dependencies: p-limit: 3.1.0 - package-json-from-dist@1.0.1: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -5949,11 +6059,6 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - periscopic@3.1.0: dependencies: '@types/estree': 1.0.8 @@ -5966,43 +6071,8 @@ snapshots: picomatch@4.0.3: {} - pify@2.3.0: {} - - pirates@4.0.7: {} - possible-typed-array-names@1.1.0: {} - postcss-import@15.1.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-value-parser: 4.2.0 - read-cache: 1.0.0 - resolve: 1.22.10 - - postcss-js@4.0.1(postcss@8.5.6): - dependencies: - camelcase-css: 2.0.1 - postcss: 8.5.6 - - postcss-load-config@4.0.2(postcss@8.5.6): - dependencies: - lilconfig: 3.1.3 - yaml: 2.8.1 - optionalDependencies: - postcss: 8.5.6 - - postcss-nested@6.2.0(postcss@8.5.6): - dependencies: - postcss: 8.5.6 - postcss-selector-parser: 6.1.2 - - postcss-selector-parser@6.1.2: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-value-parser@4.2.0: {} - postcss@8.4.31: dependencies: nanoid: 3.3.11 @@ -6053,10 +6123,6 @@ snapshots: react@19.1.1: {} - read-cache@1.0.0: - dependencies: - pify: 2.3.0 - readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -6312,8 +6378,6 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - signal-exit@4.1.0: {} - simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 @@ -6347,12 +6411,6 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.2 - string.prototype.includes@2.0.1: dependencies: call-bind: 1.0.8 @@ -6412,10 +6470,6 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.2: - dependencies: - ansi-regex: 6.2.2 - strip-bom-string@1.0.0: {} strip-bom@3.0.0: {} @@ -6431,56 +6485,24 @@ snapshots: client-only: 0.0.1 react: 19.1.1 - sucrase@3.35.0: - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - commander: 4.1.1 - glob: 10.4.5 - lines-and-columns: 1.2.4 - mz: 2.7.0 - pirates: 4.0.7 - ts-interface-checker: 0.1.13 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 supports-preserve-symlinks-flag@1.0.0: {} - tailwindcss@3.4.17: - dependencies: - '@alloc/quick-lru': 5.2.0 - arg: 5.0.2 - chokidar: 3.6.0 - didyoumean: 1.2.2 - dlv: 1.1.3 - fast-glob: 3.3.3 - glob-parent: 6.0.2 - is-glob: 4.0.3 - jiti: 1.21.7 - lilconfig: 3.1.3 - micromatch: 4.0.8 - normalize-path: 3.0.0 - object-hash: 3.0.0 - picocolors: 1.1.1 - postcss: 8.5.6 - postcss-import: 15.1.0(postcss@8.5.6) - postcss-js: 4.0.1(postcss@8.5.6) - postcss-load-config: 4.0.2(postcss@8.5.6) - postcss-nested: 6.2.0(postcss@8.5.6) - postcss-selector-parser: 6.1.2 - resolve: 1.22.10 - sucrase: 3.35.0 - transitivePeerDependencies: - - ts-node + tailwindcss@4.1.13: {} - thenify-all@1.6.0: - dependencies: - thenify: 3.3.1 + tapable@2.2.3: {} - thenify@3.3.1: + tar@7.4.3: dependencies: - any-promise: 1.3.0 + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.0.2 + mkdirp: 3.0.1 + yallist: 5.0.0 tinyglobby@0.2.15: dependencies: @@ -6501,8 +6523,6 @@ snapshots: dependencies: typescript: 5.9.2 - ts-interface-checker@0.1.13: {} - ts-pattern@4.3.0: {} tsconfig-paths@3.15.0: @@ -6667,8 +6687,6 @@ snapshots: dependencies: punycode: 2.3.1 - util-deprecate@1.0.2: {} - uuid@8.3.2: {} uvu@0.5.6: @@ -6762,14 +6780,10 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 5.1.2 - strip-ansi: 7.1.2 - y18n@5.0.8: {} + yallist@5.0.0: {} + yaml@2.8.1: {} yargs-parser@21.1.1: {} diff --git a/postcss.config.mjs b/postcss.config.mjs index 1a69fd2..5d6d845 100644 --- a/postcss.config.mjs +++ b/postcss.config.mjs @@ -1,7 +1,7 @@ /** @type {import('postcss-load-config').Config} */ const config = { plugins: { - tailwindcss: {}, + '@tailwindcss/postcss': {}, }, }; diff --git a/tailwind.config.ts b/tailwind.config.ts deleted file mode 100644 index d43da91..0000000 --- a/tailwind.config.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { Config } from "tailwindcss"; - -const config: Config = { - content: [ - "./pages/**/*.{js,ts,jsx,tsx,mdx}", - "./components/**/*.{js,ts,jsx,tsx,mdx}", - "./app/**/*.{js,ts,jsx,tsx,mdx}", - ], - theme: { - extend: { - colors: { - background: "var(--background)", - foreground: "var(--foreground)", - }, - }, - }, - plugins: [], -}; -export default config; From a10fa80f985bda6778afcb02bf1e5732a20e73f1 Mon Sep 17 00:00:00 2001 From: Crokily Date: Fri, 12 Sep 2025 16:15:43 +1000 Subject: [PATCH 2/8] chore: Add autoprefixer dependency to package.json and update pnpm-lock.yaml --- package.json | 1 + pnpm-lock.yaml | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/package.json b/package.json index c44a489..3110bbe 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@types/node": "^24.3.1", "@types/react": "^19.1.12", "@types/react-dom": "^19.1.9", + "autoprefixer": "^10.4.21", "contentlayer": "^0.3.4", "eslint": "^9.35.0", "eslint-config-next": "^15.5.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 34390d8..0574e78 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,6 +39,9 @@ importers: '@types/react-dom': specifier: ^19.1.9 version: 19.1.9(@types/react@19.1.12) + autoprefixer: + specifier: ^10.4.21 + version: 10.4.21(postcss@8.5.6) contentlayer: specifier: ^0.3.4 version: 0.3.4(esbuild@0.18.20) @@ -1120,6 +1123,13 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} + autoprefixer@10.4.21: + resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -1152,6 +1162,11 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browserslist@4.25.4: + resolution: {integrity: sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -1328,6 +1343,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + electron-to-chromium@1.5.218: + resolution: {integrity: sha512-uwwdN0TUHs8u6iRgN8vKeWZMRll4gBkz+QMqdS7DDe49uiK68/UX92lFb61oiFPrpYZNeZIqa4bA7O6Aiasnzg==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1607,6 +1625,9 @@ packages: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fs-monkey@1.1.0: resolution: {integrity: sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==} @@ -2430,10 +2451,17 @@ packages: resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + node-releases@2.0.20: + resolution: {integrity: sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -2528,6 +2556,9 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} @@ -2946,6 +2977,12 @@ packages: unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -4075,6 +4112,16 @@ snapshots: async-function@1.0.0: {} + autoprefixer@10.4.21(postcss@8.5.6): + dependencies: + browserslist: 4.25.4 + caniuse-lite: 1.0.30001741 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-value-parser: 4.2.0 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -4102,6 +4149,13 @@ snapshots: dependencies: fill-range: 7.1.1 + browserslist@4.25.4: + dependencies: + caniuse-lite: 1.0.30001741 + electron-to-chromium: 1.5.218 + node-releases: 2.0.20 + update-browserslist-db: 1.1.3(browserslist@4.25.4) + buffer-from@1.1.2: {} call-bind-apply-helpers@1.0.2: @@ -4293,6 +4347,8 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + electron-to-chromium@1.5.218: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -4741,6 +4797,8 @@ snapshots: dependencies: fetch-blob: 3.2.0 + fraction.js@4.3.7: {} + fs-monkey@1.1.0: {} fsevents@2.3.3: @@ -5963,8 +6021,12 @@ snapshots: fetch-blob: 3.2.0 formdata-polyfill: 4.0.10 + node-releases@2.0.20: {} + normalize-path@3.0.0: {} + normalize-range@0.1.2: {} + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -6073,6 +6135,8 @@ snapshots: possible-typed-array-names@1.1.0: {} + postcss-value-parser@4.2.0: {} + postcss@8.4.31: dependencies: nanoid: 3.3.11 @@ -6683,6 +6747,12 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + update-browserslist-db@1.1.3(browserslist@4.25.4): + dependencies: + browserslist: 4.25.4 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 From 47d938760bc3a4c035f091108696012aa31bd29c Mon Sep 17 00:00:00 2001 From: Crokily Date: Fri, 12 Sep 2025 16:44:05 +1000 Subject: [PATCH 3/8] chore: Add new dependencies for styling and update globals.css with custom themes --- app/globals.css | 137 +++++++++++++++++++++++++++++++++++++++++++++ components.json | 22 ++++++++ lib/utils.ts | 6 ++ package.json | 7 ++- pnpm-lock.yaml | 47 ++++++++++++++++ postcss.config.mjs | 1 + 6 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 components.json create mode 100644 lib/utils.ts diff --git a/app/globals.css b/app/globals.css index a8352cd..cbd0745 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,4 +1,9 @@ @import 'tailwindcss'; +@import "tw-animate-css"; +/* + ---break--- +*/ +@custom-variant dark (&:is(.dark *)); @theme { --color-background: var(--background); @@ -46,3 +51,135 @@ font-family: Arial, Helvetica, sans-serif; } } + +/* + ---break--- +*/ + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +/* + ---break--- +*/ + +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +/* + ---break--- +*/ + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +/* + ---break--- +*/ + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/components.json b/components.json new file mode 100644 index 0000000..b7b9791 --- /dev/null +++ b/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/lib/utils.ts b/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/package.json b/package.json index 3110bbe..2893448 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,16 @@ "check:content": "contentlayer build" }, "dependencies": { + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.544.0", "next": "^15.5.3", "react": "^19.1.1", "react-dom": "^19.1.1", "rehype-autolink-headings": "^7.1.0", "rehype-slug": "^6.0.0", - "remark-gfm": "^4.0.1" + "remark-gfm": "^4.0.1", + "tailwind-merge": "^3.3.1" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.13", @@ -28,6 +32,7 @@ "next-contentlayer": "^0.3.4", "postcss": "^8.5.6", "tailwindcss": "^4.1.13", + "tw-animate-css": "^1.3.8", "typescript": "^5.6.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0574e78..1c5b730 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,15 @@ importers: .: dependencies: + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + lucide-react: + specifier: ^0.544.0 + version: 0.544.0(react@19.1.1) next: specifier: ^15.5.3 version: 15.5.3(@opentelemetry/api@1.9.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) @@ -26,6 +35,9 @@ importers: remark-gfm: specifier: ^4.0.1 version: 4.0.1 + tailwind-merge: + specifier: ^3.3.1 + version: 3.3.1 devDependencies: '@tailwindcss/postcss': specifier: ^4.1.13 @@ -60,6 +72,9 @@ importers: tailwindcss: specifier: ^4.1.13 version: 4.1.13 + tw-animate-css: + specifier: ^1.3.8 + version: 1.3.8 typescript: specifier: ^5.6.3 version: 5.9.2 @@ -1219,6 +1234,9 @@ packages: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} @@ -1231,6 +1249,10 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -2098,6 +2120,11 @@ packages: lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lucide-react@0.544.0: + resolution: {integrity: sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + magic-string@0.30.19: resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} @@ -2850,6 +2877,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + tailwind-merge@3.3.1: + resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} + tailwindcss@4.1.13: resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==} @@ -2893,6 +2923,9 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tw-animate-css@1.3.8: + resolution: {integrity: sha512-Qrk3PZ7l7wUcGYhwZloqfkWCmaXZAoqjkdbIDvzfGshwGtexa/DAs9koXxIkrpEasyevandomzCBAV1Yyop5rw==} + typanion@3.14.0: resolution: {integrity: sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==} @@ -4213,6 +4246,10 @@ snapshots: chownr@3.0.0: {} + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + client-only@0.0.1: {} clipanion@3.2.1(typanion@3.14.0): @@ -4225,6 +4262,8 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + clsx@2.1.1: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -5293,6 +5332,10 @@ snapshots: dependencies: tslib: 2.8.1 + lucide-react@0.544.0(react@19.1.1): + dependencies: + react: 19.1.1 + magic-string@0.30.19: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -6555,6 +6598,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + tailwind-merge@3.3.1: {} + tailwindcss@4.1.13: {} tapable@2.2.3: {} @@ -6598,6 +6643,8 @@ snapshots: tslib@2.8.1: {} + tw-animate-css@1.3.8: {} + typanion@3.14.0: {} type-check@0.4.0: diff --git a/postcss.config.mjs b/postcss.config.mjs index 5d6d845..2be675b 100644 --- a/postcss.config.mjs +++ b/postcss.config.mjs @@ -2,6 +2,7 @@ const config = { plugins: { '@tailwindcss/postcss': {}, + }, }; From e09f142ac0e1cfc9e0e53fccc329a7c7c6083224 Mon Sep 17 00:00:00 2001 From: Crokily Date: Fri, 12 Sep 2025 17:26:21 +1000 Subject: [PATCH 4/8] style: Update globals.css with new CSS variables and body letter-spacing for improved theming --- app/globals.css | 200 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 136 insertions(+), 64 deletions(-) diff --git a/app/globals.css b/app/globals.css index cbd0745..0204599 100644 --- a/app/globals.css +++ b/app/globals.css @@ -26,6 +26,9 @@ ::file-selector-button { border-color: var(--color-gray-200, currentcolor); } + body { + letter-spacing: var(--tracking-normal); + } } @utility text-balance { @@ -92,6 +95,33 @@ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); + --font-sans: Inter, ui-sans-serif, sans-serif, system-ui; + --font-mono: JetBrains Mono, monospace; + --font-serif: Merriweather, serif; + --radius: 1.25rem; + --tracking-tighter: calc(var(--tracking-normal) - 0.05em); + --tracking-tight: calc(var(--tracking-normal) - 0.025em); + --tracking-wide: calc(var(--tracking-normal) + 0.025em); + --tracking-wider: calc(var(--tracking-normal) + 0.05em); + --tracking-widest: calc(var(--tracking-normal) + 0.1em); + --tracking-normal: var(--tracking-normal); + --shadow-2xl: var(--shadow-2xl); + --shadow-xl: var(--shadow-xl); + --shadow-lg: var(--shadow-lg); + --shadow-md: var(--shadow-md); + --shadow: var(--shadow); + --shadow-sm: var(--shadow-sm); + --shadow-xs: var(--shadow-xs); + --shadow-2xs: var(--shadow-2xs); + --spacing: var(--spacing); + --letter-spacing: var(--letter-spacing); + --shadow-offset-y: var(--shadow-offset-y); + --shadow-offset-x: var(--shadow-offset-x); + --shadow-spread: var(--shadow-spread); + --shadow-blur: var(--shadow-blur); + --shadow-opacity: var(--shadow-opacity); + --color-shadow-color: var(--shadow-color); + --color-destructive-foreground: var(--destructive-foreground); } /* @@ -99,38 +129,59 @@ */ :root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); + --radius: 1.25rem; + --background: oklch(0.9670 0.0029 264.5419); + --foreground: oklch(0.2795 0.0368 260.0310); + --card: oklch(1.0000 0 0); + --card-foreground: oklch(0.2795 0.0368 260.0310); + --popover: oklch(1.0000 0 0); + --popover-foreground: oklch(0.2795 0.0368 260.0310); + --primary: oklch(0.5854 0.2041 277.1173); + --primary-foreground: oklch(1.0000 0 0); + --secondary: oklch(0.9276 0.0058 264.5313); + --secondary-foreground: oklch(0.3729 0.0306 259.7328); + --muted: oklch(0.9670 0.0029 264.5419); + --muted-foreground: oklch(0.5510 0.0234 264.3637); + --accent: oklch(0.9299 0.0334 272.7879); + --accent-foreground: oklch(0.3729 0.0306 259.7328); + --destructive: oklch(0.6368 0.2078 25.3313); + --border: oklch(0.9851 0 0); + --input: oklch(0.8717 0.0093 258.3382); + --ring: oklch(0.5854 0.2041 277.1173); + --chart-1: oklch(0.5854 0.2041 277.1173); + --chart-2: oklch(0.5106 0.2301 276.9656); + --chart-3: oklch(0.4568 0.2146 277.0229); + --chart-4: oklch(0.3984 0.1773 277.3662); + --chart-5: oklch(0.3588 0.1354 278.6973); + --sidebar: oklch(0.9670 0.0029 264.5419); + --sidebar-foreground: oklch(0.2795 0.0368 260.0310); + --sidebar-primary: oklch(0.5854 0.2041 277.1173); + --sidebar-primary-foreground: oklch(1.0000 0 0); + --sidebar-accent: oklch(0.9299 0.0334 272.7879); + --sidebar-accent-foreground: oklch(0.3729 0.0306 259.7328); + --sidebar-border: oklch(0.8717 0.0093 258.3382); + --sidebar-ring: oklch(0.5854 0.2041 277.1173); + --destructive-foreground: oklch(1.0000 0 0); + --font-sans: Inter, ui-sans-serif, sans-serif, system-ui; + --font-serif: Merriweather, serif; + --font-mono: JetBrains Mono, monospace; + --shadow-color: #1a1a1a; + --shadow-opacity: 0.1; + --shadow-blur: 15px; + --shadow-spread: -1px; + --shadow-offset-x: 0px; + --shadow-offset-y: 0px; + --letter-spacing: 0em; + --spacing: 0.25rem; + --shadow-2xs: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.05); + --shadow-xs: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.05); + --shadow-sm: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 1px 2px -2px hsl(0 0% 10.1961% / 0.10); + --shadow: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 1px 2px -2px hsl(0 0% 10.1961% / 0.10); + --shadow-md: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 2px 4px -2px hsl(0 0% 10.1961% / 0.10); + --shadow-lg: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 4px 6px -2px hsl(0 0% 10.1961% / 0.10); + --shadow-xl: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 8px 10px -2px hsl(0 0% 10.1961% / 0.10); + --shadow-2xl: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.25); + --tracking-normal: 0em; } /* @@ -138,37 +189,58 @@ */ .dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); + --background: oklch(0.2077 0.0398 265.7549); + --foreground: oklch(0.9288 0.0126 255.5078); + --card: oklch(0.2795 0.0368 260.0310); + --card-foreground: oklch(0.9288 0.0126 255.5078); + --popover: oklch(0.2795 0.0368 260.0310); + --popover-foreground: oklch(0.9288 0.0126 255.5078); + --primary: oklch(0.6801 0.1583 276.9349); + --primary-foreground: oklch(0.2077 0.0398 265.7549); + --secondary: oklch(0.3351 0.0331 260.9120); + --secondary-foreground: oklch(0.8717 0.0093 258.3382); + --muted: oklch(0.2795 0.0368 260.0310); + --muted-foreground: oklch(0.7137 0.0192 261.3246); + --accent: oklch(0.3729 0.0306 259.7328); + --accent-foreground: oklch(0.8717 0.0093 258.3382); + --destructive: oklch(0.6368 0.2078 25.3313); + --border: oklch(0.4461 0.0263 256.8018); + --input: oklch(0.4461 0.0263 256.8018); + --ring: oklch(0.6801 0.1583 276.9349); + --chart-1: oklch(0.6801 0.1583 276.9349); + --chart-2: oklch(0.5854 0.2041 277.1173); + --chart-3: oklch(0.5106 0.2301 276.9656); + --chart-4: oklch(0.4568 0.2146 277.0229); + --chart-5: oklch(0.3984 0.1773 277.3662); + --sidebar: oklch(0.2795 0.0368 260.0310); + --sidebar-foreground: oklch(0.9288 0.0126 255.5078); + --sidebar-primary: oklch(0.6801 0.1583 276.9349); + --sidebar-primary-foreground: oklch(0.2077 0.0398 265.7549); + --sidebar-accent: oklch(0.3729 0.0306 259.7328); + --sidebar-accent-foreground: oklch(0.8717 0.0093 258.3382); + --sidebar-border: oklch(0.4461 0.0263 256.8018); + --sidebar-ring: oklch(0.6801 0.1583 276.9349); + --destructive-foreground: oklch(0.2077 0.0398 265.7549); + --radius: 1.25rem; + --font-sans: Inter, ui-sans-serif, sans-serif, system-ui; + --font-serif: Merriweather, serif; + --font-mono: JetBrains Mono, monospace; + --shadow-color: #1a1a1a; + --shadow-opacity: 0.1; + --shadow-blur: 15px; + --shadow-spread: -1px; + --shadow-offset-x: 0px; + --shadow-offset-y: 0px; + --letter-spacing: 0em; + --spacing: 0.25rem; + --shadow-2xs: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.05); + --shadow-xs: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.05); + --shadow-sm: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 1px 2px -2px hsl(0 0% 10.1961% / 0.10); + --shadow: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 1px 2px -2px hsl(0 0% 10.1961% / 0.10); + --shadow-md: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 2px 4px -2px hsl(0 0% 10.1961% / 0.10); + --shadow-lg: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 4px 6px -2px hsl(0 0% 10.1961% / 0.10); + --shadow-xl: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.10), 0px 8px 10px -2px hsl(0 0% 10.1961% / 0.10); + --shadow-2xl: 0px 0px 15px -1px hsl(0 0% 10.1961% / 0.25); } /* @@ -182,4 +254,4 @@ body { @apply bg-background text-foreground; } -} +} \ No newline at end of file From fa38965ac4551cdc12940c594ee52ccd13910a52 Mon Sep 17 00:00:00 2001 From: Crokily Date: Fri, 12 Sep 2025 18:15:57 +1000 Subject: [PATCH 5/8] feat(contentlayer): enhance document slug generation and add new computed fields for ordering and nesting level --- .../data-structures/array/01-static-array.mdx | 159 +++++ .../array/02-dynamic-array.mdx | 321 ++++++++++ .../data-structures/array/index.mdx | 74 +++ .../data-structures/index.mdx | 42 ++ .../linked-list/01-singly-linked-list.mdx | 565 ++++++++++++++++++ .../data-structures/linked-list/index.mdx | 239 ++++++++ app/docs/computer-science/index.mdx | 37 ++ contentlayer.config.ts | 125 +++- 8 files changed, 1533 insertions(+), 29 deletions(-) create mode 100644 app/docs/computer-science/data-structures/array/01-static-array.mdx create mode 100644 app/docs/computer-science/data-structures/array/02-dynamic-array.mdx create mode 100644 app/docs/computer-science/data-structures/array/index.mdx create mode 100644 app/docs/computer-science/data-structures/index.mdx create mode 100644 app/docs/computer-science/data-structures/linked-list/01-singly-linked-list.mdx create mode 100644 app/docs/computer-science/data-structures/linked-list/index.mdx create mode 100644 app/docs/computer-science/index.mdx diff --git a/app/docs/computer-science/data-structures/array/01-static-array.mdx b/app/docs/computer-science/data-structures/array/01-static-array.mdx new file mode 100644 index 0000000..3b9062a --- /dev/null +++ b/app/docs/computer-science/data-structures/array/01-static-array.mdx @@ -0,0 +1,159 @@ +--- +title: "Static Array" +description: "Implementation principles, characteristics, and use cases of static arrays" +date: "2024-01-04" +tags: + - static-array + - memory-management +--- + +# Static Array + +Static arrays are the most basic form of arrays. Their size is determined at compile time and cannot be changed during program execution. + +## Memory Layout + +Static arrays are stored contiguously in memory: + +``` +Memory addresses: 1000 1004 1008 1012 1016 +Array: [10] [20] [30] [40] [50] +Indices: 0 1 2 3 4 +``` + +Assuming each integer occupies 4 bytes, the memory address of array element `arr[i]` is: +``` +address = base_address + i * element_size +``` + +## Characteristics Analysis + +### Time Complexity +- **Access**: O(1) - Direct memory address calculation through indexing +- **Search**: O(n) - Need to traverse the entire array +- **Insert**: O(n) - Need to move subsequent elements +- **Delete**: O(n) - Need to move subsequent elements + +### Space Complexity +- **Storage**: O(n) - n elements +- **Extra Space**: O(1) - No additional pointers or metadata needed + +## Code Implementation + +### C++ Implementation +```cpp +#include +using namespace std; + +int main() { + // Declare static array + int arr[5] = {10, 20, 30, 40, 50}; + + // Access element + cout << "First element: " << arr[0] << endl; + + // Modify element + arr[2] = 35; + + // Traverse array + for (int i = 0; i < 5; i++) { + cout << arr[i] << " "; + } + + return 0; +} +``` + +### JavaScript Implementation +```javascript +// Arrays in JavaScript are actually dynamic, but we can simulate static array behavior +class StaticArray { + constructor(size) { + this.size = size; + this.data = new Array(size); + } + + get(index) { + if (index < 0 || index >= this.size) { + throw new Error("Index out of bounds"); + } + return this.data[index]; + } + + set(index, value) { + if (index < 0 || index >= this.size) { + throw new Error("Index out of bounds"); + } + this.data[index] = value; + } + + length() { + return this.size; + } +} + +// Usage example +const arr = new StaticArray(5); +arr.set(0, 10); +arr.set(1, 20); +console.log(arr.get(0)); // 10 +``` + +## Advantages and Limitations + +### Advantages +1. **High Memory Efficiency**: No additional metadata overhead +2. **Cache Friendly**: Contiguous memory layout improves access efficiency +3. **Simple and Direct**: Easy to implement and use +4. **Compile-time Optimization**: Compiler can perform more optimizations + +### Limitations +1. **Fixed Size**: Cannot change size at runtime +2. **Memory Waste**: If not all space can be utilized fully +3. **Inefficient Insertion/Deletion**: Need to move many elements + +## Application Scenarios + +Static arrays are particularly suitable for: + +- **Embedded Systems**: Memory constrained, need precise memory control +- **High-performance Computing**: Need to maximize memory access efficiency +- **Systems Programming**: Low-level system code, need predictable memory layout +- **Fixed-size Datasets**: Such as pixel arrays, audio samples, etc. + +## Practical Examples + +### Image Processing +```cpp +// Process a 640x480 grayscale image +unsigned char image[640 * 480]; + +// Access pixel (x, y) +int getPixel(int x, int y) { + return image[y * 640 + x]; +} + +// Set pixel value +void setPixel(int x, int y, unsigned char value) { + image[y * 640 + x] = value; +} +``` + +### Lookup Table +```cpp +// Pre-computed lookup table +const int SQUARE_TABLE[101] = { + 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, + // ... Pre-computed squares for 0-100 +}; + +int getSquare(int n) { + return SQUARE_TABLE[n]; // O(1) lookup +} +``` + +## Summary + +Static arrays are the foundation for understanding all array types. Although they have the limitation of fixed size, their efficiency and simplicity make them irreplaceable in specific scenarios. + +In the next section, we will learn how dynamic arrays solve the problem of static array's fixed size. diff --git a/app/docs/computer-science/data-structures/array/02-dynamic-array.mdx b/app/docs/computer-science/data-structures/array/02-dynamic-array.mdx new file mode 100644 index 0000000..61f34a5 --- /dev/null +++ b/app/docs/computer-science/data-structures/array/02-dynamic-array.mdx @@ -0,0 +1,321 @@ +--- +title: "Dynamic Array" +description: "Implementation principles, resizing mechanisms, and performance analysis of dynamic arrays" +date: "2024-01-05" +tags: + - dynamic-array + - resizing + - amortized-analysis +--- + +# Dynamic Array + +Dynamic arrays solve the problem of static arrays having fixed sizes. They can be dynamically resized at runtime and form the foundation for many advanced data structures and algorithms. + +## Core Concepts + +Dynamic arrays achieve dynamic expansion through the following mechanisms: + +1. **Capacity**: The number of elements that can be stored in the currently allocated memory +2. **Size**: The number of elements currently actually stored +3. **Resizing Strategy**: When size exceeds capacity, reallocate larger memory space + +``` +Capacity: [_ _ _ _ _ _ _ _] (capacity = 8) +Size: [1 2 3 4 _ _ _ _] (size = 4) +``` + +## Resizing Mechanism + +### Common Resizing Strategies + +1. **Doubling Growth**: Double the capacity each time +2. **Golden Ratio Growth**: Growth factor of 1.5 or 1.618 +3. **Fixed Growth**: Add a fixed amount of space each time + +```javascript +// Doubling growth example +function resize(oldCapacity) { + return oldCapacity * 2; // or oldCapacity + oldCapacity +} +``` + +### Resizing Process + +``` +Initial state: [1 2 3 4] capacity=4, size=4 + +Adding element 5: +1. Detect that size == capacity +2. Allocate new memory: capacity = 4 * 2 = 8 +3. Copy old data: [1 2 3 4 _ _ _ _] +4. Add new element: [1 2 3 4 5 _ _ _] +5. Release old memory +``` + +## Code Implementation + +### JavaScript Implementation + +```javascript +class DynamicArray { + constructor() { + this.capacity = 2; + this.size = 0; + this.data = new Array(this.capacity); + } + + // Get element + get(index) { + if (index < 0 || index >= this.size) { + throw new Error("Index out of bounds"); + } + return this.data[index]; + } + + // Set element + set(index, value) { + if (index < 0 || index >= this.size) { + throw new Error("Index out of bounds"); + } + this.data[index] = value; + } + + // Add element to end + push(value) { + // Check if resize is needed + if (this.size >= this.capacity) { + this.resize(); + } + + this.data[this.size] = value; + this.size++; + } + + // Remove last element + pop() { + if (this.size === 0) { + throw new Error("Array is empty"); + } + + const value = this.data[this.size - 1]; + this.size--; + + // Optional: shrink to save memory + if (this.size < this.capacity / 4) { + this.shrink(); + } + + return value; + } + + // Resize (expand) + resize() { + const oldCapacity = this.capacity; + this.capacity *= 2; + const newData = new Array(this.capacity); + + // Copy old data + for (let i = 0; i < this.size; i++) { + newData[i] = this.data[i]; + } + + this.data = newData; + console.log(`Expanded: ${oldCapacity} -> ${this.capacity}`); + } + + // Shrink (reduce capacity) + shrink() { + if (this.capacity <= 2) return; + + const oldCapacity = this.capacity; + this.capacity = Math.floor(this.capacity / 2); + const newData = new Array(this.capacity); + + for (let i = 0; i < this.size; i++) { + newData[i] = this.data[i]; + } + + this.data = newData; + console.log(`Shrunk: ${oldCapacity} -> ${this.capacity}`); + } + + // Insert element at specified position + insert(index, value) { + if (index < 0 || index > this.size) { + throw new Error("Index out of bounds"); + } + + if (this.size >= this.capacity) { + this.resize(); + } + + // Shift elements to the right + for (let i = this.size; i > index; i--) { + this.data[i] = this.data[i - 1]; + } + + this.data[index] = value; + this.size++; + } + + // 删除指定位置的元素 + remove(index) { + if (index < 0 || index >= this.size) { + throw new Error("Index out of bounds"); + } + + const value = this.data[index]; + + // 向左移动元素 + for (let i = index; i < this.size - 1; i++) { + this.data[i] = this.data[i + 1]; + } + + this.size--; + + if (this.size < this.capacity / 4) { + this.shrink(); + } + + return value; + } + + length() { + return this.size; + } + + toString() { + const elements = []; + for (let i = 0; i < this.size; i++) { + elements.push(this.data[i]); + } + return `[${elements.join(', ')}] (size: ${this.size}, capacity: ${this.capacity})`; + } +} +``` + +### 使用示例 + +```javascript +const arr = new DynamicArray(); + +// 添加元素 +arr.push(1); +arr.push(2); +arr.push(3); // 触发扩容 +console.log(arr.toString()); // [1, 2, 3] (size: 3, capacity: 4) + +// 插入元素 +arr.insert(1, 10); +console.log(arr.toString()); // [1, 10, 2, 3] (size: 4, capacity: 4) + +// 删除元素 +arr.remove(0); +console.log(arr.toString()); // [10, 2, 3] (size: 3, capacity: 4) +``` + +## 性能分析 + +### 时间复杂度 + +| 操作 | 平均情况 | 最坏情况 | 说明 | +|------|----------|----------|------| +| 访问 | O(1) | O(1) | 直接索引访问 | +| 搜索 | O(n) | O(n) | 需要遍历 | +| 插入(末尾) | O(1)* | O(n) | 摊还O(1),偶尔需要扩容 | +| 插入(任意位置) | O(n) | O(n) | 需要移动元素 | +| 删除(末尾) | O(1)* | O(1) | 摊还O(1) | +| 删除(任意位置) | O(n) | O(n) | 需要移动元素 | + +*摊还时间复杂度 + +### 摊还分析 + +虽然单次扩容操作需要 O(n) 时间,但通过摊还分析可以证明: + +- 连续进行 n 次 `push` 操作的总时间复杂度为 O(n) +- 因此单次 `push` 操作的摊还时间复杂度为 O(1) + +**证明思路**: +- 假设从空数组开始,进行 n 次 push 操作 +- 扩容发生在大小为 1, 2, 4, 8, ..., 2^k 时 +- 总的复制操作次数为:1 + 2 + 4 + ... + 2^k < 2n +- 所以平均每次 push 的成本为 (n + 2n) / n = 3 = O(1) + +## 优化策略 + +### 1. 选择合适的增长因子 + +```javascript +// 不同的增长策略 +const GROWTH_STRATEGIES = { + DOUBLE: (capacity) => capacity * 2, // 快速增长,可能浪费内存 + GOLDEN_RATIO: (capacity) => Math.floor(capacity * 1.5), // 平衡增长 + FIBONACCI: (capacity) => capacity + previousCapacity, // 渐进增长 +}; +``` + +### 2. 预分配容量 + +```javascript +// 如果知道大概的数据量,可以预分配容量 +class DynamicArray { + constructor(initialCapacity = 2) { + this.capacity = initialCapacity; + this.size = 0; + this.data = new Array(this.capacity); + } + + // 预留容量 + reserve(minCapacity) { + if (minCapacity > this.capacity) { + this.capacity = minCapacity; + this.resize(); + } + } +} +``` + +### 3. 内存对齐优化 + +```cpp +// C++ 中考虑内存对齐 +template +class DynamicArray { +private: + T* data; + size_t size; + size_t capacity; + + // 确保容量是 2 的幂次,有利于内存对齐 + size_t nextPowerOfTwo(size_t n) { + size_t power = 1; + while (power < n) power <<= 1; + return power; + } +}; +``` + +## Practical Applications + +### 1. Dynamic Arrays in Programming Languages + +- **JavaScript**: `Array` +- **Python**: `list` +- **Java**: `ArrayList` +- **C++**: `std::vector` +- **C#**: `List` + +### 2. Application Scenarios + +- **Buffers**: Network packet buffering, file reading buffers +- **Collections**: Implementing stacks, queues, and other data structures +- **Graphics Programming**: Vertex arrays, pixel buffers +- **Data Processing**: Dynamically adding and processing data items + +## Summary + +Dynamic arrays are one of the most important data structures in modern programming. They combine the efficient access characteristics of arrays with flexible size adjustment capabilities. Understanding their resizing mechanisms and amortized analysis is crucial for writing efficient code. + +Although dynamic arrays solve the size limitation problem of static arrays, in certain scenarios, other data structures like linked lists may be more suitable. In the next section, we will learn about linked list knowledge. diff --git a/app/docs/computer-science/data-structures/array/index.mdx b/app/docs/computer-science/data-structures/array/index.mdx new file mode 100644 index 0000000..e654e20 --- /dev/null +++ b/app/docs/computer-science/data-structures/array/index.mdx @@ -0,0 +1,74 @@ +--- +title: "Array" +description: "Basic concepts, characteristics, and applications of arrays" +date: "2024-01-03" +tags: + - array + - linear-data-structure +--- + +# Array + +Arrays are one of the most basic and important data structures. They are an ordered collection that stores elements of the same type, with these elements stored contiguously in memory. + +## Array Characteristics + +### Advantages +- **Random Access**: Can access any element in O(1) time through indexing +- **Memory Efficiency**: Elements are stored contiguously with high memory utilization +- **Cache Friendly**: Contiguous memory access pattern is CPU cache friendly + +### Disadvantages +- **Fixed Size**: Static array size is determined at creation time and cannot be dynamically adjusted +- **Insertion/Deletion Overhead**: Inserting or deleting elements in the middle requires moving other elements + +## Array Types + +### Static Array +- [Static Array Details](/computer-science/data-structures/array/static-array) +- Size determined at compile time +- Usually allocated on the stack + +### Dynamic Array +- [Dynamic Array Details](/computer-science/data-structures/array/dynamic-array) +- Size can be adjusted at runtime +- Usually allocated on the heap + +## Basic Operations + +```javascript +// Create array +const arr = [1, 2, 3, 4, 5]; + +// Access element - O(1) +const element = arr[2]; // 3 + +// Modify element - O(1) +arr[1] = 10; + +// Traverse array - O(n) +for (let i = 0; i < arr.length; i++) { + console.log(arr[i]); +} +``` + +## Time Complexity + +| Operation | Time Complexity | +|-----------|----------------| +| Access | O(1) | +| Search | O(n) | +| Insert | O(n) | +| Delete | O(n) | + +## Application Scenarios + +Arrays are suitable for: +- Scenarios requiring frequent random access to elements +- Situations where data size is relatively fixed +- Algorithms requiring efficient traversal +- Serving as the foundation for other data structures + +--- + +Continue learning about specific implementations and advanced applications of arrays! diff --git a/app/docs/computer-science/data-structures/index.mdx b/app/docs/computer-science/data-structures/index.mdx new file mode 100644 index 0000000..ae6dd88 --- /dev/null +++ b/app/docs/computer-science/data-structures/index.mdx @@ -0,0 +1,42 @@ +--- +title: "Data Structures Fundamentals" +description: "Basic concepts and core knowledge of data structures" +date: "2024-01-02" +tags: + - data-structures + - fundamentals +--- + +# Data Structures Fundamentals + +Data structures are the foundation of computer science. They study how to organize and store data in computers to enable efficient access and modification. + +## What are Data Structures? + +A data structure is a format for organizing, managing, and storing data that makes data access and modification more efficient. Choosing the right data structure is crucial for designing efficient algorithms. + +## Main Classifications + +### Linear Data Structures +- [Array](/computer-science/data-structures/array) - The most basic data structure +- [Linked List](/computer-science/data-structures/linked-list) - Dynamic data structure +- Stack - Last In First Out (LIFO) +- Queue - First In First Out (FIFO) + +### Non-linear Data Structures +- Tree - Hierarchical structure +- Graph - Complex relationship structure +- Hash Table - Fast lookup structure + +## Learning Focus + +When studying data structures, focus on: + +1. **Time Complexity** - Operation efficiency +2. **Space Complexity** - Memory usage +3. **Application Scenarios** - When to use which structure +4. **Implementation Details** - How to code the implementation + +## Next Steps + +We recommend starting with the most basic array, then gradually moving to more complex data structures. Each structure has its unique advantages and applicable scenarios. diff --git a/app/docs/computer-science/data-structures/linked-list/01-singly-linked-list.mdx b/app/docs/computer-science/data-structures/linked-list/01-singly-linked-list.mdx new file mode 100644 index 0000000..057fa20 --- /dev/null +++ b/app/docs/computer-science/data-structures/linked-list/01-singly-linked-list.mdx @@ -0,0 +1,565 @@ +--- +title: "Singly Linked List" +description: "Implementation, operations, and applications of singly linked lists" +date: "2024-01-07" +tags: + - singly-linked-list + - pointer-operations + - basic-data-structure +--- + +# Singly Linked List + +A singly linked list is the most basic form of linked list, where each node contains data and a pointer to the next node. It provides dynamic memory allocation and efficient insertion and deletion operations. + +## Node Structure + +```javascript +class ListNode { + constructor(data) { + this.data = data; // Data field + this.next = null; // Pointer field, points to next node + } +} +``` + +## Complete Implementation + +```javascript +class SinglyLinkedList { + constructor() { + this.head = null; // Head pointer + this.size = 0; // List length + } + + // Insert node at head + prepend(data) { + const newNode = new ListNode(data); + newNode.next = this.head; + this.head = newNode; + this.size++; + } + + // Insert node at tail + append(data) { + const newNode = new ListNode(data); + + // If list is empty, new node becomes head node + if (!this.head) { + this.head = newNode; + this.size++; + return; + } + + // Find the last node + let current = this.head; + while (current.next) { + current = current.next; + } + + // Link the new node + current.next = newNode; + this.size++; + } + + // Insert node at specified position + insert(index, data) { + if (index < 0 || index > this.size) { + throw new Error("Index out of bounds"); + } + + // Insert at head + if (index === 0) { + this.prepend(data); + return; + } + + const newNode = new ListNode(data); + let current = this.head; + + // Find the node before the insertion position + for (let i = 0; i < index - 1; i++) { + current = current.next; + } + + // Insert new node + newNode.next = current.next; + current.next = newNode; + this.size++; + } + + // Remove head node + removeFirst() { + if (!this.head) { + return null; + } + + const removedData = this.head.data; + this.head = this.head.next; + this.size--; + return removedData; + } + + // Remove tail node + removeLast() { + if (!this.head) { + return null; + } + + // Only one node + if (!this.head.next) { + const removedData = this.head.data; + this.head = null; + this.size--; + return removedData; + } + + // Find the second-to-last node + let current = this.head; + while (current.next.next) { + current = current.next; + } + + const removedData = current.next.data; + current.next = null; + this.size--; + return removedData; + } + + // Remove node at specified position + remove(index) { + if (index < 0 || index >= this.size) { + throw new Error("Index out of bounds"); + } + + // Remove head node + if (index === 0) { + return this.removeFirst(); + } + + let current = this.head; + + // Find the node before the one to be removed + for (let i = 0; i < index - 1; i++) { + current = current.next; + } + + const removedData = current.next.data; + current.next = current.next.next; + this.size--; + return removedData; + } + + // 删除指定值的第一个节点 + removeByValue(data) { + if (!this.head) { + return false; + } + + // 如果头节点就是要删除的节点 + if (this.head.data === data) { + this.head = this.head.next; + this.size--; + return true; + } + + let current = this.head; + while (current.next && current.next.data !== data) { + current = current.next; + } + + // 找到了要删除的节点 + if (current.next) { + current.next = current.next.next; + this.size--; + return true; + } + + return false; // 未找到 + } + + // 查找元素 + indexOf(data) { + let current = this.head; + let index = 0; + + while (current) { + if (current.data === data) { + return index; + } + current = current.next; + index++; + } + + return -1; // 未找到 + } + + // 获取指定位置的元素 + get(index) { + if (index < 0 || index >= this.size) { + throw new Error("Index out of bounds"); + } + + let current = this.head; + for (let i = 0; i < index; i++) { + current = current.next; + } + + return current.data; + } + + // 检查链表是否包含指定元素 + contains(data) { + return this.indexOf(data) !== -1; + } + + // 获取链表长度 + length() { + return this.size; + } + + // 检查链表是否为空 + isEmpty() { + return this.size === 0; + } + + // 清空链表 + clear() { + this.head = null; + this.size = 0; + } + + // 转换为数组 + toArray() { + const result = []; + let current = this.head; + + while (current) { + result.push(current.data); + current = current.next; + } + + return result; + } + + // 遍历链表 + forEach(callback) { + let current = this.head; + let index = 0; + + while (current) { + callback(current.data, index); + current = current.next; + index++; + } + } + + // 反转链表 + reverse() { + let prev = null; + let current = this.head; + let next = null; + + while (current) { + next = current.next; // 保存下一个节点 + current.next = prev; // 反转指针 + prev = current; // 移动 prev + current = next; // 移动 current + } + + this.head = prev; + } + + // 打印链表 + toString() { + if (!this.head) { + return "Empty list"; + } + + const elements = []; + let current = this.head; + + while (current) { + elements.push(current.data); + current = current.next; + } + + return elements.join(" -> "); + } +} +``` + +## 使用示例 + +```javascript +// 创建链表 +const list = new SinglyLinkedList(); + +// 添加元素 +list.append(1); +list.append(2); +list.append(3); +list.prepend(0); +console.log(list.toString()); // "0 -> 1 -> 2 -> 3" + +// 插入元素 +list.insert(2, 1.5); +console.log(list.toString()); // "0 -> 1 -> 1.5 -> 2 -> 3" + +// 查找元素 +console.log(list.indexOf(2)); // 3 +console.log(list.get(1)); // 1 +console.log(list.contains(3)); // true + +// 删除元素 +list.remove(0); // 删除索引 0 的元素 +list.removeByValue(1.5); // 删除值为 1.5 的元素 +console.log(list.toString()); // "1 -> 2 -> 3" + +// 反转链表 +list.reverse(); +console.log(list.toString()); // "3 -> 2 -> 1" + +// 遍历链表 +list.forEach((data, index) => { + console.log(`Index ${index}: ${data}`); +}); +``` + +## Key Algorithm Details + +### 1. Pointer Changes in Insert Operation + +``` +Before insertion: A -> B -> C +Insert X between A and B: + +Step 1: newNode.next = A.next + A -> B -> C + X ----↗ + +Step 2: A.next = newNode + A -> X -> B -> C +``` + +### 2. Pointer Changes in Delete Operation + +``` +Before deletion: A -> B -> C -> D +Delete B: + +Step 1: Find B's predecessor node A +Step 2: A.next = B.next + A -----> C -> D + (B is skipped, waiting for garbage collection) +``` + +### 3. Reverse Algorithm Details + +```javascript +// Reverse process illustration +// Initial: 1 -> 2 -> 3 -> null +// Target: null <- 1 <- 2 <- 3 + +function reverse(head) { + let prev = null; + let current = head; + + while (current !== null) { + let next = current.next; // Save next node + current.next = prev; // Reverse current node's pointer + prev = current; // prev moves forward + current = next; // current moves forward + } + + return prev; // prev now points to the new head node +} +``` + +## Common Interview Questions + +### 1. 检测链表中的环 + +```javascript +function hasCycle(head) { + if (!head || !head.next) return false; + + let slow = head; + let fast = head; + + while (fast && fast.next) { + slow = slow.next; + fast = fast.next.next; + + if (slow === fast) { + return true; // 发现环 + } + } + + return false; +} +``` + +### 2. 找到链表的中点 + +```javascript +function findMiddle(head) { + if (!head) return null; + + let slow = head; + let fast = head; + + while (fast.next && fast.next.next) { + slow = slow.next; + fast = fast.next.next; + } + + return slow; +} +``` + +### 3. 合并两个有序链表 + +```javascript +function mergeTwoLists(l1, l2) { + const dummy = new ListNode(0); + let current = dummy; + + while (l1 && l2) { + if (l1.data <= l2.data) { + current.next = l1; + l1 = l1.next; + } else { + current.next = l2; + l2 = l2.next; + } + current = current.next; + } + + // 连接剩余的节点 + current.next = l1 || l2; + + return dummy.next; +} +``` + +## Performance Optimization Tips + +### 1. Tail Pointer Optimization + +```javascript +class OptimizedSinglyLinkedList { + constructor() { + this.head = null; + this.tail = null; // 维护尾指针 + this.size = 0; + } + + append(data) { + const newNode = new ListNode(data); + + if (!this.head) { + this.head = this.tail = newNode; + } else { + this.tail.next = newNode; + this.tail = newNode; + } + + this.size++; + } + + // 现在 append 操作是 O(1) 而不是 O(n) +} +``` + +### 2. Sentinel Node Optimization + +```javascript +class SentinelLinkedList { + constructor() { + this.sentinel = new ListNode(null); // Sentinel node + this.sentinel.next = null; + this.size = 0; + } + + // With sentinel node, many operation edge case handling becomes simpler + prepend(data) { + const newNode = new ListNode(data); + newNode.next = this.sentinel.next; + this.sentinel.next = newNode; + this.size++; + } +} +``` + +## Practical Application Scenarios + +### 1. Implement Stack + +```javascript +class Stack { + constructor() { + this.list = new SinglyLinkedList(); + } + + push(item) { + this.list.prepend(item); + } + + pop() { + return this.list.removeFirst(); + } + + peek() { + return this.list.isEmpty() ? null : this.list.get(0); + } + + isEmpty() { + return this.list.isEmpty(); + } +} +``` + +### 2. Implement Queue + +```javascript +class Queue { + constructor() { + this.head = null; + this.tail = null; + } + + enqueue(item) { + const newNode = new ListNode(item); + if (!this.tail) { + this.head = this.tail = newNode; + } else { + this.tail.next = newNode; + this.tail = newNode; + } + } + + dequeue() { + if (!this.head) return null; + + const item = this.head.data; + this.head = this.head.next; + if (!this.head) this.tail = null; + + return item; + } +} +``` + +## Important Notes + +1. **Null Pointer Checks**: Always check if nodes are null +2. **Edge Cases**: Pay special attention to empty lists and single-node situations +3. **Memory Management**: In languages with manual memory management, remember to free deleted nodes +4. **Pointer Operation Order**: Pay attention to the order of pointer modifications during insertion and deletion + +## Summary + +Singly linked lists are the foundation for understanding linked list data structures. Although they are not as efficient as arrays for random access, they excel in dynamic insertion and deletion operations. Mastering the implementation and operations of singly linked lists is essential for learning more complex data structures. + +In the next section, we will learn about doubly linked lists and see how they provide more flexibility by adding reverse pointers. diff --git a/app/docs/computer-science/data-structures/linked-list/index.mdx b/app/docs/computer-science/data-structures/linked-list/index.mdx new file mode 100644 index 0000000..f87e3ac --- /dev/null +++ b/app/docs/computer-science/data-structures/linked-list/index.mdx @@ -0,0 +1,239 @@ +--- +title: "Linked List" +description: "Basic concepts, types, and application scenarios of linked lists" +date: "2024-01-06" +tags: + - linked-list + - pointers + - dynamic-data-structure +--- + +# Linked List + +A linked list is a linear data structure where elements are not stored in contiguous memory locations, but are linked together through pointers. Each element (called a node) contains data and a pointer to the next node. + +## Basic Concepts + +### Node Structure +``` +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ data | next │───▶│ data | next │───▶│ data | null │ +└─────────────┘ └─────────────┘ └─────────────┘ + Node 1 Node 2 Node 3 +``` + +Each node contains: +- **Data field (data)**: Stores the actual data +- **Pointer field (next)**: Points to the next node + +### Linked List vs Array + +| Feature | Array | Linked List | +|---------|-------|-------------| +| Memory Layout | Contiguous | Scattered | +| Access Method | Random access O(1) | Sequential access O(n) | +| Insert/Delete | O(n) | O(1) | +| Memory Overhead | Low | High (extra pointers) | +| Cache Friendliness | Good | Poor | + +## Linked List Types + +### Singly Linked List +- [Singly Linked List Details](/computer-science/data-structures/linked-list/singly-linked-list) +- Each node has only one pointer to the next node +- Can only traverse from head to tail in one direction + +### Doubly Linked List +- [Doubly Linked List Details](/computer-science/data-structures/linked-list/doubly-linked-list) +- Each node has two pointers: prev and next +- Can traverse in both directions + +### Circular Linked List +- The last node points to the first node +- Forms a circular structure + +## Basic Operations + +### Create Node +```javascript +class ListNode { + constructor(data) { + this.data = data; + this.next = null; + } +} +``` + +### Traverse Linked List +```javascript +function traverse(head) { + let current = head; + while (current !== null) { + console.log(current.data); + current = current.next; + } +} +``` + +### Search Element +```javascript +function search(head, target) { + let current = head; + let index = 0; + + while (current !== null) { + if (current.data === target) { + return index; + } + current = current.next; + index++; + } + + return -1; // Not found +} +``` + +## Time Complexity Analysis + +| Operation | Time Complexity | Description | +|-----------|----------------|-------------| +| Access | O(n) | Need to traverse from head | +| Search | O(n) | Need to traverse and search | +| Insert (head) | O(1) | Directly modify head pointer | +| Insert (tail) | O(n) | Need to find tail node | +| Insert (known position) | O(1) | Directly modify pointers | +| Delete (head) | O(1) | Directly modify head pointer | +| Delete (known node) | O(1) | Directly modify pointers | +| Delete (by value) | O(n) | Need to search first | + +## Advantages and Disadvantages + +### Advantages +1. **Dynamic Size**: Can dynamically grow and shrink at runtime +2. **Efficient Insert/Delete**: Insert/delete at known position is O(1) +3. **Memory Efficiency**: Only allocate memory when needed +4. **Flexibility**: Can implement complex data structures + +### Disadvantages +1. **Extra Memory Overhead**: Each node needs to store pointers +2. **No Random Access**: Cannot directly access the i-th element +3. **Poor Cache Performance**: Nodes are not contiguous in memory +4. **Pointer Management**: Prone to memory leaks or dangling pointers + +## Application Scenarios + +### Suitable Cases +- **Frequent Insert/Delete**: Especially in the middle of the list +- **Unknown Size**: Data volume changes greatly at runtime +- **Implement Other Structures**: Such as stacks, queues, adjacency lists for graphs +- **Undo Operations**: Editor's undo functionality + +### Unsuitable Cases +- **Need Random Access**: Frequently access elements by index +- **Memory Sensitive**: Strict memory usage requirements +- **Cache Sensitive**: Need high-performance sequential access + +## Practical Application Examples + +### 1. Music Playlist +```javascript +class Song { + constructor(title, artist) { + this.title = title; + this.artist = artist; + this.next = null; + } +} + +class Playlist { + constructor() { + this.head = null; + this.current = null; + } + + addSong(title, artist) { + const newSong = new Song(title, artist); + if (!this.head) { + this.head = newSong; + this.current = newSong; + } else { + let last = this.head; + while (last.next) { + last = last.next; + } + last.next = newSong; + } + } + + nextSong() { + if (this.current && this.current.next) { + this.current = this.current.next; + return this.current; + } + return null; + } +} +``` + +### 2. Browser History +```javascript +class HistoryEntry { + constructor(url, title) { + this.url = url; + this.title = title; + this.next = null; + } +} + +class BrowserHistory { + constructor() { + this.head = null; + this.maxSize = 100; + this.size = 0; + } + + visit(url, title) { + const entry = new HistoryEntry(url, title); + entry.next = this.head; + this.head = entry; + this.size++; + + // Limit history size + if (this.size > this.maxSize) { + this.removeLast(); + } + } + + getHistory() { + const history = []; + let current = this.head; + while (current) { + history.push({ + url: current.url, + title: current.title + }); + current = current.next; + } + return history; + } +} +``` + +## Learning Suggestions + +1. **Start from Basics**: First master the basic operations of singly linked lists +2. **Visualize with Diagrams**: Use diagrams to understand pointer changes +3. **Watch Edge Cases**: Special handling for empty lists, single nodes, head/tail nodes +4. **Practice Pointer Operations**: Master pointer CRUD operations +5. **Comparative Learning**: Compare with arrays to understand each other's use cases + +## Next Steps + +We recommend learning in the following order: + +1. [Singly Linked List](/computer-science/data-structures/linked-list/singly-linked-list) - Master basic concepts and operations +2. [Doubly Linked List](/computer-science/data-structures/linked-list/doubly-linked-list) - Understand the advantages of bidirectional pointers +3. Circular Linked List - Learn about special linked list variants +4. Advanced Linked List Applications - Such as LRU cache, skip lists, etc. + +Mastering linked lists is essential for understanding more complex data structures (like trees and graphs)! diff --git a/app/docs/computer-science/index.mdx b/app/docs/computer-science/index.mdx new file mode 100644 index 0000000..2a0ed73 --- /dev/null +++ b/app/docs/computer-science/index.mdx @@ -0,0 +1,37 @@ +--- +title: "Computer Science" +description: "Computer Science Knowledge Collection" +date: "2024-01-01" +tags: + - computer-science + - overview +--- + +# Computer Science + +Welcome to the Computer Science Knowledge Base! Here we collect core concepts and in-depth analysis from various fields of computer science. + +## Main Content + +### Data Structures and Algorithms +- [Data Structures Fundamentals](/computer-science/data-structures) +- Common Algorithm Analysis +- Complexity Theory + +### Programming Languages +- Programming Paradigms +- Language Design Principles +- Compiler Theory + +## Learning Suggestions + +We recommend learning in the following order: + +1. First master basic data structures +2. Understand implementations of common algorithms +3. Learn algorithm complexity analysis +4. Dive into advanced topics in specific domains + +--- + +*This knowledge base is maintained by a student community. Contributions are welcome!* diff --git a/contentlayer.config.ts b/contentlayer.config.ts index 6e0690d..1ee4f46 100644 --- a/contentlayer.config.ts +++ b/contentlayer.config.ts @@ -1,29 +1,96 @@ -import { defineDocumentType, makeSource } from 'contentlayer/source-files' -import remarkGfm from 'remark-gfm' -import rehypeSlug from 'rehype-slug' -import rehypeAutolinkHeadings from 'rehype-autolink-headings' - -export const Doc = defineDocumentType(() => ({ - name: 'Doc', - filePathPattern: `**/*.md?(x)`, - contentType: 'mdx', - fields: { - title: { type: 'string', required: true }, - description: { type: 'string' }, - date: { type: 'date' }, - tags: { type: 'list', of: { type: 'string' } }, - }, - computedFields: { - slug: { type: 'string', resolve: (d) => d._raw.flattenedPath }, - }, -})) - -export default makeSource({ - contentDirPath: 'app/docs', - documentTypes: [Doc], - mdx: { - remarkPlugins: [remarkGfm], - rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: 'wrap' }]], - }, - disableImportAliasWarning: true, -}) +import { defineDocumentType, makeSource } from 'contentlayer/source-files' +// import remarkGfm from 'remark-gfm' +import rehypeSlug from 'rehype-slug' +import rehypeAutolinkHeadings from 'rehype-autolink-headings' + +export const Doc = defineDocumentType(() => ({ + name: 'Doc', + filePathPattern: `**/*.md?(x)`, + contentType: 'mdx', + fields: { + title: { type: 'string', required: true }, + description: { type: 'string' }, + date: { type: 'date' }, + tags: { type: 'list', of: { type: 'string' } }, + }, + computedFields: { + slug: { + type: 'string', + resolve: (doc) => { + // Get the flattened path without extension + let path = doc._raw.flattenedPath + + // Handle index files - remove '/index' from the end + if (path.endsWith('/index')) { + path = path.replace('/index', '') + } + + // Remove numeric prefixes from the last segment + const segments = path.split('/') + const lastSegment = segments[segments.length - 1] + if (lastSegment && /^\d+-/.test(lastSegment)) { + segments[segments.length - 1] = lastSegment.replace(/^\d+-/, '') + } + + return segments.join('/') + } + }, + slugAsParams: { + type: 'string', + resolve: (doc) => { + // Same logic as slug, but explicitly for Next.js params + let path = doc._raw.flattenedPath + + if (path.endsWith('/index')) { + path = path.replace('/index', '') + } + + const segments = path.split('/') + const lastSegment = segments[segments.length - 1] + if (lastSegment && /^\d+-/.test(lastSegment)) { + segments[segments.length - 1] = lastSegment.replace(/^\d+-/, '') + } + + return segments.join('/') + } + }, + order: { + type: 'number', + resolve: (doc) => { + const filename = doc._raw.sourceFileName + + // Handle index files - always order them first (0) + if (filename === 'index.mdx' || filename === 'index.md') { + return 0 + } + + // Extract numeric prefix from filename + const match = filename.match(/^(\d+)-/) + if (match) { + return parseInt(match[1], 10) + } + + // No numeric prefix - order at the end + return 99 + } + }, + level: { + type: 'number', + resolve: (doc) => { + // Count the number of path segments to determine nesting level + const segments = doc._raw.flattenedPath.split('/') + return segments.length + } + } + }, +})) + +export default makeSource({ + contentDirPath: 'app/docs', + documentTypes: [Doc], + mdx: { + remarkPlugins: [], // 暂时移除 remarkGfm 以解决兼容性问题 + rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: 'wrap' }]], + }, + disableImportAliasWarning: true, +}) From 5ffcb2357ed22b7d17d4f5e476981a1f04797068 Mon Sep 17 00:00:00 2001 From: Crokily Date: Fri, 12 Sep 2025 22:43:45 +1000 Subject: [PATCH 6/8] docs: Revise CONTRIBUTING.md and README.md for clarity, structure, and bilingual support --- CONTRIBUTING.md | 773 +++++++++++++++++++++++++++++++++++++++++++++++- README.md | 269 +++++++++++++++-- 2 files changed, 1009 insertions(+), 33 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b6559a..547438f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,438 @@ # Contributing Guide -感谢你对 **Involution Hell Docs** 的兴趣! -这是一个基于 **Next.js + Contentlayer** 的开源文档站点,内容来自 `docs/` 文件夹。 -欢迎提交 Pull Request 或 Issue。 +Thank you for your interest in **Involution Hell Docs**! +This is an open-source documentation site built with **Next.js + Contentlayer**, with content stored in the `docs/` folder. +We welcome Pull Requests and Issues! --- +## 🚀 Development Environment + +### 1. Clone Repository + +```bash +git clone https://github.com/involutionhell/involutionhell.github.io.git +cd involutionhell.github.io +``` + +### 2. Install Dependencies + +We use **pnpm** as our package manager: + +```bash +pnpm install +``` + +If you don't have pnpm installed: + +```bash +npm install -g pnpm +``` + +### 3. Local Development + +Run the development server: + +```bash +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) in your browser. + +Changes to `.md` or `.mdx` files in the `docs/` folder will auto-update. + +--- + +## 📚 Content Standards + +All documentation is stored in the `docs/` directory. +Each document needs a Frontmatter header, for example: + +```md +--- +title: Hello World +description: Brief description +date: "2025-09-11" +tags: + - intro +--- + +# Hello World + +This is the main content. +``` + +**Required fields:** +* **title**: Required, document title + +**Optional fields:** +* **description**: Brief description +* **date**: Publication date +* **tags**: Tag list + +--- + +## 📁 Directory Structure + +Our documentation follows a hierarchical **"Folder as a Book"** structure that automatically generates URLs and navigation. + +### Current Structure + +``` +📂 docs/ +├── 📂 computer-science/ # Computer Science +│ ├── 📄 index.mdx # Overview +│ └── 📂 data-structures/ # Data Structures +│ ├── 📄 index.mdx # Overview +│ ├── 📂 array/ # Arrays +│ │ ├── 📄 index.mdx # Overview +│ │ ├── 📄 01-static-array.mdx # Static Arrays +│ │ └── 📄 02-dynamic-array.mdx # Dynamic Arrays +│ └── 📂 linked-list/ # Linked Lists +│ ├── 📄 index.mdx # Overview +│ └── 📄 01-singly-linked-list.mdx # Singly Linked List +``` + +### URL Generation + +The file structure automatically generates clean URLs: + +- `docs/computer-science/index.mdx` → `/computer-science` +- `docs/computer-science/data-structures/array/01-static-array.mdx` → `/computer-science/data-structures/array/static-array` + +### Naming Conventions + +**Folders:** +- Use `kebab-case` for folder names: `computer-science`, `data-structures` +- Each topic folder should have an `index.mdx` file as the overview + +**Files:** +- Use `kebab-case` for file names: `static-array.mdx` +- Use numeric prefixes for ordering: `01-`, `02-` +- The prefix is removed from the final URL automatically + +--- + +## ✍️ Adding New Articles + +### Step 1: Choose Location + +Decide where your article fits in the existing structure: + +```bash +# Example: Adding a new data structures topic +docs/computer-science/data-structures/new-topic/ + +# Example: Adding an article to existing topic +docs/computer-science/data-structures/array/03-new-array-type.mdx +``` + +### Step 2: Create the File + +Create a new `.mdx` file with proper Frontmatter: + +```bash +# Create directory if needed +mkdir -p docs/computer-science/data-structures/new-topic + +# Create the file +touch docs/computer-science/data-structures/new-topic/index.mdx +``` + +### Step 3: Write Content + +Write your article using Markdown/MDX: + +```mdx +--- +title: "Your Article Title" +description: "Brief description of your article" +date: "2024-01-15" +tags: + - your-topic + - another-tag +--- + +# Your Article Title + +## Introduction + +Your content here... + +## Section 1 + +More content... + +## Code Examples + +```javascript +// Your code here +function example() { + return "Hello World!"; +} +``` + +## Conclusion + +Summary of your article... +``` + +### Step 4: Test Your Changes + +Validate your content with Contentlayer: + +```bash +pnpm check:content +``` + +This command will: +- Validate your Frontmatter syntax +- Check for any MDX errors +- Generate the content for preview + +### Step 5: Preview Locally + +Start the development server and preview your changes: + +```bash +pnpm dev +``` + +Visit `http://localhost:3000` to see your new content. + +### Step 6: Submit PR + +1. Commit your changes: + ```bash + git add . + git commit -m "Add: New article about [topic]" + ``` + +2. Push to your fork: + ```bash + git push origin feat/your-article + ``` + +3. Create a Pull Request + +--- + +## 📝 Writing Guidelines + +### Content Quality + +- **Accuracy**: Ensure technical accuracy +- **Clarity**: Write clear, understandable explanations +- **Completeness**: Cover topics thoroughly +- **Examples**: Include practical code examples +- **Updates**: Keep content current + +### Markdown Best Practices + +- Use proper heading hierarchy (h1 → h2 → h3) +- Include code blocks with syntax highlighting +- Use tables for comparisons +- Add alt text to images +- Use links to reference related content + +### Code Examples + +```javascript +// ✅ Good: Clear, commented code +function binarySearch(arr, target) { + let left = 0; + let right = arr.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (arr[mid] === target) { + return mid; // Found target + } else if (arr[mid] < target) { + left = mid + 1; // Search right half + } else { + right = mid - 1; // Search left half + } + } + + return -1; // Target not found +} +``` + +### Language Style + +- **English**: Use clear, professional English +- **Chinese**: Use formal, academic Chinese when needed +- **Technical Terms**: Use standard technical terminology +- **Consistency**: Maintain consistent terminology throughout + +--- + +## 🏗️ Build and Export + +### Build (Generate .next) + +```bash +pnpm build +``` + +This creates an optimized production build in the `.next` folder. + +### Static Export (Generate /out directory) + +```bash +pnpm export +``` + +The exported `/out` directory contains the static site, ready for deployment to GitHub Pages. + +--- + +## 🚢 Deployment + +This repository is configured with **GitHub Actions**. Pushing to the `main` branch will automatically build and deploy to: + +👉 [https://involutionhell.github.io/](https://involutionhell.github.io/) + +No manual operation required! + +--- + +## 🤝 How to Contribute + +### Basic Workflow + +1. Fork the repository +2. Create a new branch for your changes +3. Make your changes +4. Test your changes +5. Submit a Pull Request + +### Types of Contributions + +We welcome the following types of contributions: + +**📝 Content Contributions** +- Fix documentation content +- Add new tutorials or guides +- Translate content to other languages +- Improve existing articles + +**🐛 Bug Fixes** +- Fix typos and grammar errors +- Fix broken links +- Fix incorrect information +- Improve code examples + +**🎨 UI/UX Improvements** +- Improve page styling +- Enhance user interactions +- Improve mobile responsiveness +- Add new features to the UI + +**🛠️ Technical Improvements** +- Improve build process +- Add new scripts or tools +- Optimize performance +- Improve accessibility + +--- + +## 📋 Pull Request Guidelines + +### PR Title Format + +Please use one of the following formats for your PR title: + +``` +Add: New article about [topic] # 添加新文章 +Fix: Typo in [file] # 修复错误 +Update: Improve [feature] # 更新改进 +Docs: Update contribution guidelines # 文档更新 +Feat: Add [new feature] # 新功能 +``` + +### PR Description + +A good PR description should include: + +1. **What changes were made?** +2. **Why were these changes needed?** +3. **How were the changes tested?** +4. **Any breaking changes?** + +### Example PR Description + +```markdown +## What +Added a new article about dynamic programming algorithms. + +## Why +Students need better resources for understanding dynamic programming concepts. + +## How +- Created new MDX file with comprehensive examples +- Tested content generation with `pnpm check:content` +- Verified rendering on local development server + +## Testing +- Contentlayer validation passed +- No linting errors +- Previewed locally at `/computer-science/algorithms/dynamic-programming` +``` + +--- + +## 🔄 Code Review Process + +1. **Automated Checks** + - GitHub Actions will run automated tests + - Contentlayer validation will check your content + - Linting will check code quality + +2. **Peer Review** + - At least one maintainer will review your PR + - Reviewers may request changes + - You can update your PR based on feedback + +3. **Merge** + - Once approved, a maintainer will merge your PR + - Your contribution will be automatically deployed + +--- + +## 📞 Getting Help + +If you need help with contributing: + +- **📧 Issues**: Open an issue for questions or bugs +- **💬 Discussions**: Use GitHub Discussions for general questions +- **📖 Documentation**: Check this CONTRIBUTING.md file +- **👥 Community**: Join our community discussions + +--- + +## 🎉 Recognition + +Contributors will be: +- Listed in the repository contributors +- Mentioned in release notes for significant contributions +- Recognized in our documentation + +--- + +## 📜 Code of Conduct + +Please be respectful and inclusive in all interactions. We follow a code of conduct to ensure a positive community experience. + +--- + +Thank you for contributing to Involution Hell Docs! 🎉 + +--- + +## 中文版本 / Chinese Version + ## 🚀 开发环境 ### 1. 克隆仓库 @@ -62,10 +489,209 @@ tags: 这是正文内容。 ``` +**必填字段:** * **title**: 必填,文档标题 -* **description**: 可选,简短说明 -* **date**: 可选,发布日期 -* **tags**: 可选,标签列表 + +**可选字段:** +* **description**: 简短说明 +* **date**: 发布日期 +* **tags**: 标签列表 + +--- + +## 📁 目录结构 + +我们的文档采用分层式的 **"Folder as a Book"** 结构,会自动生成 URL 和导航。 + +### 当前结构 + +``` +📂 docs/ +├── 📂 computer-science/ # 计算机科学 +│ ├── 📄 index.mdx # 概述 +│ └── 📂 data-structures/ # 数据结构 +│ ├── 📄 index.mdx # 概述 +│ ├── 📂 array/ # 数组 +│ │ ├── 📄 index.mdx # 概述 +│ │ ├── 📄 01-static-array.mdx # 静态数组 +│ │ └── 📄 02-dynamic-array.mdx # 动态数组 +│ └── 📂 linked-list/ # 链表 +│ ├── 📄 index.mdx # 概述 +│ └── 📄 01-singly-linked-list.mdx # 单向链表 +``` + +### URL 生成 + +文件结构会自动生成简洁的 URL: + +- `docs/computer-science/index.mdx` → `/computer-science` +- `docs/computer-science/data-structures/array/01-static-array.mdx` → `/computer-science/data-structures/array/static-array` + +### 命名约定 + +**文件夹:** +- 使用 `kebab-case` 命名: `computer-science`, `data-structures` +- 每个主题文件夹应该有一个 `index.mdx` 文件作为概述 + +**文件:** +- 使用 `kebab-case` 命名: `static-array.mdx` +- 使用数字前缀排序: `01-`, `02-` +- 前缀会自动从最终 URL 中移除 + +--- + +## ✍️ 添加新文章 + +### 步骤1:选择位置 + +确定你的文章在现有结构中的位置: + +```bash +# 示例:添加新的数据结构主题 +docs/computer-science/data-structures/new-topic/ + +# 示例:为现有主题添加文章 +docs/computer-science/data-structures/array/03-new-array-type.mdx +``` + +### 步骤2:创建文件 + +创建新的 `.mdx` 文件,并包含正确的 Frontmatter: + +```bash +# 如需要创建目录 +mkdir -p docs/computer-science/data-structures/new-topic + +# 创建文件 +touch docs/computer-science/data-structures/new-topic/index.mdx +``` + +### 步骤3:编写内容 + +使用 Markdown/MDX 编写文章: + +```mdx +--- +title: "文章标题" +description: "文章简短描述" +date: "2024-01-15" +tags: + - your-topic + - another-tag +--- + +# 文章标题 + +## 引言 + +这里是内容... + +## 第一节 + +更多内容... + +## 代码示例 + +```javascript +// 你的代码 +function example() { + return "Hello World!"; +} +``` + +## 总结 + +文章总结... +``` + +### 步骤4:测试修改 + +使用 Contentlayer 验证内容: + +```bash +pnpm check:content +``` + +此命令将: +- 验证 Frontmatter 语法 +- 检查 MDX 错误 +- 生成预览内容 + +### 步骤5:本地预览 + +启动开发服务器并预览修改: + +```bash +pnpm dev +``` + +访问 `http://localhost:3000` 查看新内容。 + +### 步骤6:提交 PR + +1. 提交修改: + ```bash + git add . + git commit -m "Add: New article about [topic]" + ``` + +2. 推送到你的 fork: + ```bash + git push origin feat/your-article + ``` + +3. 创建 Pull Request + +--- + +## 📝 写作指南 + +### 内容质量 + +- **准确性**:确保技术准确性 +- **清晰性**:编写清晰易懂的解释 +- **完整性**:全面覆盖主题 +- **示例**:包含实际代码示例 +- **更新**:保持内容更新 + +### Markdown 最佳实践 + +- 使用正确的标题层次结构 (h1 → h2 → h3) +- 包含带有语法高亮的代码块 +- 使用表格进行比较 +- 为图片添加替代文本 +- 使用链接引用相关内容 + +### 代码示例 + +```javascript +// ✅ 好的做法:清晰、有注释的代码 +function binarySearch(arr, target) { + let left = 0; + let right = arr.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (arr[mid] === target) { + return mid; // 找到目标 + } else if (arr[mid] < target) { + left = mid + 1; // 搜索右半部分 + } else { + right = mid - 1; // 搜索左半部分 + } + } + + return -1; // 未找到目标 +} +``` + +### 语言风格 + +- **英文**:使用清晰、专业的英文 +- **中文**:在需要时使用正式的学术中文 +- **技术术语**:使用标准技术术语 +- **一致性**:在整个文档中保持一致的术语 --- @@ -77,13 +703,15 @@ tags: pnpm build ``` +这会在 `.next` 文件夹中创建优化的生产构建。 + ### 静态导出(生成 /out 目录) ```bash pnpm export ``` -导出后的 `/out` 就是静态站点,可直接部署到 GitHub Pages。 +导出后的 `/out` 目录包含静态站点,可直接部署到 GitHub Pages。 --- @@ -99,12 +727,131 @@ pnpm export ## 🤝 如何贡献 +### 基本工作流程 + 1. Fork 本仓库 -2. 在新分支进行修改 -3. 提交 PR +2. 为修改创建新分支 +3. 进行修改 +4. 测试修改 +5. 提交 PR + +### 贡献类型 + +我们欢迎以下类型的贡献: + +**📝 内容贡献** +- 修正文档内容 +- 添加新的教程或指南 +- 将内容翻译成其他语言 +- 改进现有文章 + +**🐛 错误修复** +- 修复拼写和语法错误 +- 修复损坏的链接 +- 修复错误信息 +- 改进代码示例 + +**🎨 UI/UX 改进** +- 改进页面样式 +- 增强用户交互 +- 改进移动端响应性 +- 为 UI 添加新功能 + +**🛠️ 技术改进** +- 改进构建过程 +- 添加新的脚本或工具 +- 优化性能 +- 改进可访问性 + +--- + +## 📋 PR 指南 + +### PR 标题格式 + +请使用以下格式之一作为 PR 标题: + +``` +Add: New article about [topic] # 添加新文章 +Fix: Typo in [file] # 修复错误 +Update: Improve [feature] # 更新改进 +Docs: Update contribution guidelines # 文档更新 +Feat: Add [new feature] # 新功能 +``` -我们欢迎以下贡献: +### PR 描述 + +好的 PR 描述应该包括: + +1. **做了什么修改?** +2. **为什么需要这些修改?** +3. **如何测试这些修改?** +4. **有破坏性更改吗?** + +### PR 描述示例 + +```markdown +## What +Added a new article about dynamic programming algorithms. + +## Why +Students need better resources for understanding dynamic programming concepts. + +## How +- Created new MDX file with comprehensive examples +- Tested content generation with `pnpm check:content` +- Verified rendering on local development server + +## Testing +- Contentlayer validation passed +- No linting errors +- Previewed locally at `/computer-science/algorithms/dynamic-programming` +``` + +--- + +## 🔄 代码审查流程 + +1. **自动检查** + - GitHub Actions 将运行自动化测试 + - Contentlayer 将验证你的内容 + - Linting 将检查代码质量 + +2. **同行评审** + - 至少一位维护者将审查你的 PR + - 审阅者可能会要求修改 + - 你可以根据反馈更新你的 PR + +3. **合并** + - 一旦批准,维护者将合并你的 PR + - 你的贡献将自动部署 + +--- + +## 📞 获取帮助 + +如果你在贡献过程中需要帮助: + +- **📧 Issues**:为问题或错误创建 issue +- **💬 Discussions**:使用 GitHub Discussions 进行一般性问题讨论 +- **📖 Documentation**:查看此 CONTRIBUTING.md 文件 +- **👥 Community**:加入我们的社区讨论 + +--- + +## 🎉 认可 + +贡献者将: +- 被列入仓库贡献者名单 +- 在发布说明中提及重要贡献 +- 在我们的文档中得到认可 + +--- + +## 📜 行为准则 + +请在所有互动中保持尊重和包容。我们遵循行为准则以确保积极的社区体验。 + +--- -* 修正文档内容 -* 添加新的教程或指南 -* 改进页面样式或交互 +感谢你为 Involution Hell Docs 做出的贡献!🎉 diff --git a/README.md b/README.md index ed1245b..d564c3f 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,261 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# Involution Hell Docs -## Getting Started +[![Deploy to GitHub Pages](https://github.com/involutionhell/involutionhell.github.io/actions/workflows/deploy.yml/badge.svg)](https://github.com/involutionhell/involutionhell.github.io/actions/workflows/deploy.yml) -First, run the development server: +**A modern, student-maintained knowledge base for computer science and programming.** + +[🌐 View Live Site](https://involutionhell.github.io/) | [📖 Documentation](https://involutionhell.github.io/) + +--- + +## 📋 About + +This is a collaborative documentation platform built with modern web technologies, designed to help students share and access high-quality learning materials for computer science and programming. + +## ✨ Features + +- 🚀 **Modern Tech Stack**: Next.js 15 + Contentlayer + MDX +- 🎨 **Beautiful UI**: Built with Tailwind CSS and shadcn/ui +- 🌍 **Bilingual Support**: Chinese & English content +- 📱 **Responsive Design**: Works perfectly on all devices +- ⚡ **Fast & SEO-friendly**: Static generation with optimal performance +- 🤝 **Community Driven**: Open source and collaborative + +## 🚀 Quick Start + +### Prerequisites + +- Node.js 18+ +- pnpm (recommended) + +### Installation + +```bash +# Clone the repository +git clone https://github.com/involutionhell/involutionhell.github.io.git +cd involutionhell.github.io + +# Install dependencies +pnpm install + +# Start development server +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) to see the site. + +## 📁 Project Structure + +``` +📦 involutionhell.github.io +├── 📂 app/ # Next.js App Router +│ ├── 📂 components/ # React Components +│ ├── 📂 docs/ # Documentation Content +│ │ └── 📂 computer-science/ # CS Knowledge Base +│ ├── 📄 layout.tsx # Root Layout +│ └── 📄 page.tsx # Homepage +├── 📂 contentlayer.config.ts # Contentlayer Configuration +├── 📂 tailwind.config.ts # Tailwind CSS Config +└── 📄 package.json # Dependencies & Scripts +``` + +## 🤝 Contributing + +We welcome contributions from the community! Please read our [Contributing Guide](CONTRIBUTING.md) before getting started. + +### Ways to Contribute + +- 📝 **Content**: Add new articles or improve existing ones +- 🐛 **Bug Fixes**: Report and fix issues +- 🎨 **UI/UX**: Improve design and user experience +- 🌐 **Translations**: Help with multilingual support +- 📖 **Documentation**: Improve project documentation + +### Quick Start for Contributors + +1. Fork the repository +2. Create a feature branch: `git checkout -b feat/your-feature` +3. Make your changes +4. Test your changes: `pnpm check:content` +5. Submit a Pull Request + +## 📚 Documentation Structure + +Our content follows a hierarchical "Folder as a Book" structure: + +``` +📂 docs/ +├── 📂 computer-science/ # Computer Science +│ ├── 📄 index.mdx # CS Overview +│ └── 📂 data-structures/ # Data Structures +│ ├── 📄 index.mdx # DS Overview +│ ├── 📂 array/ # Arrays +│ │ ├── 📄 index.mdx # Array Overview +│ │ ├── 📄 01-static-array.mdx +│ │ └── 📄 02-dynamic-array.mdx +│ └── 📂 linked-list/ # Linked Lists +│ ├── 📄 index.mdx # Linked List Overview +│ └── 📄 01-singly-linked-list.mdx +``` + +## 🛠️ Available Scripts + +```bash +# Development +pnpm dev # Start dev server +pnpm build # Build for production +pnpm start # Start production server + +# Content +pnpm check:content # Validate content with Contentlayer + +# Export +pnpm export # Export static site to /out +``` + +## 📄 License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +## 🙏 Acknowledgments + +- Built with [Next.js](https://nextjs.org/) +- Powered by [Contentlayer](https://contentlayer.dev/) +- Styled with [Tailwind CSS](https://tailwindcss.com/) +- UI components from [shadcn/ui](https://ui.shadcn.com/) + +Special thanks to all our contributors! 🎉 + +## 📞 Contact + +- 📧 Issues: [GitHub Issues](https://github.com/involutionhell/involutionhell.github.io/issues) +- 💬 Discussions: [GitHub Discussions](https://github.com/involutionhell/involutionhell.github.io/discussions) +- 🌟 Stars: Show your support with a ⭐ + +--- + +## 中文版本 / Chinese Version + +## 📋 关于 + +这是一个基于现代 Web 技术的协作文档平台,旨在帮助学生们分享和访问计算机科学与编程的高质量学习资料。 + +## ✨ 特性 + +- 🚀 **现代化技术栈**:Next.js 15 + Contentlayer + MDX +- 🎨 **美观界面**:基于 Tailwind CSS 和 shadcn/ui 构建 +- 🌍 **双语支持**:中英文内容 +- 📱 **响应式设计**:完美适配所有设备 +- ⚡ **快速且 SEO 友好**:静态生成,性能优化 +- 🤝 **社区驱动**:开源且协作性强 + +## 🚀 快速开始 + +### 环境要求 + +- Node.js 18+ +- pnpm(推荐) + +### 安装 ```bash -npm run dev -# or -yarn dev -# or +# 克隆仓库 +git clone https://github.com/involutionhell/involutionhell.github.io.git +cd involutionhell.github.io + +# 安装依赖 +pnpm install + +# 启动开发服务器 pnpm dev -# or -bun dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +打开浏览器访问 [http://localhost:3000](http://localhost:3000) 查看站点。 + +## 📁 项目结构 + +``` +📦 involutionhell.github.io +├── 📂 app/ # Next.js App Router +│ ├── 📂 components/ # React 组件 +│ ├── 📂 docs/ # 文档内容 +│ │ └── 📂 computer-science/ # 计算机科学知识库 +│ ├── 📄 layout.tsx # 根布局 +│ └── 📄 page.tsx # 主页 +├── 📂 contentlayer.config.ts # Contentlayer 配置 +├── 📂 tailwind.config.ts # Tailwind CSS 配置 +└── 📄 package.json # 依赖和脚本 +``` + +## 🤝 贡献 + +我们欢迎社区贡献!在开始之前,请阅读我们的[贡献指南](CONTRIBUTING.md)。 + +### 贡献方式 + +- 📝 **内容**:添加新文章或改进现有文章 +- 🐛 **错误修复**:报告并修复问题 +- 🎨 **UI/UX**:改进设计和用户体验 +- 🌐 **翻译**:帮助多语言支持 +- 📖 **文档**:改进项目文档 + +### 贡献者快速开始 + +1. Fork 本仓库 +2. 创建特性分支: `git checkout -b feat/your-feature` +3. 进行修改 +4. 测试修改: `pnpm check:content` +5. 提交 PR + +## 📚 文档结构 + +我们的内容采用分层式的"Folder as a Book"结构: + +``` +📂 docs/ +├── 📂 computer-science/ # 计算机科学 +│ ├── 📄 index.mdx # 计算机科学概述 +│ └── 📂 data-structures/ # 数据结构 +│ ├── 📄 index.mdx # 数据结构概述 +│ ├── 📂 array/ # 数组 +│ │ ├── 📄 index.mdx # 数组概述 +│ │ ├── 📄 01-static-array.mdx +│ │ └── 📄 02-dynamic-array.mdx +│ └── 📂 linked-list/ # 链表 +│ ├── 📄 index.mdx # 链表概述 +│ └── 📄 01-singly-linked-list.mdx +``` + +## 🛠️ 可用脚本 + +```bash +# 开发 +pnpm dev # 启动开发服务器 +pnpm build # 构建生产版本 +pnpm start # 启动生产服务器 + +# 内容 +pnpm check:content # 使用 Contentlayer 验证内容 + +# 导出 +pnpm export # 导出静态站点到 /out 目录 +``` + +## 📄 许可证 + +本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。 -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +## 🙏 致谢 -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +- 使用 [Next.js](https://nextjs.org/) 构建 +- 由 [Contentlayer](https://contentlayer.dev/) 驱动 +- 使用 [Tailwind CSS](https://tailwindcss.com/) 样式 +- UI 组件来自 [shadcn/ui](https://ui.shadcn.com/) -## Contributing +特别感谢我们所有的贡献者!🎉 -- **请先阅读 `CONTRIBUTING.md`(仓库根)**:包含本项目的本地开发环境、分支策略、代码规范、提交信息格式、PR 流程与评审标准等。 -- **完整贡献文档**:`CONTRIBUTING.md` -- **快速开始贡献**: - - Fork 并创建特性分支(示例:`feat/your-feature`)。 - - 遵循贡献文档完成开发与自测。 - - 提交 PR,并在描述中关联 Issue、填写变更说明与测试要点。 +## 📞 联系我们 -更多细节、注意事项与最佳实践,请务必查阅仓库根的 [`CONTRIBUTING.md`](CONTRIBUTING.md)。 +- 📧 Issues: [GitHub Issues](https://github.com/involutionhell/involutionhell.github.io/issues) +- 💬 Discussions: [GitHub Discussions](https://github.com/involutionhell/involutionhell.github.io/discussions) +- 🌟 Stars: 通过 ⭐ 表示支持 From aa3d8a786881cac5bffe73002295cdbdb6edd5e6 Mon Sep 17 00:00:00 2001 From: Crokily Date: Fri, 12 Sep 2025 23:17:14 +1000 Subject: [PATCH 7/8] docs: Update CONTRIBUTING.md and README.md for improved clarity, structure, and bilingual support --- CONTRIBUTING.md | 723 ++++++++++++++++++++++++------------------------ README.md | 254 ++++++++--------- 2 files changed, 488 insertions(+), 489 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 547438f..76a5a59 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,57 +1,51 @@ -# Contributing Guide - -Thank you for your interest in **Involution Hell Docs**! -This is an open-source documentation site built with **Next.js + Contentlayer**, with content stored in the `docs/` folder. -We welcome Pull Requests and Issues! - ---- +# 贡献指南/Contributing Guide -## 🚀 Development Environment +## 🚀 开发环境 -### 1. Clone Repository +### 1. 克隆仓库 ```bash git clone https://github.com/involutionhell/involutionhell.github.io.git cd involutionhell.github.io ``` -### 2. Install Dependencies +### 2. 安装依赖 -We use **pnpm** as our package manager: +我们使用 **pnpm** 作为包管理工具: ```bash pnpm install ``` -If you don't have pnpm installed: +如果你还没有安装 pnpm: ```bash npm install -g pnpm ``` -### 3. Local Development +### 3. 本地开发 -Run the development server: +运行开发服务器: ```bash pnpm dev ``` -Open [http://localhost:3000](http://localhost:3000) in your browser. +打开浏览器访问 [http://localhost:3000](http://localhost:3000)。 -Changes to `.md` or `.mdx` files in the `docs/` folder will auto-update. +修改 `docs/` 下的 `.md` 或 `.mdx` 文件,会自动热更新。 --- -## 📚 Content Standards +## 📚 文档规范 -All documentation is stored in the `docs/` directory. -Each document needs a Frontmatter header, for example: +所有文档放在 `docs/` 目录。 +每个文档都需要一个 Frontmatter,例如: ```md --- title: Hello World -description: Brief description +description: 简短描述 date: "2025-09-11" tags: - intro @@ -59,186 +53,186 @@ tags: # Hello World -This is the main content. +这是正文内容。 ``` -**Required fields:** -* **title**: Required, document title +**必填字段:** +* **title**: 必填,文档标题 -**Optional fields:** -* **description**: Brief description -* **date**: Publication date -* **tags**: Tag list +**可选字段:** +* **description**: 简短说明 +* **date**: 发布日期 +* **tags**: 标签列表 --- -## 📁 Directory Structure +## 📁 目录结构 -Our documentation follows a hierarchical **"Folder as a Book"** structure that automatically generates URLs and navigation. +我们的文档采用分层式的 **"Folder as a Book"** 结构,会自动生成 URL 和导航。 -### Current Structure +### 当前结构 ``` 📂 docs/ -├── 📂 computer-science/ # Computer Science -│ ├── 📄 index.mdx # Overview -│ └── 📂 data-structures/ # Data Structures -│ ├── 📄 index.mdx # Overview -│ ├── 📂 array/ # Arrays -│ │ ├── 📄 index.mdx # Overview -│ │ ├── 📄 01-static-array.mdx # Static Arrays -│ │ └── 📄 02-dynamic-array.mdx # Dynamic Arrays -│ └── 📂 linked-list/ # Linked Lists -│ ├── 📄 index.mdx # Overview -│ └── 📄 01-singly-linked-list.mdx # Singly Linked List +├── 📂 computer-science/ # 计算机科学 +│ ├── 📄 index.mdx # 概述 +│ └── 📂 data-structures/ # 数据结构 +│ ├── 📄 index.mdx # 概述 +│ ├── 📂 array/ # 数组 +│ │ ├── 📄 index.mdx # 概述 +│ │ ├── 📄 01-static-array.mdx # 静态数组 +│ │ └── 📄 02-dynamic-array.mdx # 动态数组 +│ └── 📂 linked-list/ # 链表 +│ ├── 📄 index.mdx # 概述 +│ └── 📄 01-singly-linked-list.mdx # 单向链表 ``` -### URL Generation +### URL 生成 -The file structure automatically generates clean URLs: +文件结构会自动生成简洁的 URL: - `docs/computer-science/index.mdx` → `/computer-science` - `docs/computer-science/data-structures/array/01-static-array.mdx` → `/computer-science/data-structures/array/static-array` -### Naming Conventions +### 命名约定 -**Folders:** -- Use `kebab-case` for folder names: `computer-science`, `data-structures` -- Each topic folder should have an `index.mdx` file as the overview +**文件夹:** +- 使用 `kebab-case` 命名: `computer-science`, `data-structures` +- 每个主题文件夹应该有一个 `index.mdx` 文件作为概述 -**Files:** -- Use `kebab-case` for file names: `static-array.mdx` -- Use numeric prefixes for ordering: `01-`, `02-` -- The prefix is removed from the final URL automatically +**文件:** +- 使用 `kebab-case` 命名: `static-array.mdx` +- 使用数字前缀排序: `01-`, `02-` +- 前缀会自动从最终 URL 中移除 --- -## ✍️ Adding New Articles +## ✍️ 添加新文章 -### Step 1: Choose Location +### 步骤1:选择位置 -Decide where your article fits in the existing structure: +确定你的文章在现有结构中的位置: ```bash -# Example: Adding a new data structures topic +# 示例:添加新的数据结构主题 docs/computer-science/data-structures/new-topic/ -# Example: Adding an article to existing topic +# 示例:为现有主题添加文章 docs/computer-science/data-structures/array/03-new-array-type.mdx ``` -### Step 2: Create the File +### 步骤2:创建文件 -Create a new `.mdx` file with proper Frontmatter: +创建新的 `.mdx` 文件,并包含正确的 Frontmatter: ```bash -# Create directory if needed +# 如需要创建目录 mkdir -p docs/computer-science/data-structures/new-topic -# Create the file +# 创建文件 touch docs/computer-science/data-structures/new-topic/index.mdx ``` -### Step 3: Write Content +### 步骤3:编写内容 -Write your article using Markdown/MDX: +使用 Markdown/MDX 编写文章: ```mdx --- -title: "Your Article Title" -description: "Brief description of your article" +title: "文章标题" +description: "文章简短描述" date: "2024-01-15" tags: - your-topic - another-tag --- -# Your Article Title +# 文章标题 -## Introduction +## 引言 -Your content here... +这里是内容... -## Section 1 +## 第一节 -More content... +更多内容... -## Code Examples +## 代码示例 ```javascript -// Your code here +// 你的代码 function example() { return "Hello World!"; } ``` -## Conclusion +## 总结 -Summary of your article... +文章总结... ``` -### Step 4: Test Your Changes +### 步骤4:测试修改 -Validate your content with Contentlayer: +使用 Contentlayer 验证内容: ```bash pnpm check:content ``` -This command will: -- Validate your Frontmatter syntax -- Check for any MDX errors -- Generate the content for preview +此命令将: +- 验证 Frontmatter 语法 +- 检查 MDX 错误 +- 生成预览内容 -### Step 5: Preview Locally +### 步骤5:本地预览 -Start the development server and preview your changes: +启动开发服务器并预览修改: ```bash pnpm dev ``` -Visit `http://localhost:3000` to see your new content. +访问 `http://localhost:3000` 查看新内容。 -### Step 6: Submit PR +### 步骤6:提交 PR -1. Commit your changes: +1. 提交修改: ```bash git add . git commit -m "Add: New article about [topic]" ``` -2. Push to your fork: +2. 推送到你的 fork: ```bash git push origin feat/your-article ``` -3. Create a Pull Request +3. 创建 Pull Request --- -## 📝 Writing Guidelines +## 📝 写作指南 -### Content Quality +### 内容质量 -- **Accuracy**: Ensure technical accuracy -- **Clarity**: Write clear, understandable explanations -- **Completeness**: Cover topics thoroughly -- **Examples**: Include practical code examples -- **Updates**: Keep content current +- **准确性**:确保技术准确性 +- **清晰性**:编写清晰易懂的解释 +- **完整性**:全面覆盖主题 +- **示例**:包含实际代码示例 +- **更新**:保持内容更新 -### Markdown Best Practices +### Markdown 最佳实践 -- Use proper heading hierarchy (h1 → h2 → h3) -- Include code blocks with syntax highlighting -- Use tables for comparisons -- Add alt text to images -- Use links to reference related content +- 使用正确的标题层次结构 (h1 → h2 → h3) +- 包含带有语法高亮的代码块 +- 使用表格进行比较 +- 为图片添加替代文本 +- 使用链接引用相关内容 -### Code Examples +### 代码示例 ```javascript -// ✅ Good: Clear, commented code +// ✅ 好的做法:清晰、有注释的代码 function binarySearch(arr, target) { let left = 0; let right = arr.length - 1; @@ -247,102 +241,102 @@ function binarySearch(arr, target) { const mid = Math.floor((left + right) / 2); if (arr[mid] === target) { - return mid; // Found target + return mid; // 找到目标 } else if (arr[mid] < target) { - left = mid + 1; // Search right half + left = mid + 1; // 搜索右半部分 } else { - right = mid - 1; // Search left half + right = mid - 1; // 搜索左半部分 } } - return -1; // Target not found + return -1; // 未找到目标 } ``` -### Language Style +### 语言风格 -- **English**: Use clear, professional English -- **Chinese**: Use formal, academic Chinese when needed -- **Technical Terms**: Use standard technical terminology -- **Consistency**: Maintain consistent terminology throughout +- **英文**:使用清晰、专业的英文 +- **中文**:在需要时使用正式的学术中文 +- **技术术语**:使用标准技术术语 +- **一致性**:在整个文档中保持一致的术语 --- -## 🏗️ Build and Export +## 🏗️ 构建与导出 -### Build (Generate .next) +### 构建(生成 .next) ```bash pnpm build ``` -This creates an optimized production build in the `.next` folder. +这会在 `.next` 文件夹中创建优化的生产构建。 -### Static Export (Generate /out directory) +### 静态导出(生成 /out 目录) ```bash pnpm export ``` -The exported `/out` directory contains the static site, ready for deployment to GitHub Pages. +导出后的 `/out` 目录包含静态站点,可直接部署到 GitHub Pages。 --- -## 🚢 Deployment +## 🚢 部署 -This repository is configured with **GitHub Actions**. Pushing to the `main` branch will automatically build and deploy to: +本仓库配置了 **GitHub Actions**,push 到 `main` 分支会自动构建并部署到: 👉 [https://involutionhell.github.io/](https://involutionhell.github.io/) -No manual operation required! +无需手动操作。 --- -## 🤝 How to Contribute - -### Basic Workflow +## 🤝 如何贡献 -1. Fork the repository -2. Create a new branch for your changes -3. Make your changes -4. Test your changes -5. Submit a Pull Request +### 基本工作流程 -### Types of Contributions +1. Fork 本仓库 +2. 为修改创建新分支 +3. 进行修改 +4. 测试修改 +5. 提交 PR -We welcome the following types of contributions: +### 贡献类型 -**📝 Content Contributions** -- Fix documentation content -- Add new tutorials or guides -- Translate content to other languages -- Improve existing articles +我们欢迎以下类型的贡献: -**🐛 Bug Fixes** -- Fix typos and grammar errors -- Fix broken links -- Fix incorrect information -- Improve code examples +**📝 内容贡献** +- 修正文档内容 +- 添加新的教程或指南 +- 将内容翻译成其他语言 +- 改进现有文章 -**🎨 UI/UX Improvements** -- Improve page styling -- Enhance user interactions -- Improve mobile responsiveness -- Add new features to the UI +**🐛 错误修复** +- 修复拼写和语法错误 +- 修复损坏的链接 +- 修复错误信息 +- 改进代码示例 -**🛠️ Technical Improvements** -- Improve build process -- Add new scripts or tools -- Optimize performance -- Improve accessibility +**🎨 UI/UX 改进** +- 改进页面样式 +- 增强用户交互 +- 改进移动端响应性 +- 为 UI 添加新功能 + +**🛠️ 技术改进** +- 改进构建过程 +- 添加新的脚本或工具 +- 优化性能 +- 改进可访问性 --- -## 📋 Pull Request Guidelines +## 📋 PR 指南 -### PR Title Format +### PR 标题格式 -Please use one of the following formats for your PR title: +请使用以下格式之一作为 PR 标题: ``` Add: New article about [topic] # 添加新文章 @@ -352,16 +346,16 @@ Docs: Update contribution guidelines # 文档更新 Feat: Add [new feature] # 新功能 ``` -### PR Description +### PR 描述 -A good PR description should include: +好的 PR 描述应该包括: -1. **What changes were made?** -2. **Why were these changes needed?** -3. **How were the changes tested?** -4. **Any breaking changes?** +1. **做了什么修改?** +2. **为什么需要这些修改?** +3. **如何测试这些修改?** +4. **有破坏性更改吗?** -### Example PR Description +### PR 描述示例 ```markdown ## What @@ -383,102 +377,107 @@ Students need better resources for understanding dynamic programming concepts. --- -## 🔄 Code Review Process +## 🔄 代码审查流程 -1. **Automated Checks** - - GitHub Actions will run automated tests - - Contentlayer validation will check your content - - Linting will check code quality +1. **自动检查** + - GitHub Actions 将运行自动化测试 + - Contentlayer 将验证你的内容 + - Linting 将检查代码质量 -2. **Peer Review** - - At least one maintainer will review your PR - - Reviewers may request changes - - You can update your PR based on feedback +2. **同行评审** + - 至少一位维护者将审查你的 PR + - 审阅者可能会要求修改 + - 你可以根据反馈更新你的 PR -3. **Merge** - - Once approved, a maintainer will merge your PR - - Your contribution will be automatically deployed +3. **合并** + - 一旦批准,维护者将合并你的 PR + - 你的贡献将自动部署 --- -## 📞 Getting Help +## 📞 获取帮助 -If you need help with contributing: +如果你在贡献过程中需要帮助: -- **📧 Issues**: Open an issue for questions or bugs -- **💬 Discussions**: Use GitHub Discussions for general questions -- **📖 Documentation**: Check this CONTRIBUTING.md file -- **👥 Community**: Join our community discussions +- **📧 Issues**:为问题或错误创建 issue +- **💬 Discussions**:使用 GitHub Discussions 进行一般性问题讨论 +- **📖 Documentation**:查看此 CONTRIBUTING.md 文件 +- **👥 Community**:加入我们的社区讨论 --- -## 🎉 Recognition +## 🎉 认可 -Contributors will be: -- Listed in the repository contributors -- Mentioned in release notes for significant contributions -- Recognized in our documentation +贡献者将: +- 被列入仓库贡献者名单 +- 在发布说明中提及重要贡献 +- 在我们的文档中得到认可 --- -## 📜 Code of Conduct +## 📜 行为准则 -Please be respectful and inclusive in all interactions. We follow a code of conduct to ensure a positive community experience. +请在所有互动中保持尊重和包容。我们遵循行为准则以确保积极的社区体验。 --- -Thank you for contributing to Involution Hell Docs! 🎉 +感谢你为 Involution Hell Docs 做出的贡献!🎉 ---- -## 中文版本 / Chinese Version +# Contributing Guide -## 🚀 开发环境 +Thank you for your interest in **Involution Hell Docs**! +This is an open-source documentation site built with **Next.js + Contentlayer**, with content stored in the `docs/` folder. +We welcome Pull Requests and Issues! -### 1. 克隆仓库 +--- + +## 🚀 Development Environment + +### 1. Clone Repository ```bash git clone https://github.com/involutionhell/involutionhell.github.io.git cd involutionhell.github.io ``` -### 2. 安装依赖 +### 2. Install Dependencies -我们使用 **pnpm** 作为包管理工具: +We use **pnpm** as our package manager: ```bash pnpm install ``` -如果你还没有安装 pnpm: +If you don't have pnpm installed: ```bash npm install -g pnpm ``` -### 3. 本地开发 +### 3. Local Development -运行开发服务器: +Run the development server: ```bash pnpm dev ``` -打开浏览器访问 [http://localhost:3000](http://localhost:3000)。 +Open [http://localhost:3000](http://localhost:3000) in your browser. -修改 `docs/` 下的 `.md` 或 `.mdx` 文件,会自动热更新。 +Changes to `.md` or `.mdx` files in the `docs/` folder will auto-update. --- -## 📚 文档规范 +## 📚 Content Standards -所有文档放在 `docs/` 目录。 -每个文档都需要一个 Frontmatter,例如: +All documentation is stored in the `docs/` directory. +Each document needs a Frontmatter header, for example: ```md --- title: Hello World -description: 简短描述 +description: Brief description date: "2025-09-11" tags: - intro @@ -486,186 +485,186 @@ tags: # Hello World -这是正文内容。 +This is the main content. ``` -**必填字段:** -* **title**: 必填,文档标题 +**Required fields:** +* **title**: Required, document title -**可选字段:** -* **description**: 简短说明 -* **date**: 发布日期 -* **tags**: 标签列表 +**Optional fields:** +* **description**: Brief description +* **date**: Publication date +* **tags**: Tag list --- -## 📁 目录结构 +## 📁 Directory Structure -我们的文档采用分层式的 **"Folder as a Book"** 结构,会自动生成 URL 和导航。 +Our documentation follows a hierarchical **"Folder as a Book"** structure that automatically generates URLs and navigation. -### 当前结构 +### Current Structure ``` 📂 docs/ -├── 📂 computer-science/ # 计算机科学 -│ ├── 📄 index.mdx # 概述 -│ └── 📂 data-structures/ # 数据结构 -│ ├── 📄 index.mdx # 概述 -│ ├── 📂 array/ # 数组 -│ │ ├── 📄 index.mdx # 概述 -│ │ ├── 📄 01-static-array.mdx # 静态数组 -│ │ └── 📄 02-dynamic-array.mdx # 动态数组 -│ └── 📂 linked-list/ # 链表 -│ ├── 📄 index.mdx # 概述 -│ └── 📄 01-singly-linked-list.mdx # 单向链表 +├── 📂 computer-science/ # Computer Science +│ ├── 📄 index.mdx # Overview +│ └── 📂 data-structures/ # Data Structures +│ ├── 📄 index.mdx # Overview +│ ├── 📂 array/ # Arrays +│ │ ├── 📄 index.mdx # Overview +│ │ ├── 📄 01-static-array.mdx # Static Arrays +│ │ └── 📄 02-dynamic-array.mdx # Dynamic Arrays +│ └── 📂 linked-list/ # Linked Lists +│ ├── 📄 index.mdx # Overview +│ └── 📄 01-singly-linked-list.mdx # Singly Linked List ``` -### URL 生成 +### URL Generation -文件结构会自动生成简洁的 URL: +The file structure automatically generates clean URLs: - `docs/computer-science/index.mdx` → `/computer-science` - `docs/computer-science/data-structures/array/01-static-array.mdx` → `/computer-science/data-structures/array/static-array` -### 命名约定 +### Naming Conventions -**文件夹:** -- 使用 `kebab-case` 命名: `computer-science`, `data-structures` -- 每个主题文件夹应该有一个 `index.mdx` 文件作为概述 +**Folders:** +- Use `kebab-case` for folder names: `computer-science`, `data-structures` +- Each topic folder should have an `index.mdx` file as the overview -**文件:** -- 使用 `kebab-case` 命名: `static-array.mdx` -- 使用数字前缀排序: `01-`, `02-` -- 前缀会自动从最终 URL 中移除 +**Files:** +- Use `kebab-case` for file names: `static-array.mdx` +- Use numeric prefixes for ordering: `01-`, `02-` +- The prefix is removed from the final URL automatically --- -## ✍️ 添加新文章 +## ✍️ Adding New Articles -### 步骤1:选择位置 +### Step 1: Choose Location -确定你的文章在现有结构中的位置: +Decide where your article fits in the existing structure: ```bash -# 示例:添加新的数据结构主题 +# Example: Adding a new data structures topic docs/computer-science/data-structures/new-topic/ -# 示例:为现有主题添加文章 +# Example: Adding an article to existing topic docs/computer-science/data-structures/array/03-new-array-type.mdx ``` -### 步骤2:创建文件 +### Step 2: Create the File -创建新的 `.mdx` 文件,并包含正确的 Frontmatter: +Create a new `.mdx` file with proper Frontmatter: ```bash -# 如需要创建目录 +# Create directory if needed mkdir -p docs/computer-science/data-structures/new-topic -# 创建文件 +# Create the file touch docs/computer-science/data-structures/new-topic/index.mdx ``` -### 步骤3:编写内容 +### Step 3: Write Content -使用 Markdown/MDX 编写文章: +Write your article using Markdown/MDX: ```mdx --- -title: "文章标题" -description: "文章简短描述" +title: "Your Article Title" +description: "Brief description of your article" date: "2024-01-15" tags: - your-topic - another-tag --- -# 文章标题 +# Your Article Title -## 引言 +## Introduction -这里是内容... +Your content here... -## 第一节 +## Section 1 -更多内容... +More content... -## 代码示例 +## Code Examples ```javascript -// 你的代码 +// Your code here function example() { return "Hello World!"; } ``` -## 总结 +## Conclusion -文章总结... +Summary of your article... ``` -### 步骤4:测试修改 +### Step 4: Test Your Changes -使用 Contentlayer 验证内容: +Validate your content with Contentlayer: ```bash pnpm check:content ``` -此命令将: -- 验证 Frontmatter 语法 -- 检查 MDX 错误 -- 生成预览内容 +This command will: +- Validate your Frontmatter syntax +- Check for any MDX errors +- Generate the content for preview -### 步骤5:本地预览 +### Step 5: Preview Locally -启动开发服务器并预览修改: +Start the development server and preview your changes: ```bash pnpm dev ``` -访问 `http://localhost:3000` 查看新内容。 +Visit `http://localhost:3000` to see your new content. -### 步骤6:提交 PR +### Step 6: Submit PR -1. 提交修改: +1. Commit your changes: ```bash git add . git commit -m "Add: New article about [topic]" ``` -2. 推送到你的 fork: +2. Push to your fork: ```bash git push origin feat/your-article ``` -3. 创建 Pull Request +3. Create a Pull Request --- -## 📝 写作指南 +## 📝 Writing Guidelines -### 内容质量 +### Content Quality -- **准确性**:确保技术准确性 -- **清晰性**:编写清晰易懂的解释 -- **完整性**:全面覆盖主题 -- **示例**:包含实际代码示例 -- **更新**:保持内容更新 +- **Accuracy**: Ensure technical accuracy +- **Clarity**: Write clear, understandable explanations +- **Completeness**: Cover topics thoroughly +- **Examples**: Include practical code examples +- **Updates**: Keep content current -### Markdown 最佳实践 +### Markdown Best Practices -- 使用正确的标题层次结构 (h1 → h2 → h3) -- 包含带有语法高亮的代码块 -- 使用表格进行比较 -- 为图片添加替代文本 -- 使用链接引用相关内容 +- Use proper heading hierarchy (h1 → h2 → h3) +- Include code blocks with syntax highlighting +- Use tables for comparisons +- Add alt text to images +- Use links to reference related content -### 代码示例 +### Code Examples ```javascript -// ✅ 好的做法:清晰、有注释的代码 +// ✅ Good: Clear, commented code function binarySearch(arr, target) { let left = 0; let right = arr.length - 1; @@ -674,102 +673,102 @@ function binarySearch(arr, target) { const mid = Math.floor((left + right) / 2); if (arr[mid] === target) { - return mid; // 找到目标 + return mid; // Found target } else if (arr[mid] < target) { - left = mid + 1; // 搜索右半部分 + left = mid + 1; // Search right half } else { - right = mid - 1; // 搜索左半部分 + right = mid - 1; // Search left half } } - return -1; // 未找到目标 + return -1; // Target not found } ``` -### 语言风格 +### Language Style -- **英文**:使用清晰、专业的英文 -- **中文**:在需要时使用正式的学术中文 -- **技术术语**:使用标准技术术语 -- **一致性**:在整个文档中保持一致的术语 +- **English**: Use clear, professional English +- **Chinese**: Use formal, academic Chinese when needed +- **Technical Terms**: Use standard technical terminology +- **Consistency**: Maintain consistent terminology throughout --- -## 🏗️ 构建与导出 +## 🏗️ Build and Export -### 构建(生成 .next) +### Build (Generate .next) ```bash pnpm build ``` -这会在 `.next` 文件夹中创建优化的生产构建。 +This creates an optimized production build in the `.next` folder. -### 静态导出(生成 /out 目录) +### Static Export (Generate /out directory) ```bash pnpm export ``` -导出后的 `/out` 目录包含静态站点,可直接部署到 GitHub Pages。 +The exported `/out` directory contains the static site, ready for deployment to GitHub Pages. --- -## 🚢 部署 +## 🚢 Deployment -本仓库配置了 **GitHub Actions**,push 到 `main` 分支会自动构建并部署到: +This repository is configured with **GitHub Actions**. Pushing to the `main` branch will automatically build and deploy to: 👉 [https://involutionhell.github.io/](https://involutionhell.github.io/) -无需手动操作。 +No manual operation required! --- -## 🤝 如何贡献 +## 🤝 How to Contribute -### 基本工作流程 +### Basic Workflow -1. Fork 本仓库 -2. 为修改创建新分支 -3. 进行修改 -4. 测试修改 -5. 提交 PR +1. Fork the repository +2. Create a new branch for your changes +3. Make your changes +4. Test your changes +5. Submit a Pull Request -### 贡献类型 +### Types of Contributions -我们欢迎以下类型的贡献: +We welcome the following types of contributions: -**📝 内容贡献** -- 修正文档内容 -- 添加新的教程或指南 -- 将内容翻译成其他语言 -- 改进现有文章 +**📝 Content Contributions** +- Fix documentation content +- Add new tutorials or guides +- Translate content to other languages +- Improve existing articles -**🐛 错误修复** -- 修复拼写和语法错误 -- 修复损坏的链接 -- 修复错误信息 -- 改进代码示例 +**🐛 Bug Fixes** +- Fix typos and grammar errors +- Fix broken links +- Fix incorrect information +- Improve code examples -**🎨 UI/UX 改进** -- 改进页面样式 -- 增强用户交互 -- 改进移动端响应性 -- 为 UI 添加新功能 +**🎨 UI/UX Improvements** +- Improve page styling +- Enhance user interactions +- Improve mobile responsiveness +- Add new features to the UI -**🛠️ 技术改进** -- 改进构建过程 -- 添加新的脚本或工具 -- 优化性能 -- 改进可访问性 +**🛠️ Technical Improvements** +- Improve build process +- Add new scripts or tools +- Optimize performance +- Improve accessibility --- -## 📋 PR 指南 +## 📋 Pull Request Guidelines -### PR 标题格式 +### PR Title Format -请使用以下格式之一作为 PR 标题: +Please use one of the following formats for your PR title: ``` Add: New article about [topic] # 添加新文章 @@ -779,16 +778,16 @@ Docs: Update contribution guidelines # 文档更新 Feat: Add [new feature] # 新功能 ``` -### PR 描述 +### PR Description -好的 PR 描述应该包括: +A good PR description should include: -1. **做了什么修改?** -2. **为什么需要这些修改?** -3. **如何测试这些修改?** -4. **有破坏性更改吗?** +1. **What changes were made?** +2. **Why were these changes needed?** +3. **How were the changes tested?** +4. **Any breaking changes?** -### PR 描述示例 +### Example PR Description ```markdown ## What @@ -810,48 +809,48 @@ Students need better resources for understanding dynamic programming concepts. --- -## 🔄 代码审查流程 +## 🔄 Code Review Process -1. **自动检查** - - GitHub Actions 将运行自动化测试 - - Contentlayer 将验证你的内容 - - Linting 将检查代码质量 +1. **Automated Checks** + - GitHub Actions will run automated tests + - Contentlayer validation will check your content + - Linting will check code quality -2. **同行评审** - - 至少一位维护者将审查你的 PR - - 审阅者可能会要求修改 - - 你可以根据反馈更新你的 PR +2. **Peer Review** + - At least one maintainer will review your PR + - Reviewers may request changes + - You can update your PR based on feedback -3. **合并** - - 一旦批准,维护者将合并你的 PR - - 你的贡献将自动部署 +3. **Merge** + - Once approved, a maintainer will merge your PR + - Your contribution will be automatically deployed --- -## 📞 获取帮助 +## 📞 Getting Help -如果你在贡献过程中需要帮助: +If you need help with contributing: -- **📧 Issues**:为问题或错误创建 issue -- **💬 Discussions**:使用 GitHub Discussions 进行一般性问题讨论 -- **📖 Documentation**:查看此 CONTRIBUTING.md 文件 -- **👥 Community**:加入我们的社区讨论 +- **📧 Issues**: Open an issue for questions or bugs +- **💬 Discussions**: Use GitHub Discussions for general questions +- **📖 Documentation**: Check this CONTRIBUTING.md file +- **👥 Community**: Join our community discussions --- -## 🎉 认可 +## 🎉 Recognition -贡献者将: -- 被列入仓库贡献者名单 -- 在发布说明中提及重要贡献 -- 在我们的文档中得到认可 +Contributors will be: +- Listed in the repository contributors +- Mentioned in release notes for significant contributions +- Recognized in our documentation --- -## 📜 行为准则 +## 📜 Code of Conduct -请在所有互动中保持尊重和包容。我们遵循行为准则以确保积极的社区体验。 +Please be respectful and inclusive in all interactions. We follow a code of conduct to ensure a positive community experience. --- -感谢你为 Involution Hell Docs 做出的贡献!🎉 +Thank you for contributing to Involution Hell Docs! 🎉 diff --git a/README.md b/README.md index d564c3f..7faf153 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,130 @@ +# Involution Hell 知识库 + +## 📋 关于 + +这是一个基于现代 Web 技术的协作文档平台,旨在帮助学生们分享和访问学习资料。 + +## ✨ 特性 + +- 🚀 **现代化技术栈**:Next.js 15 + Contentlayer + MDX +- 🎨 **美观界面**:基于 Tailwind CSS 和 shadcn/ui 构建 +- 🌍 **双语支持**:中英文内容 +- 📱 **响应式设计**:完美适配所有设备 +- ⚡ **快速且 SEO 友好**:静态生成,性能优化 +- 🤝 **社区驱动**:开源且协作性强 + +## 🚀 快速开始 + +### 环境要求 + +- Node.js 18+ +- pnpm(推荐) + +### 安装 + +```bash +# 克隆仓库 +git clone https://github.com/involutionhell/involutionhell.github.io.git +cd involutionhell.github.io + +# 安装依赖 +pnpm install + +# 启动开发服务器 +pnpm dev +``` + +打开浏览器访问 [http://localhost:3000](http://localhost:3000) 查看站点。 + +## 📁 项目结构 + +``` +📦 involutionhell.github.io +├── 📂 app/ # Next.js App Router +│ ├── 📂 components/ # React 组件 +│ ├── 📂 docs/ # 文档内容 +│ │ └── 📂 computer-science/ # 计算机科学知识库 +│ ├── 📄 layout.tsx # 根布局 +│ └── 📄 page.tsx # 主页 +├── 📂 contentlayer.config.ts # Contentlayer 配置 +├── 📂 tailwind.config.ts # Tailwind CSS 配置 +└── 📄 package.json # 依赖和脚本 +``` + +## 🤝 贡献 + +我们欢迎社区贡献!在开始之前,请阅读我们的[贡献指南](CONTRIBUTING.md)。 + +### 贡献方式 + +- 📝 **内容**:添加新文章或改进现有文章 +- 🐛 **错误修复**:报告并修复问题 +- 🎨 **UI/UX**:改进设计和用户体验 +- 🌐 **翻译**:帮助多语言支持 +- 📖 **文档**:改进项目文档 + +### 贡献者快速开始 + +1. Fork 本仓库 +2. 创建特性分支: `git checkout -b feat/your-feature` +3. 进行修改 +4. 测试修改: `pnpm check:content` +5. 提交 PR + +## 📚 文档结构 + +我们的内容采用分层式的"Folder as a Book"结构: + +``` +📂 docs/ +├── 📂 computer-science/ # 计算机科学 +│ ├── 📄 index.mdx # 计算机科学概述 +│ └── 📂 data-structures/ # 数据结构 +│ ├── 📄 index.mdx # 数据结构概述 +│ ├── 📂 array/ # 数组 +│ │ ├── 📄 index.mdx # 数组概述 +│ │ ├── 📄 01-static-array.mdx +│ │ └── 📄 02-dynamic-array.mdx +│ └── 📂 linked-list/ # 链表 +│ ├── 📄 index.mdx # 链表概述 +│ └── 📄 01-singly-linked-list.mdx +``` + +## 🛠️ 可用脚本 + +```bash +# 开发 +pnpm dev # 启动开发服务器 +pnpm build # 构建生产版本 +pnpm start # 启动生产服务器 + +# 内容 +pnpm check:content # 使用 Contentlayer 验证内容 + +# 导出 +pnpm export # 导出静态站点到 /out 目录 +``` + +## 📄 许可证 + +本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。 + +## 🙏 致谢 + +- 使用 [Next.js](https://nextjs.org/) 构建 +- 由 [Contentlayer](https://contentlayer.dev/) 驱动 +- 使用 [Tailwind CSS](https://tailwindcss.com/) 样式 +- UI 组件来自 [shadcn/ui](https://ui.shadcn.com/) + +特别感谢我们所有的贡献者!🎉 + +## 📞 联系我们 + +- 📧 Issues: [GitHub Issues](https://github.com/involutionhell/involutionhell.github.io/issues) +- 💬 Discussions: [GitHub Discussions](https://github.com/involutionhell/involutionhell.github.io/discussions) +- 🌟 Stars: 通过 ⭐ 表示支持 + + # Involution Hell Docs [![Deploy to GitHub Pages](https://github.com/involutionhell/involutionhell.github.io/actions/workflows/deploy.yml/badge.svg)](https://github.com/involutionhell/involutionhell.github.io/actions/workflows/deploy.yml) @@ -132,130 +259,3 @@ Special thanks to all our contributors! 🎉 - 💬 Discussions: [GitHub Discussions](https://github.com/involutionhell/involutionhell.github.io/discussions) - 🌟 Stars: Show your support with a ⭐ ---- - -## 中文版本 / Chinese Version - -## 📋 关于 - -这是一个基于现代 Web 技术的协作文档平台,旨在帮助学生们分享和访问计算机科学与编程的高质量学习资料。 - -## ✨ 特性 - -- 🚀 **现代化技术栈**:Next.js 15 + Contentlayer + MDX -- 🎨 **美观界面**:基于 Tailwind CSS 和 shadcn/ui 构建 -- 🌍 **双语支持**:中英文内容 -- 📱 **响应式设计**:完美适配所有设备 -- ⚡ **快速且 SEO 友好**:静态生成,性能优化 -- 🤝 **社区驱动**:开源且协作性强 - -## 🚀 快速开始 - -### 环境要求 - -- Node.js 18+ -- pnpm(推荐) - -### 安装 - -```bash -# 克隆仓库 -git clone https://github.com/involutionhell/involutionhell.github.io.git -cd involutionhell.github.io - -# 安装依赖 -pnpm install - -# 启动开发服务器 -pnpm dev -``` - -打开浏览器访问 [http://localhost:3000](http://localhost:3000) 查看站点。 - -## 📁 项目结构 - -``` -📦 involutionhell.github.io -├── 📂 app/ # Next.js App Router -│ ├── 📂 components/ # React 组件 -│ ├── 📂 docs/ # 文档内容 -│ │ └── 📂 computer-science/ # 计算机科学知识库 -│ ├── 📄 layout.tsx # 根布局 -│ └── 📄 page.tsx # 主页 -├── 📂 contentlayer.config.ts # Contentlayer 配置 -├── 📂 tailwind.config.ts # Tailwind CSS 配置 -└── 📄 package.json # 依赖和脚本 -``` - -## 🤝 贡献 - -我们欢迎社区贡献!在开始之前,请阅读我们的[贡献指南](CONTRIBUTING.md)。 - -### 贡献方式 - -- 📝 **内容**:添加新文章或改进现有文章 -- 🐛 **错误修复**:报告并修复问题 -- 🎨 **UI/UX**:改进设计和用户体验 -- 🌐 **翻译**:帮助多语言支持 -- 📖 **文档**:改进项目文档 - -### 贡献者快速开始 - -1. Fork 本仓库 -2. 创建特性分支: `git checkout -b feat/your-feature` -3. 进行修改 -4. 测试修改: `pnpm check:content` -5. 提交 PR - -## 📚 文档结构 - -我们的内容采用分层式的"Folder as a Book"结构: - -``` -📂 docs/ -├── 📂 computer-science/ # 计算机科学 -│ ├── 📄 index.mdx # 计算机科学概述 -│ └── 📂 data-structures/ # 数据结构 -│ ├── 📄 index.mdx # 数据结构概述 -│ ├── 📂 array/ # 数组 -│ │ ├── 📄 index.mdx # 数组概述 -│ │ ├── 📄 01-static-array.mdx -│ │ └── 📄 02-dynamic-array.mdx -│ └── 📂 linked-list/ # 链表 -│ ├── 📄 index.mdx # 链表概述 -│ └── 📄 01-singly-linked-list.mdx -``` - -## 🛠️ 可用脚本 - -```bash -# 开发 -pnpm dev # 启动开发服务器 -pnpm build # 构建生产版本 -pnpm start # 启动生产服务器 - -# 内容 -pnpm check:content # 使用 Contentlayer 验证内容 - -# 导出 -pnpm export # 导出静态站点到 /out 目录 -``` - -## 📄 许可证 - -本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。 - -## 🙏 致谢 - -- 使用 [Next.js](https://nextjs.org/) 构建 -- 由 [Contentlayer](https://contentlayer.dev/) 驱动 -- 使用 [Tailwind CSS](https://tailwindcss.com/) 样式 -- UI 组件来自 [shadcn/ui](https://ui.shadcn.com/) - -特别感谢我们所有的贡献者!🎉 - -## 📞 联系我们 - -- 📧 Issues: [GitHub Issues](https://github.com/involutionhell/involutionhell.github.io/issues) -- 💬 Discussions: [GitHub Discussions](https://github.com/involutionhell/involutionhell.github.io/discussions) -- 🌟 Stars: 通过 ⭐ 表示支持 From c32860add683fafae210ac902d7c828e68371342 Mon Sep 17 00:00:00 2001 From: Crokily Date: Fri, 12 Sep 2025 23:18:07 +1000 Subject: [PATCH 8/8] feat(utils): add auto-generated comment for shadcn/ui in utils.ts --- lib/utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/utils.ts b/lib/utils.ts index bd0c391..9a94c55 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,3 +1,4 @@ +// shadcn/ui 自动生成的 utils.ts import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge"