feat: new article body stuffz
Signed-off-by: Filipe Medeiros <hello@filipesm.eu>
This commit is contained in:
parent
d42271eb15
commit
09852de001
|
@ -1,8 +1,7 @@
|
||||||
import react from '@astrojs/react';
|
|
||||||
import tailwind from '@astrojs/tailwind';
|
import tailwind from '@astrojs/tailwind';
|
||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [react(), tailwind()],
|
integrations: [tailwind()],
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,14 @@ export const forBlogPostPage = groq`
|
||||||
{
|
{
|
||||||
"slug": slug.current,
|
"slug": slug.current,
|
||||||
title,
|
title,
|
||||||
content,
|
content[]{
|
||||||
|
_type == 'image' => {
|
||||||
|
...,
|
||||||
|
"lqip": @.asset->metadata.lqip,
|
||||||
|
"alt": @.asset->altText
|
||||||
|
},
|
||||||
|
_type != 'image' => @
|
||||||
|
},
|
||||||
headerImage,
|
headerImage,
|
||||||
publishDate
|
publishDate
|
||||||
}`;
|
}`;
|
||||||
|
|
10
frontend/lib/cms/urlFor.ts
Normal file
10
frontend/lib/cms/urlFor.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import urlBuilder from '@sanity/image-url';
|
||||||
|
import type { SanityImageSource } from '@sanity/image-url/lib/types/types';
|
||||||
|
|
||||||
|
import client from './client';
|
||||||
|
|
||||||
|
const builder = urlBuilder(client);
|
||||||
|
|
||||||
|
export default function urlFor(source: SanityImageSource) {
|
||||||
|
return builder.image(source);
|
||||||
|
}
|
|
@ -11,19 +11,16 @@
|
||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/react": "^2.1.1",
|
|
||||||
"@astrojs/tailwind": "^3.1.1",
|
"@astrojs/tailwind": "^3.1.1",
|
||||||
"@portabletext/react": "^2.0.2",
|
"@portabletext/react": "^2.0.2",
|
||||||
"@sanity/client": "^5.4.2",
|
"@sanity/client": "^5.4.2",
|
||||||
|
"@sanity/image-url": "^1.0.2",
|
||||||
"astro": "^2.2.1",
|
"astro": "^2.2.1",
|
||||||
"react": "^18.2.0",
|
"astro-portabletext": "^0.8.0"
|
||||||
"react-dom": "^18.2.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@portabletext/types": "^2.0.2",
|
"@portabletext/types": "^2.0.2",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
|
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
|
||||||
"@types/react": "^18.0.21",
|
|
||||||
"@types/react-dom": "^18.0.6",
|
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"groq": "^3.8.3",
|
"groq": "^3.8.3",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.21",
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/react':
|
|
||||||
specifier: ^2.1.1
|
|
||||||
version: 2.1.1(@types/react-dom@18.0.11)(@types/react@18.0.33)(react-dom@18.2.0)(react@18.2.0)
|
|
||||||
'@astrojs/tailwind':
|
'@astrojs/tailwind':
|
||||||
specifier: ^3.1.1
|
specifier: ^3.1.1
|
||||||
version: 3.1.1(astro@2.2.1)(tailwindcss@3.3.1)
|
version: 3.1.1(astro@2.2.1)(tailwindcss@3.3.1)
|
||||||
|
@ -13,18 +10,15 @@ dependencies:
|
||||||
'@sanity/client':
|
'@sanity/client':
|
||||||
specifier: ^5.4.2
|
specifier: ^5.4.2
|
||||||
version: 5.4.2
|
version: 5.4.2
|
||||||
|
'@sanity/image-url':
|
||||||
|
specifier: ^1.0.2
|
||||||
|
version: 1.0.2
|
||||||
astro:
|
astro:
|
||||||
specifier: ^2.2.1
|
specifier: ^2.2.1
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
groq:
|
astro-portabletext:
|
||||||
specifier: ^3.8.3
|
specifier: ^0.8.0
|
||||||
version: 3.8.3
|
version: 0.8.0
|
||||||
react:
|
|
||||||
specifier: ^18.2.0
|
|
||||||
version: 18.2.0
|
|
||||||
react-dom:
|
|
||||||
specifier: ^18.2.0
|
|
||||||
version: 18.2.0(react@18.2.0)
|
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@portabletext/types':
|
'@portabletext/types':
|
||||||
|
@ -33,15 +27,12 @@ devDependencies:
|
||||||
'@trivago/prettier-plugin-sort-imports':
|
'@trivago/prettier-plugin-sort-imports':
|
||||||
specifier: ^4.1.1
|
specifier: ^4.1.1
|
||||||
version: 4.1.1(prettier@2.8.7)
|
version: 4.1.1(prettier@2.8.7)
|
||||||
'@types/react':
|
|
||||||
specifier: ^18.0.21
|
|
||||||
version: 18.0.33
|
|
||||||
'@types/react-dom':
|
|
||||||
specifier: ^18.0.6
|
|
||||||
version: 18.0.11
|
|
||||||
autoprefixer:
|
autoprefixer:
|
||||||
specifier: ^10.4.14
|
specifier: ^10.4.14
|
||||||
version: 10.4.14(postcss@8.4.21)
|
version: 10.4.14(postcss@8.4.21)
|
||||||
|
groq:
|
||||||
|
specifier: ^3.8.3
|
||||||
|
version: 3.8.3
|
||||||
postcss:
|
postcss:
|
||||||
specifier: ^8.4.21
|
specifier: ^8.4.21
|
||||||
version: 8.4.21
|
version: 8.4.21
|
||||||
|
@ -118,25 +109,6 @@ packages:
|
||||||
prismjs: 1.29.0
|
prismjs: 1.29.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@astrojs/react@2.1.1(@types/react-dom@18.0.11)(@types/react@18.0.33)(react-dom@18.2.0)(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-nIcDFnn5H4FKGoSBYXZr95RIQvpcTNRcVV1hvUQifO0F5hQsgb0PVyk6TG4JWxiPGY4Jt4MVQb5JaaDQHlHu4w==}
|
|
||||||
engines: {node: '>=16.12.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': ^17.0.50 || ^18.0.21
|
|
||||||
'@types/react-dom': ^17.0.17 || ^18.0.6
|
|
||||||
react: ^17.0.2 || ^18.0.0
|
|
||||||
react-dom: ^17.0.2 || ^18.0.0
|
|
||||||
dependencies:
|
|
||||||
'@babel/core': 7.21.4
|
|
||||||
'@babel/plugin-transform-react-jsx': 7.21.0(@babel/core@7.21.4)
|
|
||||||
'@types/react': 18.0.33
|
|
||||||
'@types/react-dom': 18.0.11
|
|
||||||
react: 18.2.0
|
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@astrojs/tailwind@3.1.1(astro@2.2.1)(tailwindcss@3.3.1):
|
/@astrojs/tailwind@3.1.1(astro@2.2.1)(tailwindcss@3.3.1):
|
||||||
resolution: {integrity: sha512-Wx/ZtVnmtfqHWGVzvUEYZm8rufVKVgDIef0q6fzwUxoT1EpTTwBkTbpnzooogewMLOh2eTscasGe3Ih2HC1wVA==}
|
resolution: {integrity: sha512-Wx/ZtVnmtfqHWGVzvUEYZm8rufVKVgDIef0q6fzwUxoT1EpTTwBkTbpnzooogewMLOh2eTscasGe3Ih2HC1wVA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -754,6 +726,11 @@ packages:
|
||||||
eventsource: 2.0.2
|
eventsource: 2.0.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@sanity/image-url@1.0.2:
|
||||||
|
resolution: {integrity: sha512-C4+jb2ny3ZbMgEkLd7Z3C75DsxcTEoE+axXQJsQ75ou0AKWGdVsP351hqK6mJUUxn5HCSlu3vznoh7Yljye4cQ==}
|
||||||
|
engines: {node: '>=10.0.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@trivago/prettier-plugin-sort-imports@4.1.1(prettier@2.8.7):
|
/@trivago/prettier-plugin-sort-imports@4.1.1(prettier@2.8.7):
|
||||||
resolution: {integrity: sha512-dQ2r2uzNr1x6pJsuh/8x0IRA3CBUB+pWEW3J/7N98axqt7SQSm+2fy0FLNXvXGg77xEDC7KHxJlHfLYyi7PDcw==}
|
resolution: {integrity: sha512-dQ2r2uzNr1x6pJsuh/8x0IRA3CBUB+pWEW3J/7N98axqt7SQSm+2fy0FLNXvXGg77xEDC7KHxJlHfLYyi7PDcw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -851,28 +828,10 @@ packages:
|
||||||
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
|
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/prop-types@15.7.5:
|
|
||||||
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
|
|
||||||
|
|
||||||
/@types/react-dom@18.0.11:
|
|
||||||
resolution: {integrity: sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==}
|
|
||||||
dependencies:
|
|
||||||
'@types/react': 18.0.33
|
|
||||||
|
|
||||||
/@types/react@18.0.33:
|
|
||||||
resolution: {integrity: sha512-sHxzVxeanvQyQ1lr8NSHaj0kDzcNiGpILEVt69g9S31/7PfMvNCKLKcsHw4lYKjs3cGNJjXSP4mYzX43QlnjNA==}
|
|
||||||
dependencies:
|
|
||||||
'@types/prop-types': 15.7.5
|
|
||||||
'@types/scheduler': 0.16.3
|
|
||||||
csstype: 3.1.2
|
|
||||||
|
|
||||||
/@types/resolve@1.20.2:
|
/@types/resolve@1.20.2:
|
||||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/scheduler@0.16.3:
|
|
||||||
resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
|
|
||||||
|
|
||||||
/@types/unist@2.0.6:
|
/@types/unist@2.0.6:
|
||||||
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
|
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -958,6 +917,13 @@ packages:
|
||||||
resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
|
resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/astro-portabletext@0.8.0:
|
||||||
|
resolution: {integrity: sha512-2zA5TJ70Uhd4XfLlcTgxFMe202mEyB4V5R81KsjrP0nqBBHZLk1MaWxHPNq8Bz9KrF/u0mNYp+HFMQ/L/TDW7A==}
|
||||||
|
dependencies:
|
||||||
|
'@portabletext/toolkit': 2.0.1
|
||||||
|
'@portabletext/types': 2.0.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/astro@2.2.1:
|
/astro@2.2.1:
|
||||||
resolution: {integrity: sha512-yYPRzh3su38bi3VBCKmYAUBkQSaFQMKFsu8JAVDzFRoGLbskJ/6JkDX2abSB9/iRug8GAKaH/FWxXOTzIsSQ7Q==}
|
resolution: {integrity: sha512-yYPRzh3su38bi3VBCKmYAUBkQSaFQMKFsu8JAVDzFRoGLbskJ/6JkDX2abSB9/iRug8GAKaH/FWxXOTzIsSQ7Q==}
|
||||||
engines: {node: '>=16.12.0', npm: '>=6.14.0'}
|
engines: {node: '>=16.12.0', npm: '>=6.14.0'}
|
||||||
|
@ -1269,9 +1235,6 @@ packages:
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
/csstype@3.1.2:
|
|
||||||
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
|
|
||||||
|
|
||||||
/debug@4.3.4:
|
/debug@4.3.4:
|
||||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
|
@ -1629,7 +1592,7 @@ packages:
|
||||||
/groq@3.8.3:
|
/groq@3.8.3:
|
||||||
resolution: {integrity: sha512-2zB3MseKzoZ+zySVJBB3u/tNYn4nEepF8O3fNa71ojD5UwG0Ra2kzNR9sbojF+eToazCHKcvPW73OfB9yYrYsQ==}
|
resolution: {integrity: sha512-2zB3MseKzoZ+zySVJBB3u/tNYn4nEepF8O3fNa71ojD5UwG0Ra2kzNR9sbojF+eToazCHKcvPW73OfB9yYrYsQ==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/has-flag@3.0.0:
|
/has-flag@3.0.0:
|
||||||
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
|
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
|
||||||
|
@ -2817,16 +2780,6 @@ packages:
|
||||||
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
|
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
/react-dom@18.2.0(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^18.2.0
|
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
react: 18.2.0
|
|
||||||
scheduler: 0.23.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/react@18.2.0:
|
/react@18.2.0:
|
||||||
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -3038,12 +2991,6 @@ packages:
|
||||||
suf-log: 2.5.3
|
suf-log: 2.5.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/scheduler@0.23.0:
|
|
||||||
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
|
|
||||||
dependencies:
|
|
||||||
loose-envify: 1.4.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/section-matter@1.0.0:
|
/section-matter@1.0.0:
|
||||||
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
|
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
import { PortableText, PortableTextReactComponents } from '@portabletext/react';
|
|
||||||
import type { PortableTextBlock } from '@portabletext/types';
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
content: PortableTextBlock[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const components: Partial<PortableTextReactComponents> = {
|
|
||||||
block: {
|
|
||||||
h1: ({ children }) => (
|
|
||||||
<h2 className="mb-2 mt-4 text-3xl font-medium">{children}</h2>
|
|
||||||
),
|
|
||||||
h2: ({ children }) => (
|
|
||||||
<h3 className="mb-2 mt-3 text-2xl font-medium">{children}</h3>
|
|
||||||
),
|
|
||||||
h3: ({ children }) => (
|
|
||||||
<h4 className="mb-2 text-xl font-medium">{children}</h4>
|
|
||||||
),
|
|
||||||
h4: ({ children }) => (
|
|
||||||
<h5 className="mb-2 text-lg font-medium">{children}</h5>
|
|
||||||
),
|
|
||||||
h5: ({ children }) => (
|
|
||||||
<h6 className="mb-2 text-lg underline">{children}</h6>
|
|
||||||
),
|
|
||||||
h6: ({ children }) => <h6 className="mb-2 text-lg">{children}</h6>,
|
|
||||||
normal: ({ children }) => <p className="mb-2">{children}</p>,
|
|
||||||
},
|
|
||||||
marks: {
|
|
||||||
code: ({ children }) => (
|
|
||||||
<code className="bg-stone-800 p-0.5 px-1 text-white">{children}</code>
|
|
||||||
),
|
|
||||||
link: ({ children, value }) => {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
className="text-primary-800 underline hover:text-primary-700"
|
|
||||||
href={value.href}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
list: {
|
|
||||||
bullet: ({ children }) => (
|
|
||||||
<ul className="list-disc [counter-reset:list-counter]">{children}</ul>
|
|
||||||
),
|
|
||||||
number: ({ children }) => (
|
|
||||||
<ol className="[counter-reset:list-counter]">{children}</ol>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
listItem: {
|
|
||||||
bullet: ({ children }) => <li className="mb-1 ml-5 pl-2">{children}</li>,
|
|
||||||
number: ({ children, value }) => (
|
|
||||||
<li
|
|
||||||
className={`mb-1 pl-2 [counter-increment:list-counter] before:pr-2 before:content-[counter(list-counter)'.'] data-[list-type=lower-latin]:before:content-[counter(list-counter,lower-latin)')'] data-[list-type=lower-roman]:before:content-[counter(list-counter,lower-roman)'.'] ${
|
|
||||||
(value.level ?? 1) !== 1 ? 'ml-5' : ''
|
|
||||||
}`}
|
|
||||||
data-list-type={
|
|
||||||
(value.level ?? 1) % 3 === 1
|
|
||||||
? 'decimal'
|
|
||||||
: (value.level ?? 1) % 3 === 2
|
|
||||||
? 'lower-latin'
|
|
||||||
: 'lower-roman'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</li>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function BlogPostContent({ content }: Props) {
|
|
||||||
return (
|
|
||||||
<div className="text-justify">
|
|
||||||
<PortableText components={components} value={content} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
57
frontend/src/components/portableText/BlogPostContent.astro
Normal file
57
frontend/src/components/portableText/BlogPostContent.astro
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
---
|
||||||
|
import { PortableText } from 'astro-portabletext';
|
||||||
|
import type { PortableTextBlock } from '@portabletext/types';
|
||||||
|
|
||||||
|
import ShowableFigure from './components/ShowableFigure.astro';
|
||||||
|
import NumberListItem from './components/NumberListItem.astro';
|
||||||
|
import InlineLink from './components/InlineLink.astro';
|
||||||
|
import InlineCode from './components/InlineCode.astro';
|
||||||
|
import BulletList from './components/BulletList.astro';
|
||||||
|
import NumberList from './components/NumberList.astro';
|
||||||
|
import BulletListItem from './components/BulletListItem.astro';
|
||||||
|
import Heading1 from './components/Heading1.astro';
|
||||||
|
import Heading2 from './components/Heading2.astro';
|
||||||
|
import Heading3 from './components/Heading3.astro';
|
||||||
|
import Heading4 from './components/Heading4.astro';
|
||||||
|
import Heading5 from './components/Heading5.astro';
|
||||||
|
import Heading6 from './components/Heading6.astro';
|
||||||
|
import Paragraph from './components/Paragraph.astro';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
content: PortableTextBlock[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const components = {
|
||||||
|
type: {
|
||||||
|
image: ShowableFigure,
|
||||||
|
},
|
||||||
|
block: {
|
||||||
|
h1: Heading1,
|
||||||
|
h2: Heading2,
|
||||||
|
h3: Heading3,
|
||||||
|
h4: Heading4,
|
||||||
|
h5: Heading5,
|
||||||
|
h6: Heading6,
|
||||||
|
normal: Paragraph,
|
||||||
|
},
|
||||||
|
marks: {
|
||||||
|
code: InlineCode,
|
||||||
|
link: InlineLink,
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
bullet: BulletList,
|
||||||
|
number: NumberList,
|
||||||
|
},
|
||||||
|
listItem: {
|
||||||
|
bullet: BulletListItem,
|
||||||
|
number: NumberListItem,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { content } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="text-justify">
|
||||||
|
{/* @ts-expect-error */}
|
||||||
|
<PortableText components={components} value={content} />
|
||||||
|
</div>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<ul class="list-disc ps-2 list-inside [counter-reset:list-counter]">
|
||||||
|
<slot />
|
||||||
|
</ul>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<li>
|
||||||
|
<slot />
|
||||||
|
</li>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h2 class="mb-2 mt-4 text-3xl font-medium">
|
||||||
|
<slot />
|
||||||
|
</h2>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h3 class="mb-2 mt-3 text-2xl font-medium">
|
||||||
|
<slot />
|
||||||
|
</h3>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h4 class="mb-2 text-xl font-medium">
|
||||||
|
<slot />
|
||||||
|
</h4>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h5 class="mb-2 text-lg font-medium">
|
||||||
|
<slot />
|
||||||
|
</h5>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h6 class="mb-2 text-lg underline">
|
||||||
|
<slot />
|
||||||
|
</h6>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<h6 class="mb-2 text-lg">
|
||||||
|
<slot />
|
||||||
|
</h6>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<code class="bg-stone-800 p-0.5 px-1 text-white">
|
||||||
|
<slot />
|
||||||
|
</code>
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
import type { PortableTextLink } from '@portabletext/types';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
value?: PortableTextLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { value } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<a class="text-primary-800 underline hover:text-primary-700" href={value?.href}>
|
||||||
|
<slot />
|
||||||
|
</a>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<ol class="[counter-reset:list-counter] ps-2 list-inside">
|
||||||
|
<slot />
|
||||||
|
</ol>
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
import type { PortableTextListItemBlock } from '@portabletext/types';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
node: PortableTextListItemBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { node: value } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<li
|
||||||
|
class:list={[
|
||||||
|
"[counter-increment:list-counter] before:content-[counter(list-counter)'.'] data-[list-type=lower-latin]:before:content-[counter(list-counter,lower-latin)')'] data-[list-type=lower-roman]:before:content-[counter(list-counter,lower-roman)'.']",
|
||||||
|
]}
|
||||||
|
data-list-type={(value.level ?? 1) % 3 === 1
|
||||||
|
? 'decimal'
|
||||||
|
: (value.level ?? 1) % 3 === 2
|
||||||
|
? 'lower-latin'
|
||||||
|
: 'lower-roman'}
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</li>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<p class="mb-2">
|
||||||
|
<slot />
|
||||||
|
</p>
|
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
import { PortableText } from 'astro-portabletext';
|
||||||
|
import ShowableImage from './ShowableImage.astro';
|
||||||
|
import type { Props as ShowableImageProps } from './ShowableImage.astro';
|
||||||
|
import InlineLink from './InlineLink.astro';
|
||||||
|
|
||||||
|
export interface Props extends ShowableImageProps {}
|
||||||
|
|
||||||
|
const { node: value } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
{
|
||||||
|
!value.caption ? (
|
||||||
|
<ShowableImage {...Astro.props} />
|
||||||
|
) : (
|
||||||
|
<figure class="flex flex-col gap-1 mb-4 mt-4">
|
||||||
|
<ShowableImage {...Astro.props} />
|
||||||
|
<figcaption class="text-sm text-start">
|
||||||
|
<PortableText
|
||||||
|
components={{
|
||||||
|
mark: {
|
||||||
|
// @ts-expect-error
|
||||||
|
link: InlineLink,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
value={value.caption}
|
||||||
|
/>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
import type { PortableTextBlock } from '@portabletext/types';
|
||||||
|
import urlFor from '../../../../lib/cms/urlFor';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
node: BlogPostContentImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BlogPostContentImage {
|
||||||
|
lqip: string;
|
||||||
|
_type: 'image';
|
||||||
|
asset: {
|
||||||
|
_type: 'reference';
|
||||||
|
ref: string;
|
||||||
|
};
|
||||||
|
caption: PortableTextBlock[];
|
||||||
|
alt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { node: value } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<showable-image>
|
||||||
|
<div class="relative" role="button" class="w-full" data-wrapper>
|
||||||
|
<img
|
||||||
|
src={value.lqip}
|
||||||
|
alt={`${value.alt} Quando esta página carrega, esta imagem está desfocada para poupar dados e energia. Podes carregar na imagem para mostrar a imagem completa.`}
|
||||||
|
class="w-full border-2 border-primary-800"
|
||||||
|
data-url={urlFor(value).url()}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
data-tooltip
|
||||||
|
class="text-xs w-10/12 sm:w-1/2 left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 text-center absolute leading-tight bg-primary-900/80 text-white p-3"
|
||||||
|
>
|
||||||
|
<p class="mb-1">
|
||||||
|
Para poupar os teus dados e um bocadinho de energia, tens esta
|
||||||
|
pre-visualização da imagem.
|
||||||
|
</p>
|
||||||
|
<p class="text-sm">
|
||||||
|
Clica na pre-visualização para veres a versão completa.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</showable-image>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
class ShowableImage extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const image = this.querySelector('img')!;
|
||||||
|
const wrapper = this.querySelector('[data-wrapper]')!;
|
||||||
|
const tooltip = this.querySelector('[data-tooltip]')!;
|
||||||
|
|
||||||
|
wrapper.addEventListener('click', () => {
|
||||||
|
image.src = image.dataset.url!;
|
||||||
|
wrapper.role = 'none';
|
||||||
|
tooltip.classList.add('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('showable-image', ShowableImage);
|
||||||
|
</script>
|
|
@ -2,7 +2,7 @@
|
||||||
import type { PortableTextBlock } from '@portabletext/types';
|
import type { PortableTextBlock } from '@portabletext/types';
|
||||||
import client from '../../../../lib/cms/client';
|
import client from '../../../../lib/cms/client';
|
||||||
import { forBlogPostPage } from '../../../../lib/cms/queries/blogPosts';
|
import { forBlogPostPage } from '../../../../lib/cms/queries/blogPosts';
|
||||||
import BlogPostContent from '../../../components/BlogPostContent';
|
import BlogPostContent from '../../../components/portableText/BlogPostContent.astro';
|
||||||
import ButtonLink from '../../../components/ButtonLink.astro';
|
import ButtonLink from '../../../components/ButtonLink.astro';
|
||||||
import PageTitle from '../../../components/PageTitle.astro';
|
import PageTitle from '../../../components/PageTitle.astro';
|
||||||
import Layout from '../../../layouts/Layout.astro';
|
import Layout from '../../../layouts/Layout.astro';
|
||||||
|
|
Loading…
Reference in a new issue