fix classes and make fic loader more responsive in dev
This commit is contained in:
parent
496ba125d0
commit
e7ed23bb39
28
bun.lock
28
bun.lock
@ -4,15 +4,17 @@
|
||||
"": {
|
||||
"name": "astro",
|
||||
"dependencies": {
|
||||
"@astrojs/db": "^0.16.1",
|
||||
"@astrojs/db": "0.17.1",
|
||||
"@astrojs/mdx": "^4.3.3",
|
||||
"@astrojs/node": "^9.4.0",
|
||||
"@astrojs/node": "9.4.1",
|
||||
"@astrojs/rss": "4.0.12",
|
||||
"@fujocoded/astro-dev-only": "0.0.3",
|
||||
"astro": "5.12.3",
|
||||
"@fujocoded/astro-dev-only": "0.0.4",
|
||||
"astro": "5.13.0",
|
||||
"astro-breadcrumbs": "^3.3.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"dompurify": "^3.2.6",
|
||||
"markdown-it": "^14.1.0",
|
||||
"marked": "^16.1.2",
|
||||
"node-html-parser": "^7.0.1",
|
||||
"sanitize-html": "^2.17.0",
|
||||
},
|
||||
@ -26,7 +28,7 @@
|
||||
"packages": {
|
||||
"@astrojs/compiler": ["@astrojs/compiler@2.12.2", "", {}, "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw=="],
|
||||
|
||||
"@astrojs/db": ["@astrojs/db@0.16.1", "", { "dependencies": { "@libsql/client": "^0.15.2", "deep-diff": "^1.0.2", "drizzle-orm": "^0.42.0", "kleur": "^4.1.5", "nanoid": "^5.1.5", "prompts": "^2.4.2", "yargs-parser": "^21.1.1", "zod": "^3.24.4" } }, "sha512-pBX19Rh1Ds7riQReDH6gZ5gCf1Txk03WWqMhHIkZIW7lNPnyEx5cuYtl/V9fUnXnqMrBxL9bOHkW4e937DFtWg=="],
|
||||
"@astrojs/db": ["@astrojs/db@0.17.1", "", { "dependencies": { "@libsql/client": "^0.15.2", "deep-diff": "^1.0.2", "drizzle-orm": "^0.42.0", "kleur": "^4.1.5", "nanoid": "^5.1.5", "prompts": "^2.4.2", "yargs-parser": "^21.1.1", "zod": "^3.24.4" } }, "sha512-QL09xZf5Om8AshIlt+YhLDYf6M1QSzv+kfuljsPrhEXJ8U/tuKnbWs2M3wimFaLG3/fU0prFix8lWt7zU8ytfA=="],
|
||||
|
||||
"@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.1", "", {}, "sha512-7dwEVigz9vUWDw3nRwLQ/yH/xYovlUA0ZD86xoeKEBmkz9O6iELG1yri67PgAPW6VLL/xInA4t7H0CK6VmtkKQ=="],
|
||||
|
||||
@ -34,7 +36,7 @@
|
||||
|
||||
"@astrojs/mdx": ["@astrojs/mdx@4.3.3", "", { "dependencies": { "@astrojs/markdown-remark": "6.3.5", "@mdx-js/mdx": "^3.1.0", "acorn": "^8.14.1", "es-module-lexer": "^1.6.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "kleur": "^4.1.5", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.4", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-+9+xGP2TBXxcm84cpiq4S9JbuHOHM1fcvREfqW7VHxlUyfUQPByoJ9YYliqHkLS6BMzG+O/+o7n8nguVhuEv4w=="],
|
||||
|
||||
"@astrojs/node": ["@astrojs/node@9.4.0", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.1", "send": "^1.2.0", "server-destroy": "^1.0.1" }, "peerDependencies": { "astro": "^5.3.0" } }, "sha512-Gxs0iVUvOmQmK+H1DBoabcgvdSDg277SwbujRv2cUBlnpcOTJQDFRhRvyJ7G+Zkd06/jhRphsTTmmrBY0PqI4g=="],
|
||||
"@astrojs/node": ["@astrojs/node@9.4.1", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.1", "send": "^1.2.0", "server-destroy": "^1.0.1" }, "peerDependencies": { "astro": "^5.3.0" } }, "sha512-lpSAQFS4IiCFGQHL/q/1CcX+AmFbma4NOoV5j7Z7Ml2wevyDe/2kAjScKIKk2DA7k/MrXSZ5ZN+IxJgpPbnAOQ=="],
|
||||
|
||||
"@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="],
|
||||
|
||||
@ -106,7 +108,7 @@
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.8", "", { "os": "win32", "cpu": "x64" }, "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw=="],
|
||||
|
||||
"@fujocoded/astro-dev-only": ["@fujocoded/astro-dev-only@0.0.3", "", {}, "sha512-BOLYZcivrJVUA60d4R2+yEGwDJZ+3Z/zndLACxk6YpClu5ETl0adghwCCt9yIHsq79KDx/Or8LH2aqS6fVlQbg=="],
|
||||
"@fujocoded/astro-dev-only": ["@fujocoded/astro-dev-only@0.0.4", "", {}, "sha512-1I/h/M5QguTjl+MxXUqwDiuLs1xUDhzQ3bzWwwhyrrZL8bhqXsHbEcuxw+AUT0RS3WTFclF7L/5wq7vw1YEXdg=="],
|
||||
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
|
||||
|
||||
@ -268,6 +270,8 @@
|
||||
|
||||
"@types/sanitize-html": ["@types/sanitize-html@2.16.0", "", { "dependencies": { "htmlparser2": "^8.0.0" } }, "sha512-l6rX1MUXje5ztPT0cAFtUayXF06DqPhRyfVXareEN5gGCFaP/iwsxIyKODr9XDhfxPpN6vXUFNfo5kZMXCxBtw=="],
|
||||
|
||||
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||
|
||||
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
||||
@ -294,7 +298,7 @@
|
||||
|
||||
"astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="],
|
||||
|
||||
"astro": ["astro@5.12.3", "", { "dependencies": { "@astrojs/compiler": "^2.12.2", "@astrojs/internal-helpers": "0.6.1", "@astrojs/markdown-remark": "6.3.3", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "smol-toml": "^1.3.4", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.2", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-fU1hNPMkccm+FuonGsY5DFkC2QyuLCju++8L2ubzBtYBDBf6bmfgmVM7A2dK+Hl+ZJCUNgepsClhBpczj+2LRw=="],
|
||||
"astro": ["astro@5.13.0", "", { "dependencies": { "@astrojs/compiler": "^2.12.2", "@astrojs/internal-helpers": "0.7.1", "@astrojs/markdown-remark": "6.3.5", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "smol-toml": "^1.3.4", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.4", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-kWahyvrrxUtgxFRRWSH5X0DESvgg4ZZ0fk6tU7blVZRgmj4PY79nzfaXFT+N+Ac2vWXX7eYUPYs1kLLk5IjBfQ=="],
|
||||
|
||||
"astro-breadcrumbs": ["astro-breadcrumbs@3.3.1", "", { "peerDependencies": { "astro": "^2.0.0-beta.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" } }, "sha512-O3wWzlc4HOU//ePefcwk2F4yQn830buVUVn6h7+sGmVq7+xvv9JmHTcmihU18ISte72ELnJlG2U8s58nIuPXfg=="],
|
||||
|
||||
@ -408,6 +412,8 @@
|
||||
|
||||
"domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
|
||||
|
||||
"dompurify": ["dompurify@3.2.6", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ=="],
|
||||
|
||||
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
||||
|
||||
"drizzle-orm": ["drizzle-orm@0.42.0", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-pS8nNJm2kBNZwrOjTHJfdKkaU+KuUQmV/vk5D57NojDq4FG+0uAYGMulXtYT///HfgsMF0hnFFvu1ezI3OwOkg=="],
|
||||
@ -570,6 +576,8 @@
|
||||
|
||||
"markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
|
||||
|
||||
"marked": ["marked@16.1.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-rNQt5EvRinalby7zJZu/mB+BvaAY2oz3wCuCjt1RDrWNpS1Pdf9xqMOeC9Hm5adBdcV/3XZPJpG58eT+WBc0XQ=="],
|
||||
|
||||
"mdast-util-definitions": ["mdast-util-definitions@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ=="],
|
||||
|
||||
"mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="],
|
||||
@ -960,10 +968,6 @@
|
||||
|
||||
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="],
|
||||
|
||||
"astro/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.3", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.2.1", "smol-toml": "^1.3.4", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-DDRtD1sPvAuA7ms2btc9A7/7DApKqgLMNrE6kh5tmkfy8utD0Z738gqd3p5aViYYdUtHIyEJ1X4mCMxfCfu15w=="],
|
||||
|
||||
"cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||
|
||||
"hast-util-to-parse5/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="],
|
||||
|
0
guestbook.db
Normal file
0
guestbook.db
Normal file
10
package.json
10
package.json
@ -9,15 +9,17 @@
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/db": "^0.16.1",
|
||||
"@astrojs/db": "0.17.1",
|
||||
"@astrojs/mdx": "^4.3.3",
|
||||
"@astrojs/node": "^9.4.0",
|
||||
"@astrojs/node": "9.4.1",
|
||||
"@astrojs/rss": "4.0.12",
|
||||
"@fujocoded/astro-dev-only": "0.0.3",
|
||||
"astro": "5.12.3",
|
||||
"@fujocoded/astro-dev-only": "0.0.4",
|
||||
"astro": "5.13.0",
|
||||
"astro-breadcrumbs": "^3.3.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"dompurify": "^3.2.6",
|
||||
"markdown-it": "^14.1.0",
|
||||
"marked": "^16.1.2",
|
||||
"node-html-parser": "^7.0.1",
|
||||
"sanitize-html": "^2.17.0"
|
||||
},
|
||||
|
@ -5,15 +5,15 @@ interface Props {
|
||||
imagePath: string;
|
||||
alt: string;
|
||||
caption?: string;
|
||||
class?: string | string[];
|
||||
class?: string;
|
||||
}
|
||||
|
||||
const { imagePath, alt, caption, class: className }: Props = Astro.props;
|
||||
const { imagePath, alt, caption, class: className, ...rest }: Props = Astro.props;
|
||||
const images = import.meta.glob<{ default: ImageMetadata }>("/src/assets/**/*.{jpeg,jpg,png,webp,gif}");
|
||||
const path = imagePath.startsWith("$") ? imagePath.replace("$", "/src/assets") : imagePath;
|
||||
if (!images[path]) throw new Error(`"${path}" does not exist in glob: "src/assets/**/*.{jpeg,jpg,png,webp,gif}"`);
|
||||
---
|
||||
<figure class:list={[className]}>
|
||||
<figure class:list={className} {...rest}>
|
||||
<Image src={images[path]()} {alt} />
|
||||
{caption && <figcaption>{caption}</figcaption>}
|
||||
</figure>
|
@ -1,7 +1,8 @@
|
||||
import { defineCollection, reference, z } from "astro:content";
|
||||
import { glob } from "astro/loaders";
|
||||
import { rssSchema } from "@astrojs/rss";
|
||||
import MarkdownIt from "markdown-it";
|
||||
// import MarkdownIt from "markdown-it";
|
||||
import { marked } from "marked";
|
||||
import moods from "@/utils/moods";
|
||||
import { ficsLoader } from "@/utils/loader";
|
||||
|
||||
@ -19,10 +20,7 @@ function slugify(input: string) {
|
||||
.replace(/-+$/, "");
|
||||
}
|
||||
|
||||
const parser = new MarkdownIt({
|
||||
html: true,
|
||||
breaks: true,
|
||||
});
|
||||
const parser = marked.use({ gfm: true, breaks: true, });
|
||||
|
||||
const blog = defineCollection({
|
||||
loader: glob({ pattern: "*.{md,mdx}", base: "./src/content/blog" }),
|
||||
@ -46,14 +44,13 @@ const chapters = defineCollection({
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
publishedAt: z.coerce.date(),
|
||||
notes: z.ostring().transform(notes => parser.renderInline(notes ?? "", {})),
|
||||
notes: z.ostring().transform(async (notes) => await parser.parseInline(notes ?? "")),
|
||||
lastModified: z.coerce.date().optional(),
|
||||
sortOrder: z.number().default(1),
|
||||
// fic: reference("fics"),
|
||||
}),
|
||||
});
|
||||
|
||||
const fics = defineCollection({
|
||||
const test = defineCollection({
|
||||
loader: glob({
|
||||
pattern: "**/*.{yml,yaml}",
|
||||
base: source,
|
||||
@ -66,19 +63,19 @@ const fics = defineCollection({
|
||||
title: z.string(),
|
||||
series: z.union([z.string(), z.array(z.string())]),
|
||||
publishedAt: z.coerce.date(),
|
||||
summary: z.string().transform(summary => parser.renderInline(summary, {})),
|
||||
summary: z.string().transform(async (summary) => await parser.parseInline(summary ?? "")),
|
||||
characters: z.array(z.string()).optional(),
|
||||
ships: z.ostring(),
|
||||
tags: z.array(z.string()).optional(),
|
||||
notes: z.ostring().transform(notes => parser.renderInline(notes ?? "", {})),
|
||||
notes: z.ostring().transform(async (notes) => await parser.parseInline(notes ?? "")),
|
||||
lastModified: z.coerce.date().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
const test = defineCollection({
|
||||
const fics = defineCollection({
|
||||
loader: ficsLoader(
|
||||
glob({
|
||||
pattern: "**/*.{yml,yaml}",
|
||||
pattern: "**/*.{yml,yaml|toml}",
|
||||
base: source,
|
||||
generateId: ({ entry, data }) => {
|
||||
if (data.slug) return data.slug as string;
|
||||
@ -90,14 +87,14 @@ const test = defineCollection({
|
||||
title: z.string(),
|
||||
series: z.union([z.string(), z.array(z.string())]),
|
||||
publishedAt: z.coerce.date(),
|
||||
summary: z.string().transform(summary => parser.renderInline(summary, {})),
|
||||
summary: z.string().transform(async (summary) => await parser.parseInline(summary ?? "")),
|
||||
characters: z.array(z.string()).optional(),
|
||||
ships: z.ostring(),
|
||||
tags: z.array(z.string()).optional(),
|
||||
notes: z.ostring().transform(notes => parser.renderInline(notes ?? "", {})),
|
||||
notes: z.ostring().transform(async (notes) => await parser.parseInline(notes ?? "")),
|
||||
lastModified: z.coerce.date().optional(),
|
||||
chapters: z.array(reference("chapters")).optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog, fics, chapters, test };
|
||||
export const collections = { blog, fics, chapters };
|
9
src/content/fics/test/_index.toml
Normal file
9
src/content/fics/test/_index.toml
Normal file
@ -0,0 +1,9 @@
|
||||
title = "this is a test"
|
||||
series = [
|
||||
"test",
|
||||
"fandom 2"
|
||||
]
|
||||
publishedAt = 2022-12-22
|
||||
summary = """
|
||||
yeller
|
||||
"""
|
@ -1,5 +0,0 @@
|
||||
title: this is a test
|
||||
series: test
|
||||
publishedAt: 2020-12-20T19:18:00
|
||||
summary:
|
||||
yeller
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: ch 1
|
||||
publishedAt: 2020-12-20T19:18:00
|
||||
publishedAt: 2022-11-01
|
||||
notes: i wrote this in a fugue state while listening to [Waste by Oh Wonder](https://www.youtube.com/watch?v=Ar1grAdGkec)
|
||||
sortOrder: 1
|
||||
---
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: ch 2
|
||||
publishedAt: 2020-12-20T19:18:00
|
||||
title: chapter 2
|
||||
publishedAt: 2023-12-12
|
||||
notes: i wrote this in a fugue state while listening to [Waste by Oh Wonder](https://www.youtube.com/watch?v=Ar1grAdGkec)
|
||||
sortOrder: 2
|
||||
---
|
||||
|
@ -4,6 +4,6 @@ publishedAt: 2020-12-20T19:18:00
|
||||
summary:
|
||||
Sanemi survives. He learns to bear the weight of living.
|
||||
|
||||
--
|
||||
<hr/>
|
||||
|
||||
MAJOR ending spoilers for the manga please don't read if you haven't finished the manga!!
|
@ -75,7 +75,7 @@ const { frontmatter } = Astro.props;
|
||||
li::marker { content: " "; }
|
||||
}
|
||||
|
||||
:global(.avatar) {
|
||||
.avatar {
|
||||
width: fit-content;
|
||||
margin: 0 auto 2rem;
|
||||
border-image: var(--borderImage) 5 4 / 10px 8px / 8px repeat;
|
||||
@ -86,7 +86,6 @@ const { frontmatter } = Astro.props;
|
||||
place-content: center;
|
||||
width: 80px;
|
||||
height: auto;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -24,7 +24,8 @@ const { title, ficTitle, date, notes, lastModified }: Props = Astro.props;
|
||||
<main>
|
||||
<ChapterContent lastModified={lastModified} notes={notes}>
|
||||
<Fragment slot="title">
|
||||
<h1>{title}</h1>
|
||||
<h1>{ficTitle}</h1>
|
||||
<h2>{title}</h2>
|
||||
<time datetime={formatDate(date, true)}>
|
||||
Published on {formatDate(date)}
|
||||
</time>
|
||||
|
@ -5,7 +5,10 @@ import { getCollection, render } from "astro:content";
|
||||
import { Breadcrumbs } from "astro-breadcrumbs";
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
const chapters = await getCollection("chapters");
|
||||
const fics = await getCollection("fics");
|
||||
const chapters = await getCollection("chapters", ({ id }) => {
|
||||
return fics.find(({ data }) => data.chapters?.some(chapter => chapter.id === id));
|
||||
});
|
||||
return chapters.map(chapter => ({
|
||||
params: {
|
||||
ficId: chapter.id.split("/")[0],
|
||||
@ -19,12 +22,8 @@ const { ficId, chapterId } = Astro.params;
|
||||
const { chapter } = Astro.props;
|
||||
const { Content, remarkPluginFrontmatter } = await render(chapter);
|
||||
|
||||
const chapters = await getCollection("chapters", ({ id }) => {
|
||||
return id.split("/")[0] === ficId;
|
||||
});
|
||||
const fic = await getCollection("fics", ({ id }) => {
|
||||
return id === ficId;
|
||||
});
|
||||
const chapters = await getCollection("chapters", ({ id }) => id.split("/")[0] === ficId);
|
||||
const fic = await getCollection("fics", ({ id }) => id === ficId);
|
||||
chapters.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
|
||||
const current = chapters.findIndex(chapter => chapter.id === `${ficId}/${chapterId}`);
|
||||
const next = current + 1 === chapters.length ? undefined : chapters[current + 1];
|
||||
@ -66,12 +65,8 @@ const links = [
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
{previous && (
|
||||
<a id="previous" href={`/fics/${previous.id}`}>{previous.data.title}</a>
|
||||
)}
|
||||
{next && (
|
||||
<a id="next" href={`/fics/${next.id}`}>{next.data.title}</a>
|
||||
)}
|
||||
{previous && <a id="previous" href={`/fics/${previous.id}`}>{previous.data.title}</a>}
|
||||
{next && <a id="next" href={`/fics/${next.id}`}>{next.data.title}</a>}
|
||||
</nav>
|
||||
)}
|
||||
</Chapter>
|
||||
|
@ -1,7 +1,9 @@
|
||||
---
|
||||
import type { GetStaticPaths } from "astro";
|
||||
import { Font } from "astro:assets";
|
||||
import { getCollection, getEntry, render } from "astro:content";
|
||||
import { getCollection, getEntries, render } from "astro:content";
|
||||
import { marked } from "marked";
|
||||
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import formatDate from "@/utils/formatDate";
|
||||
import ChapterContent from "~/ChapterContent.astro";
|
||||
@ -15,21 +17,17 @@ export const getStaticPaths = (async () => {
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
const { fic } = Astro.props;
|
||||
const chapters = await getCollection("chapters", ({ id }) => {
|
||||
return id.startsWith(fic.id);
|
||||
});
|
||||
const chapters = await getEntries(fic.data.chapters ?? []);
|
||||
chapters.length = Math.min(chapters.length, 5);
|
||||
chapters.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
|
||||
const oneshot = chapters.length === 1 && await getEntry(chapters[0]);
|
||||
const { Content } = oneshot && await render(oneshot);
|
||||
const { Content } = await render(fic);
|
||||
const notes = fic.rendered && await marked.use({ async: true, gfm: true, breaks: true }).parseInline((fic.rendered.metadata!.frontmatter as any)["notes"]);
|
||||
---
|
||||
<Layout title={fic.data.title}>
|
||||
<Fragment slot="head">
|
||||
<link rel="alternate" type="application/rss+xml" title={fic.data.title} href={new URL(`/fics/${Astro.params.ficId}/rss.xml`, Astro.site)} />
|
||||
<meta name="description" content={fic.data.summary?.substring(0, 150) + "…"} />
|
||||
{oneshot && (
|
||||
<Font cssVariable="--serif" preload />
|
||||
)}
|
||||
{fic.body && <Font cssVariable="--serif" preload />}
|
||||
</Fragment>
|
||||
|
||||
<main>
|
||||
@ -39,10 +37,8 @@ const { Content } = oneshot && await render(oneshot);
|
||||
<dl>
|
||||
<dt>Fandom</dt>
|
||||
{typeof fic.data.series === "object"
|
||||
? (<ul>
|
||||
{fic.data.series.map(fandom => (<li>{fandom}</li>))}
|
||||
</ul>)
|
||||
: (<dd>{fic.data.series}</dd>)
|
||||
? <ul>{fic.data.series.map(fandom => (<li>{fandom}</li>))}</ul>
|
||||
: <dd>{fic.data.series}</dd>
|
||||
}
|
||||
<dt>Date</dt>
|
||||
<dd>
|
||||
@ -59,14 +55,12 @@ const { Content } = oneshot && await render(oneshot);
|
||||
</dl>
|
||||
|
||||
<div class="links">
|
||||
{!oneshot && (
|
||||
<a class="button" href={`/fics/${chapters[0].id}`}>start reading</a>
|
||||
)}
|
||||
{fic.data.chapters && <a class="button" href={`/fics/${chapters[0].id}`}>start reading</a>}
|
||||
<a class="button" href={`/fics/${Astro.params.ficId}/rss.xml`}>rss feed</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{!oneshot && (
|
||||
|
||||
{fic.data.chapters && (
|
||||
<h2>chapters</h2>
|
||||
<ul>
|
||||
{chapters.map(chapter => (
|
||||
@ -76,9 +70,9 @@ const { Content } = oneshot && await render(oneshot);
|
||||
)}
|
||||
</section>
|
||||
|
||||
{oneshot && (
|
||||
{fic.body && (
|
||||
<section id="oneshot">
|
||||
<ChapterContent lastModified={oneshot.data.lastModified} notes={oneshot.data.notes}>
|
||||
<ChapterContent lastModified={(fic.rendered?.metadata!.frontmatter as any)['lastModified']} notes={notes}>
|
||||
<Content />
|
||||
</ChapterContent>
|
||||
</section>
|
||||
|
@ -1,23 +1,25 @@
|
||||
import type { APIRoute } from "astro";
|
||||
import { getCollection } from "astro:content";
|
||||
import { experimental_AstroContainer as AstroContainer } from "astro/container";
|
||||
import { getCollection, render } from "astro:content";
|
||||
import rss, { type RSSFeedItem } from "@astrojs/rss";
|
||||
import MarkdownIt from "markdown-it";
|
||||
|
||||
import { marked } from "marked";
|
||||
import { parse as htmlParser } from "node-html-parser";
|
||||
import sanitize from "sanitize-html";
|
||||
import fixRssImages from "@/utils/fixRssImages";
|
||||
|
||||
const parser = new MarkdownIt();
|
||||
const parser = marked.use({ gfm: true, breaks: true });
|
||||
const fics = await getCollection("fics");
|
||||
|
||||
export const GET: APIRoute = async (context) => {
|
||||
const chapters = await getCollection("chapters", ({ id }) => {
|
||||
return id.split("/")[0] === context.params.ficId;
|
||||
});
|
||||
const chapters = await getCollection("chapters", ({ id }) => id.split("/")[0] === context.params.ficId);
|
||||
const fic = fics.find(({ id }) => id === context.params.ficId);
|
||||
const container = await AstroContainer.create();
|
||||
const feed: RSSFeedItem[] = [];
|
||||
|
||||
for (const entry of chapters) {
|
||||
const content = parser.render(entry.body!);
|
||||
const { Content } = await render(entry);
|
||||
const content = await container.renderToString(Content);
|
||||
const html = htmlParser.parse(content);
|
||||
const images = html.querySelectorAll("img");
|
||||
|
||||
@ -33,12 +35,11 @@ export const GET: APIRoute = async (context) => {
|
||||
categories: typeof fic?.data.series == "string" ? [fic?.data.series] : [...fic?.data.series!],
|
||||
});
|
||||
}
|
||||
const summary = await parser.parseInline(fic?.data.summary ?? "");
|
||||
|
||||
return rss({
|
||||
title: `${fic?.data.title}`,
|
||||
description: sanitize(parser.render(fic?.data.summary!), {
|
||||
allowedTags: sanitize.defaults.allowedTags.concat(["br"]),
|
||||
}),
|
||||
description: sanitize(summary),
|
||||
site: context.site!,
|
||||
items: feed,
|
||||
});
|
||||
|
@ -1,14 +1,13 @@
|
||||
---
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import { getCollection } from "astro:content";
|
||||
import dayjs from "dayjs";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import formatDate from "@/utils/formatDate";
|
||||
|
||||
const fics = await getCollection("fics");
|
||||
const chapters = await getCollection("chapters");
|
||||
fics.sort((a, b) => b.data.publishedAt.valueOf() - a.data.publishedAt.valueOf());
|
||||
chapters.length = Math.min(chapters.length, 5);
|
||||
chapters.sort((a, b) => a.data.publishedAt.valueOf() - b.data.publishedAt.valueOf());
|
||||
dayjs.extend(utc);
|
||||
chapters.sort((a, b) => b.data.publishedAt.valueOf() - a.data.publishedAt.valueOf());
|
||||
---
|
||||
<Layout>
|
||||
<h1>fanfics</h1>
|
||||
@ -17,15 +16,20 @@ dayjs.extend(utc);
|
||||
<ul>
|
||||
{chapters.map(post => (
|
||||
<li>
|
||||
<time datetime={dayjs(post.data.publishedAt).utc(true).toISOString()}>
|
||||
{dayjs(post.data.publishedAt).utc(true).format("MMMM DD, YYYY")}
|
||||
<time datetime={formatDate(post.data.publishedAt, true)}>
|
||||
{formatDate(post.data.publishedAt, false, "MMMM DD, YYYY")}
|
||||
</time>
|
||||
{post.id}
|
||||
{JSON.stringify(fics.filter(fic => fic.id.includes(post.id)))}
|
||||
<a href={`/fics/${post.id}`}>{post.data.title}</a> in
|
||||
<a href={`/fics/${post.id.split("/")[0]}`}>
|
||||
{fics.find(({ id }) => post.id.startsWith(id))?.data.title}
|
||||
</a>
|
||||
{fics.some(({ data }) => data.chapters?.some(({ id }) => id === post.id))
|
||||
? <>
|
||||
<a href={`/fics/${post.id}`}>{post.data.title}</a>
|
||||
in
|
||||
<a href={`/fics/${post.id.split("/")[0]}`}>
|
||||
{fics.filter(({ id }) => id === post.id.split("/")[0])[0].data.title}
|
||||
</a>
|
||||
</>
|
||||
: <a href={`/fics/${post.id.split("/")[0]}`}>
|
||||
{fics.filter(({ id }) => id === post.id.split("/")[0])[0].data.title}
|
||||
</a>}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
@ -7,7 +7,7 @@ import bulletin from "$/acnl-bulletin.png";
|
||||
<Layout>
|
||||
<Navbar />
|
||||
<main>
|
||||
<section id="welcome" class="board">
|
||||
<section id="welcome">
|
||||
<div class="card">
|
||||
<h1>welcome!</h1>
|
||||
<article>
|
||||
@ -16,7 +16,7 @@ import bulletin from "$/acnl-bulletin.png";
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="updates" class="board">
|
||||
<section id="updates">
|
||||
<article class="update card">
|
||||
<h1>update title</h1>
|
||||
<time datetime="">05/01/25</time>
|
||||
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
const fics = await getCollection("test");
|
||||
---
|
||||
<Layout>
|
||||
{fics.map(fic => (
|
||||
<article>
|
||||
<h2>{fic.data.title}</h2>
|
||||
</article>
|
||||
))}
|
||||
|
||||
</Layout>
|
@ -14,55 +14,70 @@ async function getAllChapters(metaPath: string) {
|
||||
export function ficsLoader(loader: Loader) {
|
||||
const oldLoad = loader.load;
|
||||
loader.load = async (context: LoaderContext) => {
|
||||
await oldLoad({
|
||||
...context,
|
||||
parseData: async (data) => data.data,
|
||||
context.watcher?.on("all", async (_event, path) => {
|
||||
if (path.includes("fics")) {
|
||||
await resolveFics(oldLoad, context);
|
||||
}
|
||||
});
|
||||
await Promise.all(
|
||||
context.store.values().map(async (value) => {
|
||||
const loadedPromise = Promise.withResolvers();
|
||||
getAllChapters(value.filePath as string).then(
|
||||
async (chapters) => {
|
||||
const { digest, ...valueWithoutDigest } = value;
|
||||
const newData = await context.parseData({
|
||||
id: value.id,
|
||||
data: {
|
||||
...valueWithoutDigest.data,
|
||||
...chapters.length > 1 && { chapters: chapters },
|
||||
},
|
||||
});
|
||||
if (chapters.length === 1) {
|
||||
// i've committed unspeakable atrocities here
|
||||
const search = import.meta.glob<MarkdownInstance<any>>(`../content/fics/**/*.md`, { eager: true });
|
||||
const body = Object.values(search).filter(path => path.file?.includes(chapters[0]))[0];
|
||||
context.store.set({
|
||||
...valueWithoutDigest,
|
||||
data: newData,
|
||||
body: body.rawContent(),
|
||||
rendered: {
|
||||
html: await body.compiledContent(),
|
||||
metadata: {
|
||||
headings: body.getHeadings(),
|
||||
frontmatter: body.frontmatter,
|
||||
},
|
||||
},
|
||||
digest: context.generateDigest(newData),
|
||||
});
|
||||
} else {
|
||||
context.store.set({
|
||||
...valueWithoutDigest,
|
||||
data: newData,
|
||||
digest: context.generateDigest(newData),
|
||||
});
|
||||
}
|
||||
loadedPromise.resolve(chapters);
|
||||
}
|
||||
);
|
||||
|
||||
return loadedPromise.promise;
|
||||
})
|
||||
);
|
||||
await resolveFics(oldLoad, context);
|
||||
};
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
// please don't ask me why i did this. idk either.
|
||||
async function resolveFics(loader: (oldContext: LoaderContext) => Promise<void>, context: LoaderContext) {
|
||||
await loader({
|
||||
...context,
|
||||
parseData: async (data) => data.data,
|
||||
});
|
||||
await Promise.all(
|
||||
context.store.values().map(async (value) => {
|
||||
const loadedPromise = Promise.withResolvers();
|
||||
getAllChapters(value.filePath as string).then(
|
||||
async (chapters) => {
|
||||
const { digest, ...valueWithoutDigest } = value;
|
||||
const newData = await context.parseData({
|
||||
id: value.id,
|
||||
data: {
|
||||
...valueWithoutDigest.data,
|
||||
...chapters.length > 1 && { chapters: chapters },
|
||||
},
|
||||
});
|
||||
if (chapters.length === 1) {
|
||||
// i've committed unspeakable atrocities here
|
||||
const search = import.meta.glob<MarkdownInstance<any>>(`../content/fics/**/*.md`);
|
||||
// const body = Object.values(search).filter(path => path.file?.includes(chapters[0]))[0];
|
||||
for (const path in search) {
|
||||
if (path.includes(chapters[0])) {
|
||||
const body = await search[path]();
|
||||
const html = await body.compiledContent();
|
||||
context.store.set({
|
||||
...valueWithoutDigest,
|
||||
data: newData,
|
||||
body: body.rawContent(),
|
||||
rendered: {
|
||||
html,
|
||||
metadata: {
|
||||
headings: body.getHeadings(),
|
||||
frontmatter: body.frontmatter,
|
||||
},
|
||||
},
|
||||
digest: context.generateDigest(newData),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.store.set({
|
||||
...valueWithoutDigest,
|
||||
data: newData,
|
||||
digest: context.generateDigest(newData),
|
||||
});
|
||||
}
|
||||
loadedPromise.resolve(chapters);
|
||||
}
|
||||
);
|
||||
return loadedPromise.promise;
|
||||
})
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user