@nuxt/scripts 1.0.0-beta.21 → 1.0.0-beta.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/{BlmrFwhD.js → B7aPLMNo.js} +1 -1
- package/dist/client/_nuxt/{DvbTvDd0.js → BNNMZFwZ.js} +21 -21
- package/dist/client/_nuxt/{BwCYQWJt.js → Bh9fd9qr.js} +1 -1
- package/dist/client/_nuxt/{ZrewjUYk.js → UTi7FhVv.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/7b372941-1db0-4ea4-80d2-a41f53088a98.json +1 -0
- package/dist/client/_nuxt/error-404.DMdWw4vT.css +1 -0
- package/dist/client/_nuxt/error-500.CROTF27X.css +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +2 -2
- package/dist/module.d.ts +2 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +57 -50
- package/dist/registry.mjs +30 -4
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.d.vue.ts +3 -3
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue +14 -1
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMaps.vue.d.ts +3 -3
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.d.vue.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsAdvancedMarkerElement.vue.d.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.d.vue.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsMarker.vue.d.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.d.vue.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolygon.vue.d.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.d.vue.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsPolyline.vue.d.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.d.vue.ts +2 -2
- package/dist/runtime/components/GoogleMaps/ScriptGoogleMapsRectangle.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptBlueskyEmbed.d.vue.ts +87 -0
- package/dist/runtime/components/ScriptBlueskyEmbed.vue +85 -0
- package/dist/runtime/components/ScriptBlueskyEmbed.vue.d.ts +87 -0
- package/dist/runtime/components/ScriptInstagramEmbed.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptInstagramEmbed.vue +4 -1
- package/dist/runtime/components/ScriptInstagramEmbed.vue.d.ts +2 -2
- package/dist/runtime/components/ScriptXEmbed.d.vue.ts +2 -2
- package/dist/runtime/components/ScriptXEmbed.vue +5 -2
- package/dist/runtime/components/ScriptXEmbed.vue.d.ts +2 -2
- package/dist/runtime/registry/bluesky-embed.d.ts +116 -0
- package/dist/runtime/registry/bluesky-embed.js +72 -0
- package/dist/runtime/registry/gravatar.js +2 -2
- package/dist/runtime/registry/schemas.d.ts +20 -3
- package/dist/runtime/registry/schemas.js +20 -3
- package/dist/runtime/registry/x-embed.js +1 -1
- package/dist/runtime/server/bluesky-embed-image.d.ts +2 -0
- package/dist/runtime/server/bluesky-embed-image.js +7 -0
- package/dist/runtime/server/bluesky-embed.d.ts +16 -0
- package/dist/runtime/server/bluesky-embed.js +59 -0
- package/dist/runtime/server/google-maps-geocode-proxy.d.ts +2 -0
- package/dist/runtime/server/google-maps-geocode-proxy.js +34 -0
- package/dist/runtime/server/google-static-maps-proxy.js +1 -12
- package/dist/runtime/server/gravatar-proxy.js +1 -16
- package/dist/runtime/server/instagram-embed-asset.js +8 -42
- package/dist/runtime/server/instagram-embed-image.js +6 -54
- package/dist/runtime/server/instagram-embed.d.ts +16 -0
- package/dist/runtime/server/instagram-embed.js +171 -42
- package/dist/runtime/server/utils/image-proxy.d.ts +12 -0
- package/dist/runtime/server/utils/image-proxy.js +70 -0
- package/dist/runtime/server/x-embed-image.js +5 -49
- package/dist/runtime/types.d.ts +11 -0
- package/dist/runtime/utils.d.ts +1 -0
- package/dist/runtime/utils.js +11 -2
- package/dist/stats.mjs +1 -1
- package/dist/types-source.mjs +18 -6
- package/package.json +8 -7
- package/dist/client/_nuxt/builds/meta/6660a023-888d-415f-b66d-ce774e6f8f11.json +0 -1
- package/dist/client/_nuxt/error-404.CHeaW3dp.css +0 -1
- package/dist/client/_nuxt/error-500.DvOvWme_.css +0 -1
|
@@ -2,8 +2,8 @@ type __VLS_Props = {
|
|
|
2
2
|
options?: Omit<google.maps.RectangleOptions, 'map'>;
|
|
3
3
|
};
|
|
4
4
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
5
|
-
click: (payload: google.maps.MapMouseEvent) => any;
|
|
6
5
|
contextmenu: (payload: google.maps.MapMouseEvent) => any;
|
|
6
|
+
click: (payload: google.maps.MapMouseEvent) => any;
|
|
7
7
|
dblclick: (payload: google.maps.MapMouseEvent) => any;
|
|
8
8
|
drag: (payload: google.maps.MapMouseEvent) => any;
|
|
9
9
|
dragend: (payload: google.maps.MapMouseEvent) => any;
|
|
@@ -15,8 +15,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
15
15
|
mouseup: (payload: google.maps.MapMouseEvent) => any;
|
|
16
16
|
bounds_changed: () => any;
|
|
17
17
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
18
|
-
onClick?: ((payload: google.maps.MapMouseEvent) => any) | undefined;
|
|
19
18
|
onContextmenu?: ((payload: google.maps.MapMouseEvent) => any) | undefined;
|
|
19
|
+
onClick?: ((payload: google.maps.MapMouseEvent) => any) | undefined;
|
|
20
20
|
onDblclick?: ((payload: google.maps.MapMouseEvent) => any) | undefined;
|
|
21
21
|
onDrag?: ((payload: google.maps.MapMouseEvent) => any) | undefined;
|
|
22
22
|
onDragend?: ((payload: google.maps.MapMouseEvent) => any) | undefined;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'vue';
|
|
2
|
+
import type { BlueskyEmbedPostData } from '../registry/bluesky-embed.js';
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
/**
|
|
5
|
+
* The Bluesky post URL to embed
|
|
6
|
+
* @example 'https://bsky.app/profile/bsky.app/post/3mgnwwvj3u22a'
|
|
7
|
+
*/
|
|
8
|
+
postUrl: string;
|
|
9
|
+
/**
|
|
10
|
+
* Custom API endpoint for fetching post data
|
|
11
|
+
* @default '/_scripts/embed/bluesky'
|
|
12
|
+
*/
|
|
13
|
+
apiEndpoint?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Custom image proxy endpoint
|
|
16
|
+
* @default '/_scripts/embed/bluesky-image'
|
|
17
|
+
*/
|
|
18
|
+
imageProxyEndpoint?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Root element attributes
|
|
21
|
+
*/
|
|
22
|
+
rootAttrs?: HTMLAttributes;
|
|
23
|
+
};
|
|
24
|
+
declare var __VLS_1: {}, __VLS_3: {
|
|
25
|
+
error: import("nuxt/app").NuxtError<unknown> | undefined;
|
|
26
|
+
}, __VLS_5: {
|
|
27
|
+
post: BlueskyEmbedPostData;
|
|
28
|
+
displayName: string;
|
|
29
|
+
handle: string;
|
|
30
|
+
avatar: string;
|
|
31
|
+
avatarOriginal: string;
|
|
32
|
+
isVerified: boolean;
|
|
33
|
+
text: string;
|
|
34
|
+
richText: string;
|
|
35
|
+
langs: string[] | undefined;
|
|
36
|
+
datetime: string;
|
|
37
|
+
createdAt: Date;
|
|
38
|
+
likes: number;
|
|
39
|
+
likesFormatted: string;
|
|
40
|
+
reposts: number;
|
|
41
|
+
repostsFormatted: string;
|
|
42
|
+
replies: number;
|
|
43
|
+
repliesFormatted: string;
|
|
44
|
+
quotes: number;
|
|
45
|
+
quotesFormatted: string;
|
|
46
|
+
images: {
|
|
47
|
+
thumb: string;
|
|
48
|
+
fullsize: string;
|
|
49
|
+
alt: string;
|
|
50
|
+
aspectRatio: {
|
|
51
|
+
width: number;
|
|
52
|
+
height: number;
|
|
53
|
+
} | undefined;
|
|
54
|
+
}[] | undefined;
|
|
55
|
+
externalEmbed: {
|
|
56
|
+
uri: string;
|
|
57
|
+
title: string;
|
|
58
|
+
description: string;
|
|
59
|
+
thumb: string | undefined;
|
|
60
|
+
} | undefined;
|
|
61
|
+
postUrl: string;
|
|
62
|
+
authorUrl: string;
|
|
63
|
+
proxyImage: (url: string) => string;
|
|
64
|
+
};
|
|
65
|
+
type __VLS_Slots = {} & {
|
|
66
|
+
loading?: (props: typeof __VLS_1) => any;
|
|
67
|
+
} & {
|
|
68
|
+
error?: (props: typeof __VLS_3) => any;
|
|
69
|
+
} & {
|
|
70
|
+
default?: (props: typeof __VLS_5) => any;
|
|
71
|
+
};
|
|
72
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
73
|
+
post: import("vue").Ref<BlueskyEmbedPostData | undefined, BlueskyEmbedPostData | undefined>;
|
|
74
|
+
status: import("vue").Ref<import("nuxt/app").AsyncDataRequestStatus, import("nuxt/app").AsyncDataRequestStatus>;
|
|
75
|
+
error: import("vue").Ref<import("nuxt/app").NuxtError<unknown> | undefined, import("nuxt/app").NuxtError<unknown> | undefined>;
|
|
76
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
77
|
+
apiEndpoint: string;
|
|
78
|
+
imageProxyEndpoint: string;
|
|
79
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
80
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
81
|
+
declare const _default: typeof __VLS_export;
|
|
82
|
+
export default _default;
|
|
83
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
84
|
+
new (): {
|
|
85
|
+
$slots: S;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { useAsyncData } from "nuxt/app";
|
|
3
|
+
import { computed } from "vue";
|
|
4
|
+
import { extractBlueskyPostId, facetsToHtml, formatBlueskyDate, formatCount, proxyBlueskyImageUrl } from "../registry/bluesky-embed";
|
|
5
|
+
import { requireRegistryEndpoint } from "../utils";
|
|
6
|
+
const props = defineProps({
|
|
7
|
+
postUrl: { type: String, required: true },
|
|
8
|
+
apiEndpoint: { type: String, required: false, default: "/_scripts/embed/bluesky" },
|
|
9
|
+
imageProxyEndpoint: { type: String, required: false, default: "/_scripts/embed/bluesky-image" },
|
|
10
|
+
rootAttrs: { type: Object, required: false }
|
|
11
|
+
});
|
|
12
|
+
if (!props.apiEndpoint || props.apiEndpoint === "/_scripts/embed/bluesky")
|
|
13
|
+
requireRegistryEndpoint("ScriptBlueskyEmbed", "blueskyEmbed");
|
|
14
|
+
const postId = computed(() => extractBlueskyPostId(props.postUrl));
|
|
15
|
+
const cacheKey = computed(() => `bluesky-embed-${postId.value?.actor}-${postId.value?.rkey}`);
|
|
16
|
+
const { data: post, status, error } = useAsyncData(
|
|
17
|
+
cacheKey,
|
|
18
|
+
() => $fetch(`${props.apiEndpoint}?url=${encodeURIComponent(props.postUrl)}`)
|
|
19
|
+
);
|
|
20
|
+
const slotProps = computed(() => {
|
|
21
|
+
if (!post.value)
|
|
22
|
+
return null;
|
|
23
|
+
const p = post.value;
|
|
24
|
+
return {
|
|
25
|
+
// Raw data
|
|
26
|
+
post: p,
|
|
27
|
+
// Author info
|
|
28
|
+
displayName: p.author.displayName,
|
|
29
|
+
handle: p.author.handle,
|
|
30
|
+
avatar: proxyBlueskyImageUrl(p.author.avatar, props.imageProxyEndpoint),
|
|
31
|
+
avatarOriginal: p.author.avatar,
|
|
32
|
+
isVerified: p.author.verification?.verifiedStatus === "valid",
|
|
33
|
+
// Post content
|
|
34
|
+
text: p.record.text,
|
|
35
|
+
richText: facetsToHtml(p.record.text, p.record.facets),
|
|
36
|
+
langs: p.record.langs,
|
|
37
|
+
// Formatted values
|
|
38
|
+
datetime: formatBlueskyDate(p.record.createdAt),
|
|
39
|
+
createdAt: new Date(p.record.createdAt),
|
|
40
|
+
likes: p.likeCount,
|
|
41
|
+
likesFormatted: formatCount(p.likeCount),
|
|
42
|
+
reposts: p.repostCount,
|
|
43
|
+
repostsFormatted: formatCount(p.repostCount),
|
|
44
|
+
replies: p.replyCount,
|
|
45
|
+
repliesFormatted: formatCount(p.replyCount),
|
|
46
|
+
quotes: p.quoteCount,
|
|
47
|
+
quotesFormatted: formatCount(p.quoteCount),
|
|
48
|
+
// Media
|
|
49
|
+
images: p.embed?.images?.map((img) => ({
|
|
50
|
+
thumb: proxyBlueskyImageUrl(img.thumb, props.imageProxyEndpoint),
|
|
51
|
+
fullsize: proxyBlueskyImageUrl(img.fullsize, props.imageProxyEndpoint),
|
|
52
|
+
alt: img.alt,
|
|
53
|
+
aspectRatio: img.aspectRatio
|
|
54
|
+
})),
|
|
55
|
+
externalEmbed: p.embed?.external ? {
|
|
56
|
+
uri: p.embed.external.uri,
|
|
57
|
+
title: p.embed.external.title,
|
|
58
|
+
description: p.embed.external.description,
|
|
59
|
+
thumb: p.embed.external.thumb ? proxyBlueskyImageUrl(p.embed.external.thumb, props.imageProxyEndpoint) : void 0
|
|
60
|
+
} : void 0,
|
|
61
|
+
// Links
|
|
62
|
+
postUrl: props.postUrl,
|
|
63
|
+
authorUrl: `https://bsky.app/profile/${p.author.handle}`,
|
|
64
|
+
// Helpers
|
|
65
|
+
proxyImage: (url) => proxyBlueskyImageUrl(url, props.imageProxyEndpoint)
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
defineExpose({
|
|
69
|
+
post,
|
|
70
|
+
status,
|
|
71
|
+
error
|
|
72
|
+
});
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<template>
|
|
76
|
+
<div v-bind="rootAttrs">
|
|
77
|
+
<slot v-if="status === 'pending'" name="loading">
|
|
78
|
+
<div>Loading Bluesky post...</div>
|
|
79
|
+
</slot>
|
|
80
|
+
<slot v-else-if="status === 'error'" name="error" :error="error">
|
|
81
|
+
<div>Failed to load Bluesky post</div>
|
|
82
|
+
</slot>
|
|
83
|
+
<slot v-else-if="slotProps" v-bind="slotProps" />
|
|
84
|
+
</div>
|
|
85
|
+
</template>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'vue';
|
|
2
|
+
import type { BlueskyEmbedPostData } from '../registry/bluesky-embed.js';
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
/**
|
|
5
|
+
* The Bluesky post URL to embed
|
|
6
|
+
* @example 'https://bsky.app/profile/bsky.app/post/3mgnwwvj3u22a'
|
|
7
|
+
*/
|
|
8
|
+
postUrl: string;
|
|
9
|
+
/**
|
|
10
|
+
* Custom API endpoint for fetching post data
|
|
11
|
+
* @default '/_scripts/embed/bluesky'
|
|
12
|
+
*/
|
|
13
|
+
apiEndpoint?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Custom image proxy endpoint
|
|
16
|
+
* @default '/_scripts/embed/bluesky-image'
|
|
17
|
+
*/
|
|
18
|
+
imageProxyEndpoint?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Root element attributes
|
|
21
|
+
*/
|
|
22
|
+
rootAttrs?: HTMLAttributes;
|
|
23
|
+
};
|
|
24
|
+
declare var __VLS_1: {}, __VLS_3: {
|
|
25
|
+
error: import("nuxt/app").NuxtError<unknown> | undefined;
|
|
26
|
+
}, __VLS_5: {
|
|
27
|
+
post: BlueskyEmbedPostData;
|
|
28
|
+
displayName: string;
|
|
29
|
+
handle: string;
|
|
30
|
+
avatar: string;
|
|
31
|
+
avatarOriginal: string;
|
|
32
|
+
isVerified: boolean;
|
|
33
|
+
text: string;
|
|
34
|
+
richText: string;
|
|
35
|
+
langs: string[] | undefined;
|
|
36
|
+
datetime: string;
|
|
37
|
+
createdAt: Date;
|
|
38
|
+
likes: number;
|
|
39
|
+
likesFormatted: string;
|
|
40
|
+
reposts: number;
|
|
41
|
+
repostsFormatted: string;
|
|
42
|
+
replies: number;
|
|
43
|
+
repliesFormatted: string;
|
|
44
|
+
quotes: number;
|
|
45
|
+
quotesFormatted: string;
|
|
46
|
+
images: {
|
|
47
|
+
thumb: string;
|
|
48
|
+
fullsize: string;
|
|
49
|
+
alt: string;
|
|
50
|
+
aspectRatio: {
|
|
51
|
+
width: number;
|
|
52
|
+
height: number;
|
|
53
|
+
} | undefined;
|
|
54
|
+
}[] | undefined;
|
|
55
|
+
externalEmbed: {
|
|
56
|
+
uri: string;
|
|
57
|
+
title: string;
|
|
58
|
+
description: string;
|
|
59
|
+
thumb: string | undefined;
|
|
60
|
+
} | undefined;
|
|
61
|
+
postUrl: string;
|
|
62
|
+
authorUrl: string;
|
|
63
|
+
proxyImage: (url: string) => string;
|
|
64
|
+
};
|
|
65
|
+
type __VLS_Slots = {} & {
|
|
66
|
+
loading?: (props: typeof __VLS_1) => any;
|
|
67
|
+
} & {
|
|
68
|
+
error?: (props: typeof __VLS_3) => any;
|
|
69
|
+
} & {
|
|
70
|
+
default?: (props: typeof __VLS_5) => any;
|
|
71
|
+
};
|
|
72
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
73
|
+
post: import("vue").Ref<BlueskyEmbedPostData | undefined, BlueskyEmbedPostData | undefined>;
|
|
74
|
+
status: import("vue").Ref<import("nuxt/app").AsyncDataRequestStatus, import("nuxt/app").AsyncDataRequestStatus>;
|
|
75
|
+
error: import("vue").Ref<import("nuxt/app").NuxtError<unknown> | undefined, import("nuxt/app").NuxtError<unknown> | undefined>;
|
|
76
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
77
|
+
apiEndpoint: string;
|
|
78
|
+
imageProxyEndpoint: string;
|
|
79
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
80
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
81
|
+
declare const _default: typeof __VLS_export;
|
|
82
|
+
export default _default;
|
|
83
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
84
|
+
new (): {
|
|
85
|
+
$slots: S;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
@@ -12,7 +12,7 @@ type __VLS_Props = {
|
|
|
12
12
|
captions?: boolean;
|
|
13
13
|
/**
|
|
14
14
|
* Custom API endpoint for fetching embed HTML
|
|
15
|
-
* @default '/
|
|
15
|
+
* @default '/_scripts/embed/instagram'
|
|
16
16
|
*/
|
|
17
17
|
apiEndpoint?: string;
|
|
18
18
|
/**
|
|
@@ -40,8 +40,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
|
40
40
|
error: import("vue").Ref<import("nuxt/app").NuxtError<unknown> | undefined, import("nuxt/app").NuxtError<unknown> | undefined>;
|
|
41
41
|
shortcode: import("vue").ComputedRef<string | undefined>;
|
|
42
42
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
43
|
-
captions: boolean;
|
|
44
43
|
apiEndpoint: string;
|
|
44
|
+
captions: boolean;
|
|
45
45
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
46
46
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
47
47
|
declare const _default: typeof __VLS_export;
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
import { useAsyncData } from "nuxt/app";
|
|
3
3
|
import { computed } from "vue";
|
|
4
4
|
import { extractInstagramShortcode } from "../registry/instagram-embed";
|
|
5
|
+
import { requireRegistryEndpoint } from "../utils";
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
postUrl: { type: String, required: true },
|
|
7
8
|
captions: { type: Boolean, required: false, default: true },
|
|
8
|
-
apiEndpoint: { type: String, required: false, default: "/
|
|
9
|
+
apiEndpoint: { type: String, required: false, default: "/_scripts/embed/instagram" },
|
|
9
10
|
rootAttrs: { type: Object, required: false }
|
|
10
11
|
});
|
|
12
|
+
if (!props.apiEndpoint || props.apiEndpoint === "/_scripts/embed/instagram")
|
|
13
|
+
requireRegistryEndpoint("ScriptInstagramEmbed", "instagramEmbed");
|
|
11
14
|
const shortcode = computed(() => extractInstagramShortcode(props.postUrl));
|
|
12
15
|
const { data: html, status, error } = useAsyncData(
|
|
13
16
|
`instagram-embed-${props.postUrl}`,
|
|
@@ -12,7 +12,7 @@ type __VLS_Props = {
|
|
|
12
12
|
captions?: boolean;
|
|
13
13
|
/**
|
|
14
14
|
* Custom API endpoint for fetching embed HTML
|
|
15
|
-
* @default '/
|
|
15
|
+
* @default '/_scripts/embed/instagram'
|
|
16
16
|
*/
|
|
17
17
|
apiEndpoint?: string;
|
|
18
18
|
/**
|
|
@@ -40,8 +40,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
|
40
40
|
error: import("vue").Ref<import("nuxt/app").NuxtError<unknown> | undefined, import("nuxt/app").NuxtError<unknown> | undefined>;
|
|
41
41
|
shortcode: import("vue").ComputedRef<string | undefined>;
|
|
42
42
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
43
|
-
captions: boolean;
|
|
44
43
|
apiEndpoint: string;
|
|
44
|
+
captions: boolean;
|
|
45
45
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
46
46
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
47
47
|
declare const _default: typeof __VLS_export;
|
|
@@ -7,12 +7,12 @@ type __VLS_Props = {
|
|
|
7
7
|
tweetId: string;
|
|
8
8
|
/**
|
|
9
9
|
* Custom API endpoint for fetching tweet data
|
|
10
|
-
* @default '/
|
|
10
|
+
* @default '/_scripts/embed/x'
|
|
11
11
|
*/
|
|
12
12
|
apiEndpoint?: string;
|
|
13
13
|
/**
|
|
14
14
|
* Custom image proxy endpoint
|
|
15
|
-
* @default '/_scripts/x-
|
|
15
|
+
* @default '/_scripts/embed/x-image'
|
|
16
16
|
*/
|
|
17
17
|
imageProxyEndpoint?: string;
|
|
18
18
|
/**
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
import { useAsyncData } from "nuxt/app";
|
|
3
3
|
import { computed } from "vue";
|
|
4
4
|
import { formatCount, formatTweetDate, proxyXImageUrl } from "../registry/x-embed";
|
|
5
|
+
import { requireRegistryEndpoint } from "../utils";
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
tweetId: { type: String, required: true },
|
|
7
|
-
apiEndpoint: { type: String, required: false, default: "/
|
|
8
|
-
imageProxyEndpoint: { type: String, required: false, default: "/
|
|
8
|
+
apiEndpoint: { type: String, required: false, default: "/_scripts/embed/x" },
|
|
9
|
+
imageProxyEndpoint: { type: String, required: false, default: "/_scripts/embed/x-image" },
|
|
9
10
|
rootAttrs: { type: Object, required: false }
|
|
10
11
|
});
|
|
12
|
+
if (!props.apiEndpoint || props.apiEndpoint === "/_scripts/embed/x")
|
|
13
|
+
requireRegistryEndpoint("ScriptXEmbed", "xEmbed");
|
|
11
14
|
const cacheKey = computed(() => `x-embed-${props.tweetId}`);
|
|
12
15
|
const { data: tweet, status, error } = useAsyncData(
|
|
13
16
|
cacheKey,
|
|
@@ -7,12 +7,12 @@ type __VLS_Props = {
|
|
|
7
7
|
tweetId: string;
|
|
8
8
|
/**
|
|
9
9
|
* Custom API endpoint for fetching tweet data
|
|
10
|
-
* @default '/
|
|
10
|
+
* @default '/_scripts/embed/x'
|
|
11
11
|
*/
|
|
12
12
|
apiEndpoint?: string;
|
|
13
13
|
/**
|
|
14
14
|
* Custom image proxy endpoint
|
|
15
|
-
* @default '/_scripts/x-
|
|
15
|
+
* @default '/_scripts/embed/x-image'
|
|
16
16
|
*/
|
|
17
17
|
imageProxyEndpoint?: string;
|
|
18
18
|
/**
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { RegistryScriptInput } from '#nuxt-scripts/types';
|
|
2
|
+
import { BlueskyEmbedOptions } from './schemas.js';
|
|
3
|
+
export { BlueskyEmbedOptions };
|
|
4
|
+
export interface BlueskyEmbedPostData {
|
|
5
|
+
uri: string;
|
|
6
|
+
cid: string;
|
|
7
|
+
author: {
|
|
8
|
+
did: string;
|
|
9
|
+
handle: string;
|
|
10
|
+
displayName: string;
|
|
11
|
+
avatar: string;
|
|
12
|
+
labels: Array<{
|
|
13
|
+
val: string;
|
|
14
|
+
}>;
|
|
15
|
+
verification?: {
|
|
16
|
+
verifiedStatus: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
record: {
|
|
20
|
+
$type: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
text: string;
|
|
23
|
+
langs?: string[];
|
|
24
|
+
facets?: Array<{
|
|
25
|
+
features: Array<{
|
|
26
|
+
$type: string;
|
|
27
|
+
uri?: string;
|
|
28
|
+
did?: string;
|
|
29
|
+
tag?: string;
|
|
30
|
+
}>;
|
|
31
|
+
index: {
|
|
32
|
+
byteStart: number;
|
|
33
|
+
byteEnd: number;
|
|
34
|
+
};
|
|
35
|
+
}>;
|
|
36
|
+
embed?: {
|
|
37
|
+
$type: string;
|
|
38
|
+
images?: Array<{
|
|
39
|
+
alt: string;
|
|
40
|
+
image: {
|
|
41
|
+
ref: {
|
|
42
|
+
$link: string;
|
|
43
|
+
};
|
|
44
|
+
mimeType: string;
|
|
45
|
+
size: number;
|
|
46
|
+
};
|
|
47
|
+
aspectRatio?: {
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
};
|
|
51
|
+
}>;
|
|
52
|
+
external?: {
|
|
53
|
+
uri: string;
|
|
54
|
+
title: string;
|
|
55
|
+
description: string;
|
|
56
|
+
thumb?: {
|
|
57
|
+
ref: {
|
|
58
|
+
$link: string;
|
|
59
|
+
};
|
|
60
|
+
mimeType: string;
|
|
61
|
+
size: number;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
embed?: {
|
|
67
|
+
$type: string;
|
|
68
|
+
images?: Array<{
|
|
69
|
+
thumb: string;
|
|
70
|
+
fullsize: string;
|
|
71
|
+
alt: string;
|
|
72
|
+
aspectRatio?: {
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
};
|
|
76
|
+
}>;
|
|
77
|
+
external?: {
|
|
78
|
+
uri: string;
|
|
79
|
+
title: string;
|
|
80
|
+
description: string;
|
|
81
|
+
thumb?: string;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
likeCount: number;
|
|
85
|
+
repostCount: number;
|
|
86
|
+
replyCount: number;
|
|
87
|
+
quoteCount: number;
|
|
88
|
+
indexedAt: string;
|
|
89
|
+
labels: Array<{
|
|
90
|
+
val: string;
|
|
91
|
+
}>;
|
|
92
|
+
}
|
|
93
|
+
export type BlueskyEmbedInput = RegistryScriptInput<typeof BlueskyEmbedOptions, false, false, false>;
|
|
94
|
+
/**
|
|
95
|
+
* Extract the handle/DID and post rkey from a Bluesky post URL
|
|
96
|
+
*/
|
|
97
|
+
export declare function extractBlueskyPostId(url: string): {
|
|
98
|
+
actor: string;
|
|
99
|
+
rkey: string;
|
|
100
|
+
} | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* Proxy a Bluesky image URL through the server
|
|
103
|
+
*/
|
|
104
|
+
export declare function proxyBlueskyImageUrl(url: string, proxyEndpoint?: string): string;
|
|
105
|
+
/**
|
|
106
|
+
* Format a Bluesky post date for display
|
|
107
|
+
*/
|
|
108
|
+
export declare function formatBlueskyDate(dateString: string): string;
|
|
109
|
+
/**
|
|
110
|
+
* Format a number for display (e.g., 1234 -> 1.2K)
|
|
111
|
+
*/
|
|
112
|
+
export declare function formatCount(count: number): string;
|
|
113
|
+
/**
|
|
114
|
+
* Convert Bluesky facets (byte-range rich text annotations) to HTML
|
|
115
|
+
*/
|
|
116
|
+
export declare function facetsToHtml(text: string, facets?: BlueskyEmbedPostData['record']['facets']): string;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { BlueskyEmbedOptions } from "./schemas.js";
|
|
2
|
+
export { BlueskyEmbedOptions };
|
|
3
|
+
const BSKY_POST_URL_RE = /bsky\.app\/profile\/([^/]+)\/post\/([^/?]+)/;
|
|
4
|
+
export function extractBlueskyPostId(url) {
|
|
5
|
+
const match = url.match(BSKY_POST_URL_RE);
|
|
6
|
+
if (!match)
|
|
7
|
+
return void 0;
|
|
8
|
+
return { actor: match[1], rkey: match[2] };
|
|
9
|
+
}
|
|
10
|
+
export function proxyBlueskyImageUrl(url, proxyEndpoint = "/_scripts/embed/bluesky-image") {
|
|
11
|
+
const separator = proxyEndpoint.includes("?") ? "&" : "?";
|
|
12
|
+
return `${proxyEndpoint}${separator}url=${encodeURIComponent(url)}`;
|
|
13
|
+
}
|
|
14
|
+
export function formatBlueskyDate(dateString) {
|
|
15
|
+
const date = new Date(dateString);
|
|
16
|
+
const time = date.toLocaleString("en-US", {
|
|
17
|
+
hour: "numeric",
|
|
18
|
+
minute: "numeric",
|
|
19
|
+
hour12: true,
|
|
20
|
+
timeZone: "UTC"
|
|
21
|
+
});
|
|
22
|
+
const month = date.toLocaleString("en-US", { month: "short", timeZone: "UTC" });
|
|
23
|
+
return `${time} \xB7 ${month} ${date.getUTCDate()}, ${date.getUTCFullYear()}`;
|
|
24
|
+
}
|
|
25
|
+
export function formatCount(count) {
|
|
26
|
+
if (count >= 1e6) {
|
|
27
|
+
return `${(count / 1e6).toFixed(1)}M`;
|
|
28
|
+
}
|
|
29
|
+
if (count >= 1e3) {
|
|
30
|
+
return `${(count / 1e3).toFixed(1)}K`;
|
|
31
|
+
}
|
|
32
|
+
return count.toString();
|
|
33
|
+
}
|
|
34
|
+
export function facetsToHtml(text, facets) {
|
|
35
|
+
if (!facets?.length)
|
|
36
|
+
return escapeHtml(text);
|
|
37
|
+
const encoder = new TextEncoder();
|
|
38
|
+
const decoder = new TextDecoder();
|
|
39
|
+
const bytes = encoder.encode(text);
|
|
40
|
+
const sorted = facets.toSorted((a, b) => a.index.byteStart - b.index.byteStart);
|
|
41
|
+
const parts = [];
|
|
42
|
+
let lastEnd = 0;
|
|
43
|
+
for (const facet of sorted) {
|
|
44
|
+
if (facet.index.byteStart > lastEnd) {
|
|
45
|
+
parts.push(escapeHtml(decoder.decode(bytes.slice(lastEnd, facet.index.byteStart))));
|
|
46
|
+
}
|
|
47
|
+
const facetText = escapeHtml(decoder.decode(bytes.slice(facet.index.byteStart, facet.index.byteEnd)));
|
|
48
|
+
for (const feature of facet.features) {
|
|
49
|
+
if (feature.$type === "app.bsky.richtext.facet#link" && feature.uri) {
|
|
50
|
+
parts.push(`<a href="${escapeHtml(feature.uri)}" target="_blank" rel="noopener noreferrer">${facetText}</a>`);
|
|
51
|
+
} else if (feature.$type === "app.bsky.richtext.facet#mention" && feature.did) {
|
|
52
|
+
parts.push(`<a href="https://bsky.app/profile/${escapeHtml(feature.did)}" target="_blank" rel="noopener noreferrer">${facetText}</a>`);
|
|
53
|
+
} else if (feature.$type === "app.bsky.richtext.facet#tag" && feature.tag) {
|
|
54
|
+
parts.push(`<a href="https://bsky.app/hashtag/${escapeHtml(feature.tag)}" target="_blank" rel="noopener noreferrer">${facetText}</a>`);
|
|
55
|
+
} else {
|
|
56
|
+
parts.push(facetText);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
lastEnd = facet.index.byteEnd;
|
|
60
|
+
}
|
|
61
|
+
if (lastEnd < bytes.length) {
|
|
62
|
+
parts.push(escapeHtml(decoder.decode(bytes.slice(lastEnd))));
|
|
63
|
+
}
|
|
64
|
+
return parts.join("");
|
|
65
|
+
}
|
|
66
|
+
const AMP_RE = /&/g;
|
|
67
|
+
const LT_RE = /</g;
|
|
68
|
+
const GT_RE = />/g;
|
|
69
|
+
const QUOT_RE = /"/g;
|
|
70
|
+
function escapeHtml(str) {
|
|
71
|
+
return str.replace(AMP_RE, "&").replace(LT_RE, "<").replace(GT_RE, ">").replace(QUOT_RE, """);
|
|
72
|
+
}
|
|
@@ -20,10 +20,10 @@ export function useScriptGravatar(_options) {
|
|
|
20
20
|
scriptOptions: {
|
|
21
21
|
use: () => ({
|
|
22
22
|
getAvatarUrl: (hash, overrides) => {
|
|
23
|
-
return `/_scripts/gravatar
|
|
23
|
+
return `/_scripts/proxy/gravatar?hash=${encodeURIComponent(hash)}&${buildQuery(overrides)}`;
|
|
24
24
|
},
|
|
25
25
|
getAvatarUrlFromEmail: (email, overrides) => {
|
|
26
|
-
return `/_scripts/gravatar
|
|
26
|
+
return `/_scripts/proxy/gravatar?email=${encodeURIComponent(email)}&${buildQuery(overrides)}`;
|
|
27
27
|
}
|
|
28
28
|
})
|
|
29
29
|
}
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
export declare const BlueskyEmbedOptions: import("valibot").ObjectSchema<{
|
|
2
|
+
/**
|
|
3
|
+
* The Bluesky post URL to embed.
|
|
4
|
+
* @example 'https://bsky.app/profile/bsky.app/post/3mgnwwvj3u22a'
|
|
5
|
+
*/
|
|
6
|
+
readonly postUrl: import("valibot").StringSchema<undefined>;
|
|
7
|
+
/**
|
|
8
|
+
* Custom API endpoint for fetching post data.
|
|
9
|
+
* @default '/_scripts/embed/bluesky'
|
|
10
|
+
*/
|
|
11
|
+
readonly apiEndpoint: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
12
|
+
/**
|
|
13
|
+
* Custom image proxy endpoint.
|
|
14
|
+
* @default '/_scripts/embed/bluesky-image'
|
|
15
|
+
*/
|
|
16
|
+
readonly imageProxyEndpoint: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
17
|
+
}, undefined>;
|
|
1
18
|
export declare const ClarityOptions: import("valibot").ObjectSchema<{
|
|
2
19
|
/**
|
|
3
20
|
* The Clarity token.
|
|
@@ -433,7 +450,7 @@ export declare const InstagramEmbedOptions: import("valibot").ObjectSchema<{
|
|
|
433
450
|
readonly captions: import("valibot").OptionalSchema<import("valibot").BooleanSchema<undefined>, undefined>;
|
|
434
451
|
/**
|
|
435
452
|
* Custom API endpoint for fetching embed HTML.
|
|
436
|
-
* @default '/
|
|
453
|
+
* @default '/_scripts/embed/instagram'
|
|
437
454
|
*/
|
|
438
455
|
readonly apiEndpoint: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
439
456
|
}, undefined>;
|
|
@@ -871,12 +888,12 @@ export declare const XEmbedOptions: import("valibot").ObjectSchema<{
|
|
|
871
888
|
readonly tweetId: import("valibot").StringSchema<undefined>;
|
|
872
889
|
/**
|
|
873
890
|
* Optional: Custom API endpoint for fetching tweet data.
|
|
874
|
-
* @default '/
|
|
891
|
+
* @default '/_scripts/embed/x'
|
|
875
892
|
*/
|
|
876
893
|
readonly apiEndpoint: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
877
894
|
/**
|
|
878
895
|
* Optional: Custom image proxy endpoint.
|
|
879
|
-
* @default '/
|
|
896
|
+
* @default '/_scripts/embed/x-image'
|
|
880
897
|
*/
|
|
881
898
|
readonly imageProxyEndpoint: import("valibot").OptionalSchema<import("valibot").StringSchema<undefined>, undefined>;
|
|
882
899
|
}, undefined>;
|