Integrate ghost cms
Signed-off-by: baalajimaestro <me@baalajimaestro.me>
This commit is contained in:
parent
d59a8e91a6
commit
7d4dbb00a0
9 changed files with 164 additions and 93 deletions
|
@ -16,6 +16,7 @@
|
||||||
"@astrojs/rss": "^4.0.7",
|
"@astrojs/rss": "^4.0.7",
|
||||||
"@astrojs/sitemap": "^3.1.6",
|
"@astrojs/sitemap": "^3.1.6",
|
||||||
"@astrojs/vue": "^4.5.0",
|
"@astrojs/vue": "^4.5.0",
|
||||||
|
"@tryghost/content-api": "^1.11.21",
|
||||||
"@unocss/reset": "^0.61.0",
|
"@unocss/reset": "^0.61.0",
|
||||||
"astro": "^4.11.3",
|
"astro": "^4.11.3",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
"@iconify/json": "^2.2.204",
|
"@iconify/json": "^2.2.204",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
|
"@types/tryghost__content-api": "^1.3.16",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"bumpp": "^9.4.1",
|
"bumpp": "^9.4.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
|
|
|
@ -20,6 +20,9 @@ importers:
|
||||||
'@astrojs/vue':
|
'@astrojs/vue':
|
||||||
specifier: ^4.5.0
|
specifier: ^4.5.0
|
||||||
version: 4.5.0(astro@4.11.5(typescript@5.5.3))(rollup@4.18.1)(vite@5.3.3)(vue@3.4.31(typescript@5.5.3))
|
version: 4.5.0(astro@4.11.5(typescript@5.5.3))(rollup@4.18.1)(vite@5.3.3)(vue@3.4.31(typescript@5.5.3))
|
||||||
|
'@tryghost/content-api':
|
||||||
|
specifier: ^1.11.21
|
||||||
|
version: 1.11.21
|
||||||
'@unocss/reset':
|
'@unocss/reset':
|
||||||
specifier: ^0.61.0
|
specifier: ^0.61.0
|
||||||
version: 0.61.3
|
version: 0.61.3
|
||||||
|
@ -48,6 +51,9 @@ importers:
|
||||||
'@types/nprogress':
|
'@types/nprogress':
|
||||||
specifier: ^0.2.3
|
specifier: ^0.2.3
|
||||||
version: 0.2.3
|
version: 0.2.3
|
||||||
|
'@types/tryghost__content-api':
|
||||||
|
specifier: ^1.3.16
|
||||||
|
version: 1.3.16
|
||||||
'@vueuse/core':
|
'@vueuse/core':
|
||||||
specifier: ^10.11.0
|
specifier: ^10.11.0
|
||||||
version: 10.11.0(vue@3.4.31(typescript@5.5.3))
|
version: 10.11.0(vue@3.4.31(typescript@5.5.3))
|
||||||
|
@ -846,6 +852,9 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: '>=8.40.0'
|
eslint: '>=8.40.0'
|
||||||
|
|
||||||
|
'@tryghost/content-api@1.11.21':
|
||||||
|
resolution: {integrity: sha512-ozJqEMHDUO7D0SGxPbUnG+RvwBbzC3zmdGOW8cFvkcKzrhe7uOAmVKyq7/J3kRAM2QthTlmiDpqp7NEo9ZLlKg==}
|
||||||
|
|
||||||
'@types/acorn@4.0.6':
|
'@types/acorn@4.0.6':
|
||||||
resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==}
|
resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==}
|
||||||
|
|
||||||
|
@ -915,6 +924,9 @@ packages:
|
||||||
'@types/sax@1.2.7':
|
'@types/sax@1.2.7':
|
||||||
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
|
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
|
||||||
|
|
||||||
|
'@types/tryghost__content-api@1.3.16':
|
||||||
|
resolution: {integrity: sha512-i3TryXx8ZoW5LC9dMDWLkCg6vFMeCh4tAvr0ijAdlEzIhoSC8q5RPMANNmkiDxDcNMRCByVMoT4+RfB5qeURZQ==}
|
||||||
|
|
||||||
'@types/unist@2.0.10':
|
'@types/unist@2.0.10':
|
||||||
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
||||||
|
|
||||||
|
@ -1301,6 +1313,12 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@astrojs/compiler': '>=0.27.0'
|
'@astrojs/compiler': '>=0.27.0'
|
||||||
|
|
||||||
|
asynckit@0.4.0:
|
||||||
|
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||||
|
|
||||||
|
axios@1.7.2:
|
||||||
|
resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==}
|
||||||
|
|
||||||
axobject-query@4.0.0:
|
axobject-query@4.0.0:
|
||||||
resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==}
|
resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==}
|
||||||
|
|
||||||
|
@ -1490,6 +1508,10 @@ packages:
|
||||||
colorette@2.0.20:
|
colorette@2.0.20:
|
||||||
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
|
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
|
||||||
|
|
||||||
|
combined-stream@1.0.8:
|
||||||
|
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||||
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
comma-separated-tokens@2.0.3:
|
comma-separated-tokens@2.0.3:
|
||||||
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
||||||
|
|
||||||
|
@ -1582,6 +1604,10 @@ packages:
|
||||||
defu@6.1.4:
|
defu@6.1.4:
|
||||||
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
||||||
|
|
||||||
|
delayed-stream@1.0.0:
|
||||||
|
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||||
|
engines: {node: '>=0.4.0'}
|
||||||
|
|
||||||
dequal@2.0.3:
|
dequal@2.0.3:
|
||||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -2006,6 +2032,19 @@ packages:
|
||||||
resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==}
|
resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
follow-redirects@1.15.6:
|
||||||
|
resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
|
||||||
|
engines: {node: '>=4.0'}
|
||||||
|
peerDependencies:
|
||||||
|
debug: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
debug:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
form-data@4.0.0:
|
||||||
|
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
fs-extra@11.2.0:
|
fs-extra@11.2.0:
|
||||||
resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
|
resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
|
||||||
engines: {node: '>=14.14'}
|
engines: {node: '>=14.14'}
|
||||||
|
@ -2657,6 +2696,14 @@ packages:
|
||||||
resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
|
resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
|
||||||
engines: {node: '>=8.6'}
|
engines: {node: '>=8.6'}
|
||||||
|
|
||||||
|
mime-db@1.52.0:
|
||||||
|
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
mime-types@2.1.35:
|
||||||
|
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||||
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
mimic-fn@2.1.0:
|
mimic-fn@2.1.0:
|
||||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -2962,6 +3009,9 @@ packages:
|
||||||
property-information@6.5.0:
|
property-information@6.5.0:
|
||||||
resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==}
|
resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==}
|
||||||
|
|
||||||
|
proxy-from-env@1.1.0:
|
||||||
|
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||||
|
|
||||||
punycode@2.3.1:
|
punycode@2.3.1:
|
||||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -4490,6 +4540,12 @@ snapshots:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
|
'@tryghost/content-api@1.11.21':
|
||||||
|
dependencies:
|
||||||
|
axios: 1.7.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
|
||||||
'@types/acorn@4.0.6':
|
'@types/acorn@4.0.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.5
|
'@types/estree': 1.0.5
|
||||||
|
@ -4570,6 +4626,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 17.0.45
|
'@types/node': 17.0.45
|
||||||
|
|
||||||
|
'@types/tryghost__content-api@1.3.16': {}
|
||||||
|
|
||||||
'@types/unist@2.0.10': {}
|
'@types/unist@2.0.10': {}
|
||||||
|
|
||||||
'@types/unist@3.0.2': {}
|
'@types/unist@3.0.2': {}
|
||||||
|
@ -5197,6 +5255,16 @@ snapshots:
|
||||||
'@astrojs/compiler': 2.8.2
|
'@astrojs/compiler': 2.8.2
|
||||||
synckit: 0.9.0
|
synckit: 0.9.0
|
||||||
|
|
||||||
|
asynckit@0.4.0: {}
|
||||||
|
|
||||||
|
axios@1.7.2:
|
||||||
|
dependencies:
|
||||||
|
follow-redirects: 1.15.6
|
||||||
|
form-data: 4.0.0
|
||||||
|
proxy-from-env: 1.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
|
||||||
axobject-query@4.0.0:
|
axobject-query@4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
dequal: 2.0.3
|
dequal: 2.0.3
|
||||||
|
@ -5392,6 +5460,10 @@ snapshots:
|
||||||
|
|
||||||
colorette@2.0.20: {}
|
colorette@2.0.20: {}
|
||||||
|
|
||||||
|
combined-stream@1.0.8:
|
||||||
|
dependencies:
|
||||||
|
delayed-stream: 1.0.0
|
||||||
|
|
||||||
comma-separated-tokens@2.0.3: {}
|
comma-separated-tokens@2.0.3: {}
|
||||||
|
|
||||||
commander@12.1.0: {}
|
commander@12.1.0: {}
|
||||||
|
@ -5458,6 +5530,8 @@ snapshots:
|
||||||
|
|
||||||
defu@6.1.4: {}
|
defu@6.1.4: {}
|
||||||
|
|
||||||
|
delayed-stream@1.0.0: {}
|
||||||
|
|
||||||
dequal@2.0.3: {}
|
dequal@2.0.3: {}
|
||||||
|
|
||||||
destr@2.0.3: {}
|
destr@2.0.3: {}
|
||||||
|
@ -6010,6 +6084,14 @@ snapshots:
|
||||||
|
|
||||||
flattie@1.1.1: {}
|
flattie@1.1.1: {}
|
||||||
|
|
||||||
|
follow-redirects@1.15.6: {}
|
||||||
|
|
||||||
|
form-data@4.0.0:
|
||||||
|
dependencies:
|
||||||
|
asynckit: 0.4.0
|
||||||
|
combined-stream: 1.0.8
|
||||||
|
mime-types: 2.1.35
|
||||||
|
|
||||||
fs-extra@11.2.0:
|
fs-extra@11.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
|
@ -6980,6 +7062,12 @@ snapshots:
|
||||||
braces: 3.0.3
|
braces: 3.0.3
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
|
|
||||||
|
mime-db@1.52.0: {}
|
||||||
|
|
||||||
|
mime-types@2.1.35:
|
||||||
|
dependencies:
|
||||||
|
mime-db: 1.52.0
|
||||||
|
|
||||||
mimic-fn@2.1.0: {}
|
mimic-fn@2.1.0: {}
|
||||||
|
|
||||||
mimic-fn@4.0.0: {}
|
mimic-fn@4.0.0: {}
|
||||||
|
@ -7293,6 +7381,8 @@ snapshots:
|
||||||
|
|
||||||
property-information@6.5.0: {}
|
property-information@6.5.0: {}
|
||||||
|
|
||||||
|
proxy-from-env@1.1.0: {}
|
||||||
|
|
||||||
punycode@2.3.1: {}
|
punycode@2.3.1: {}
|
||||||
|
|
||||||
queue-microtask@1.2.3: {}
|
queue-microtask@1.2.3: {}
|
||||||
|
|
|
@ -2,10 +2,14 @@
|
||||||
interface Post {
|
interface Post {
|
||||||
id: string
|
id: string
|
||||||
slug: string
|
slug: string
|
||||||
body: string
|
title: string
|
||||||
data: Record<string, any>
|
html: string
|
||||||
collection: string
|
excerpt: string
|
||||||
render: any
|
feature_image: string
|
||||||
|
published_at: string
|
||||||
|
reading_time: number
|
||||||
|
tags: Array<{ name: string, slug: string }>
|
||||||
|
primary_author: { name: string, profile_image: string }
|
||||||
}
|
}
|
||||||
|
|
||||||
withDefaults(defineProps<{
|
withDefaults(defineProps<{
|
||||||
|
@ -19,17 +23,9 @@ function getDate(date: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHref(post: Post) {
|
function getHref(post: Post) {
|
||||||
if (post.data.redirect)
|
|
||||||
return post.data.redirect
|
|
||||||
return `/posts/${post.slug}`
|
return `/posts/${post.slug}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTarget(post: Post) {
|
|
||||||
if (post.data.redirect)
|
|
||||||
return '_blank'
|
|
||||||
return '_self'
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSameYear(a: Date | string | number, b: Date | string | number) {
|
function isSameYear(a: Date | string | number, b: Date | string | number) {
|
||||||
return a && b && getYear(a) === getYear(b)
|
return a && b && getYear(a) === getYear(b)
|
||||||
}
|
}
|
||||||
|
@ -46,30 +42,26 @@ function getYear(date: Date | string | number) {
|
||||||
nothing here yet.
|
nothing here yet.
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<li v-for="(post, index) in list " :key="post.data.title" mb-8>
|
<li v-for="(post, index) in list " :key="post.id" mb-8>
|
||||||
<div v-if="!isSameYear(post.data.date, list[index - 1]?.data.date)" select-none relative h18 pointer-events-none>
|
<div v-if="!isSameYear(post.published_at, list[index - 1]?.published_at)" select-none relative h18 pointer-events-none>
|
||||||
<span text-7em color-transparent font-bold text-stroke-2 text-stroke-hex-aaa op14 absolute top--0.2em>
|
<span text-7em color-transparent font-bold text-stroke-2 text-stroke-hex-aaa op14 absolute top--0.2em>
|
||||||
{{ getYear(post.data.date) }}
|
{{ getYear(post.published_at) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<a text-lg lh-tight nav-link flex="~ col gap-2" :aria-label="post.data.title" :target="getTarget(post)" :href="getHref(post)">
|
<a text-lg lh-tight nav-link flex="~ col gap-2" :aria-label="post.title" :href="getHref(post)">
|
||||||
<div flex="~ col md:row gap-2 md:items-center">
|
<div flex="~ col md:row gap-2 md:items-center">
|
||||||
<div flex="~ gap-2 items-center text-wrap">
|
<div flex="~ gap-2 items-center text-wrap">
|
||||||
<span lh-normal>
|
<span lh-normal>
|
||||||
<i v-if="post.data.draft" text-base vertical-mid i-ri-draft-line />
|
{{ post.title }}
|
||||||
{{ post.data.title }}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div opacity-50 text-sm ws-nowrap flex="~ gap-2 items-center">
|
<div opacity-50 text-sm ws-nowrap flex="~ gap-2 items-center">
|
||||||
<i v-if="post.data.redirect" text-base i-ri-external-link-line />
|
<time v-if="post.published_at" :datetime="getDate(post.published_at)">{{ new Date(post.published_at).toLocaleDateString() }}</time>
|
||||||
<i v-if="post.data.recording || post.data.video" text-base i-ri:film-line />
|
<span v-if="post.reading_time">· {{ post.reading_time }} min read</span>
|
||||||
<time v-if="post.data.date" :datetime="getDate(post.data.date)">{{ post.data.date.split(',')[0] }}</time>
|
<span v-if="post.tags && post.tags.length">· {{ post.tags[0].name }}</span>
|
||||||
<span v-if="post.data.duration">· {{ post.data.duration }}</span>
|
|
||||||
<span v-if="post.data.tag">· {{ post.data.tag }}</span>
|
|
||||||
<span v-if="post.data.lang && post.data.lang.includes('zh')">· 中文</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div opacity-50 text-sm>{{ post.data.description }}</div>
|
<div opacity-50 text-sm>{{ post.excerpt }}</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -12,6 +12,7 @@ const { ...head } = Astro.props
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
<meta name="darkreader-lock">
|
||||||
<BaseHead {...head} />
|
<BaseHead {...head} />
|
||||||
<ViewTransitions />
|
<ViewTransitions />
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -2,23 +2,16 @@
|
||||||
import BaseLayout from '@/layouts/BaseLayout.astro'
|
import BaseLayout from '@/layouts/BaseLayout.astro'
|
||||||
import ListPosts from '@/components/ListPosts.vue'
|
import ListPosts from '@/components/ListPosts.vue'
|
||||||
import siteConfig from '@/site-config'
|
import siteConfig from '@/site-config'
|
||||||
import { getPosts } from '@/utils/posts'
|
import { posts } from '@/utils/ghost'
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
|
||||||
const paths = siteConfig.page.blogLinks.map((nav) => {
|
|
||||||
const href = nav.href.replace('/blog', '')
|
|
||||||
return {
|
|
||||||
params: {
|
|
||||||
path: href === '' ? undefined : href.replace(/^\/+|\/+$/g, ''),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return paths
|
|
||||||
}
|
|
||||||
|
|
||||||
const { path } = Astro.params
|
const { path } = Astro.params
|
||||||
|
|
||||||
const posts = await getPosts(path)
|
const ghostPosts = await posts
|
||||||
|
.browse({
|
||||||
|
limit: 'all',
|
||||||
|
include: ['tags', 'authors'],
|
||||||
|
filter: path ? `tag:${path}` : undefined
|
||||||
|
})
|
||||||
|
|
||||||
function activeLink(pathname: string) {
|
function activeLink(pathname: string) {
|
||||||
return Astro.url.pathname.replace(/\/+/g, '/').replace(/\/$/, '') === pathname
|
return Astro.url.pathname.replace(/\/+/g, '/').replace(/\/$/, '') === pathname
|
||||||
|
@ -44,5 +37,5 @@ function activeLink(pathname: string) {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<ListPosts list={posts} />
|
<ListPosts list={ghostPosts} />
|
||||||
</BaseLayout>
|
</BaseLayout>
|
|
@ -2,7 +2,6 @@
|
||||||
import BaseLayout from '@/layouts/BaseLayout.astro'
|
import BaseLayout from '@/layouts/BaseLayout.astro'
|
||||||
import siteConfig from '@/site-config'
|
import siteConfig from '@/site-config'
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout description={siteConfig.description}>
|
<BaseLayout description={siteConfig.description}>
|
||||||
<article class="prose">
|
<article class="prose">
|
||||||
<h1 class="text-title">Vitesse theme</h1>
|
<h1 class="text-title">Vitesse theme</h1>
|
||||||
|
|
|
@ -1,47 +1,44 @@
|
||||||
---
|
---
|
||||||
import BaseLayout from '@/layouts/BaseLayout.astro'
|
import BaseLayout from '@/layouts/BaseLayout.astro'
|
||||||
import { type CollectionPosts } from '@/types'
|
import { api } from '@/utils/ghost'
|
||||||
import { getPosts } from '@/utils/posts'
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = await getPosts()
|
const posts = await api.posts
|
||||||
return posts.map((post) => {
|
.browse({
|
||||||
return {
|
limit: 'all',
|
||||||
params: { slug: post.slug },
|
fields: ['slug', 'title']
|
||||||
props: {
|
|
||||||
post,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Error fetching posts:', err);
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
|
||||||
|
return posts.map((post) => ({
|
||||||
|
params: { slug: post.slug },
|
||||||
|
props: { slug: post.slug },
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = { post: CollectionPosts }
|
const { slug } = Astro.props;
|
||||||
|
|
||||||
const { post } = Astro.props
|
let post;
|
||||||
const { title, image, description, date, duration, tag } = post.data
|
post = await api.posts.read({ slug }, { include: ['tags', 'authors'] });
|
||||||
|
if (!post) {
|
||||||
const { Content } = await post.render()
|
return Astro.redirect('/404');
|
||||||
|
|
||||||
function getDate(date: string) {
|
|
||||||
return new Date(date).toISOString()
|
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
<BaseLayout title={post.title} description={post.excerpt} pageType="article">
|
||||||
<BaseLayout title={title} description={description} pageType="article">
|
|
||||||
<article class="prose">
|
<article class="prose">
|
||||||
<h1>{title}</h1>
|
<h1>{post.title}</h1>
|
||||||
<p op-50>
|
<p op-50>
|
||||||
{date && <time datetime={getDate(date)}>{date.split(',')}</time>}
|
{post.published_at && <time datetime={post.published_at}>{new Date(post.published_at).toLocaleDateString()}</time>}
|
||||||
{duration && <span>· {duration}</span>}
|
{post.reading_time && <span>· {post.reading_time} min read</span>}
|
||||||
{tag && <span>· {tag}</span>}
|
{post.primary_tag && <span>· {post.primary_tag.name}</span>}
|
||||||
</p>
|
</p>
|
||||||
{
|
{post.feature_image && (
|
||||||
image && (
|
<img width="640" height="360" src={post.feature_image} alt={post.feature_image_alt || ''} />
|
||||||
<p>
|
)}
|
||||||
<img width="640" height="360" src={image.src} alt={image.alt || ''} />
|
|
||||||
</p>
|
<div set:html={post.html}></div>
|
||||||
)
|
|
||||||
}
|
|
||||||
<Content />
|
|
||||||
</article>
|
</article>
|
||||||
</BaseLayout>
|
</BaseLayout>
|
|
@ -47,14 +47,6 @@ export const siteConfig = {
|
||||||
text: 'Blog',
|
text: 'Blog',
|
||||||
href: '/blog',
|
href: '/blog',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: 'Notes',
|
|
||||||
href: '/blog/notes',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Talks',
|
|
||||||
href: '/blog/talks',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: 'Projects',
|
text: 'Projects',
|
||||||
href: '/projects',
|
href: '/projects',
|
||||||
|
@ -66,15 +58,7 @@ export const siteConfig = {
|
||||||
{
|
{
|
||||||
text: 'Blog',
|
text: 'Blog',
|
||||||
href: '/blog',
|
href: '/blog',
|
||||||
},
|
}
|
||||||
{
|
|
||||||
text: 'Notes',
|
|
||||||
href: '/blog/notes',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Talks',
|
|
||||||
href: '/blog/talks',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
|
|
13
src/utils/ghost.ts
Normal file
13
src/utils/ghost.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import GhostContentAPI from '@tryghost/content-api';
|
||||||
|
|
||||||
|
export const api = new GhostContentAPI({
|
||||||
|
url: import.meta.env.CONTENT_API_URL,
|
||||||
|
key: import.meta.env.CONTENT_API_KEY,
|
||||||
|
version: 'v5.0',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const posts = api.posts
|
||||||
|
export const tags = api.tags
|
||||||
|
export const authors = api.authors
|
||||||
|
export const pages = api.pages
|
||||||
|
export const settings = api.settings
|
Loading…
Reference in a new issue