Compare commits

...

35 commits

Author SHA1 Message Date
Daniel Roe
5b37047b00
refactor: simplify handler and remove opengraph section 2022-12-12 23:06:57 +00:00
Daniel Roe
7b973811c0
refactor: remove opengraph implementation for now 2022-12-12 23:06:26 +00:00
Daniel Roe
83a4ee75d0
refactor: remove extra computed 2022-12-12 22:49:23 +00:00
Daniel Roe
705ce6ada4
refactor: try fetching images (for netlify cache) 2022-12-12 22:46:22 +00:00
Shinigami92
e18443ab6f fallback on error 2022-12-12 23:07:56 +01:00
Shinigami92
200bc3d3f1 use sendError for other 4xx errors 2022-12-12 22:46:37 +01:00
Shinigami92
27c0c4d6f2 try sendError 2022-12-12 22:41:22 +01:00
Shinigami
49a9291339
Merge branch 'main' into feat-increase-status-preview-card-image-quality 2022-12-12 22:18:51 +01:00
Shinigami92
eab2342d91 use 404 2022-12-12 22:18:29 +01:00
Shinigami92
a650b1f369 reject http urls 2022-12-12 22:13:23 +01:00
Shinigami92
174b2b2d83 throw 404 2022-12-12 21:59:46 +01:00
Daniel Roe
bb013ddd18
fix: expand og:image regexp 2022-12-12 20:58:03 +00:00
Daniel Roe
797b99f122
refactor: only enable maxAge locally 2022-12-12 20:54:32 +00:00
Daniel Roe
e88d255c07
refactor: use runtimeConfig 2022-12-12 20:51:50 +00:00
Shinigami92
5e717cac03 fix fallbackUrl 2022-12-12 20:56:43 +01:00
Shinigami
49290b7386
Merge branch 'main' into feat-increase-status-preview-card-image-quality 2022-12-12 20:07:25 +01:00
Shinigami92
5da564dda4 fix comment 2022-12-12 20:06:57 +01:00
Shinigami92
cfacff87be remove log 2022-12-12 19:54:58 +01:00
Shinigami92
dff937aa89 use new glob 2022-12-12 19:29:57 +01:00
Shinigami92
ed091d284f use srcset 2022-12-12 18:43:38 +01:00
Shinigami92
2f72c03fd9 pass url as path variable 2022-12-12 16:53:43 +01:00
Shinigami92
26bc4e7251 more safe 2022-12-12 16:31:29 +01:00
Shinigami92
a34e7e23f0 Add opengraph types 2022-12-12 16:27:33 +01:00
Shinigami92
0f1937340d use routeRules cache 2022-12-12 16:15:26 +01:00
Shinigami92
b90479d169 testing 2022-12-12 16:07:24 +01:00
Shinigami92
bd0a2517c6 fallback to hybridGraph 2022-12-12 16:06:35 +01:00
Shinigami92
a4eae9891b Only request opengraph if api key is defined 2022-12-12 16:02:28 +01:00
Shinigami92
2c3e0253f6 Only call opengraph if needed 2022-12-12 16:00:26 +01:00
Shinigami92
2a819c6d0c iterate 2022-12-12 15:55:57 +01:00
Shinigami92
19c8393c7c use cache via nuxt config 2022-12-12 14:26:30 +01:00
Shinigami
f73219f9bd
Merge branch 'main' into feat-increase-status-preview-card-image-quality 2022-12-12 12:26:03 +01:00
Shinigami
32e68b6c65
Merge branch 'main' into feat-increase-status-preview-card-image-quality 2022-12-11 12:52:49 +01:00
Shinigami92
5607c2fe37 update lastUsed 2022-12-11 01:04:37 +01:00
Shinigami92
4e81d0e27d improve 2022-12-10 23:27:06 +01:00
Shinigami92
cab3ed4ad4 feat: improve status image quality 2022-12-10 23:09:11 +01:00
5 changed files with 72 additions and 3 deletions

View file

@ -10,3 +10,5 @@ NUXT_STORAGE_DRIVER=
NUXT_STORAGE_FS_BASE= NUXT_STORAGE_FS_BASE=
NUXT_PUBLIC_DISABLE_VERSION_CHECK= NUXT_PUBLIC_DISABLE_VERSION_CHECK=
NUXT_OPENGRAPH_API=

View file

@ -17,7 +17,7 @@ export default defineComponent({
required: false, required: false,
}, },
}, },
setup(props, { attrs }) { setup(props, { attrs, emit }) {
const placeholderSrc = ref<string>() const placeholderSrc = ref<string>()
const isLoaded = ref(false) const isLoaded = ref(false)
@ -26,6 +26,9 @@ export default defineComponent({
img.onload = () => { img.onload = () => {
isLoaded.value = true isLoaded.value = true
} }
img.onerror = (ev) => {
emit('onerror', ev)
}
img.src = props.src img.src = props.src
if (props.srcset) if (props.srcset)
img.srcset = props.srcset img.srcset = props.srcset

View file

@ -11,6 +11,11 @@ const props = defineProps<{
const alt = $computed(() => `${props.card.title} - ${props.card.title}`) const alt = $computed(() => `${props.card.title} - ${props.card.title}`)
const isSquare = $computed(() => props.smallPictureOnly || props.card.width === props.card.height) const isSquare = $computed(() => props.smallPictureOnly || props.card.width === props.card.height)
const providerName = $computed(() => props.card.providerName ? props.card.providerName : new URL(props.card.url).hostname) const providerName = $computed(() => props.card.providerName ? props.card.providerName : new URL(props.card.url).hostname)
const useFallback = ref(false)
const imageSrcset = $computed(() => props.card.image
? `${props.card.image}${useFallback.value ? '' : `, /api/og-image/${encodeURIComponent(props.card.url)} 2x`}`
: '',
)
// TODO: handle card.type: 'photo' | 'video' | 'rich'; // TODO: handle card.type: 'photo' | 'video' | 'rich';
</script> </script>
@ -42,10 +47,13 @@ const providerName = $computed(() => props.card.providerName ? props.card.provid
<CommonBlurhash <CommonBlurhash
:blurhash="card.blurhash" :blurhash="card.blurhash"
:src="card.image" :src="card.image"
:srcset="imageSrcset"
:width="card.width" :width="card.width"
:height="card.height" :height="card.height"
:alt="alt" :alt="alt"
w-full h-full object-cover w-full
h-full object-cover
@onerror="useFallback = true"
/> />
</div> </div>
<div <div

View file

@ -1,6 +1,6 @@
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url'
import Inspect from 'vite-plugin-inspect' import Inspect from 'vite-plugin-inspect'
import { isCI } from 'std-env' import { isCI, isDevelopment } from 'std-env'
import { i18n } from './config/i18n' import { i18n } from './config/i18n'
const isPreview = process.env.PULL_REQUEST === 'true' const isPreview = process.env.PULL_REQUEST === 'true'
@ -65,6 +65,7 @@ export default defineNuxtConfig({
namespaceId: '', namespaceId: '',
apiToken: '', apiToken: '',
}, },
opengraphApi: '',
public: { public: {
env: isCI ? isPreview ? 'staging' : 'production' : 'local', env: isCI ? isPreview ? 'staging' : 'production' : 'local',
translateApi: '', translateApi: '',
@ -86,6 +87,14 @@ export default defineNuxtConfig({
crawlLinks: false, crawlLinks: false,
routes: ['/', '/200.html'], routes: ['/', '/200.html'],
}, },
routeRules: {
'/api/og-image/**': {
static: isCI,
cache: !isCI && !isDevelopment
? { maxAge: 86400 } // 1 day
: {},
},
},
}, },
app: { app: {
keepalive: true, keepalive: true,

View file

@ -0,0 +1,47 @@
// This API-Endpoint will be cached via netlify builder function -> nitro.routeRules['/api/og-image/**']
export default defineEventHandler(async (event) => {
const { url } = getRouterParams(event)
const cardUrl = decodeURIComponent(url || '')
if (!cardUrl) {
sendError(event, {
statusCode: 422,
fatal: false,
message: 'Missing cardUrl.',
name: 'OgImageError',
unhandled: false,
})
return
}
// First we want to try to get the og:image from the html
// But sometimes it is not included due to async JS loading
const ogImageUrl = await resolveOgImageUrlManually(cardUrl)
if (!ogImageUrl) {
// If nothing helped, send 404 so the srcset can fallback to the default image
sendError(event, {
statusCode: 404,
fatal: false,
message: 'Could not find og:image.',
name: 'OgImageError',
unhandled: false,
})
return
}
return $fetch(ogImageUrl, {
responseType: 'stream',
})
})
const OG_IMAGE_RE = /<meta[^>]*property="og:image"[^>]*content="([^"]+)"|<meta[^>]*content="([^"]+)"[^>]*property="og:image"/
async function resolveOgImageUrlManually(cardUrl: string): Promise<string> {
const html = await $fetch<string>(cardUrl)
const match = html.match(OG_IMAGE_RE)
return match?.[1] ?? match?.[2] ?? ''
}