@meowdown/embed 0.3.0 → 0.3.2
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/{fetch-Djnul03u.d.ts → fetch-gxdhOZP6.d.ts} +0 -2
- package/dist/{is-plain-click-QDpLdFP7.js → is-plain-click-Dbydr3nX.js} +6 -10
- package/dist/x/index.d.ts +3 -11
- package/dist/x/index.js +25 -26
- package/dist/x/theme.css +42 -16
- package/dist/youtube/index.d.ts +3 -11
- package/dist/youtube/index.js +9 -14
- package/package.json +5 -5
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { HostElement, State } from "@aria-ui/core";
|
|
2
|
-
//#region src/fetch.d.ts
|
|
3
2
|
/**
|
|
4
3
|
* Loads the snapshot for `url`. Return `undefined` when nothing was found.
|
|
5
4
|
*/
|
|
@@ -18,5 +17,4 @@ interface FetchProps<T> {
|
|
|
18
17
|
*/
|
|
19
18
|
resolver: Resolver<T> | null;
|
|
20
19
|
}
|
|
21
|
-
//#endregion
|
|
22
20
|
export { Resolver as n, FetchProps as t };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createSignal, useEffect } from "@aria-ui/core";
|
|
2
2
|
import el from "crelt";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/fetch.ts
|
|
5
5
|
/**
|
|
6
6
|
* Runs `resolver(url)` whenever `data` is `null` and both `url` and `resolver`
|
|
7
7
|
* are set, ignoring results that arrive after the inputs changed or the host
|
|
@@ -10,6 +10,7 @@ import el from "crelt";
|
|
|
10
10
|
* @internal
|
|
11
11
|
*/
|
|
12
12
|
function useFetch(host, props, label) {
|
|
13
|
+
"use no memo";
|
|
13
14
|
const fetched = createSignal(null);
|
|
14
15
|
const pending = createSignal(false);
|
|
15
16
|
useEffect(host, () => {
|
|
@@ -53,8 +54,7 @@ function isPromiseLike(value) {
|
|
|
53
54
|
return typeof value === "object" && value !== null && typeof value.then === "function";
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
//#region src/safe-url.ts
|
|
57
|
+
// src/safe-url.ts
|
|
58
58
|
function getSafeUrl(value, protocols) {
|
|
59
59
|
if (Array.from(value).some((character) => {
|
|
60
60
|
return character.charCodeAt(0) <= 32 || character.charCodeAt(0) === 127;
|
|
@@ -68,8 +68,7 @@ function getSafeUrl(value, protocols) {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
//#region src/render-link.ts
|
|
71
|
+
// src/render-link.ts
|
|
73
72
|
function renderLink(content, destination) {
|
|
74
73
|
const href = destination && getSafeUrl(destination);
|
|
75
74
|
return href ? el("a", {
|
|
@@ -79,8 +78,7 @@ function renderLink(content, destination) {
|
|
|
79
78
|
}, content) : content;
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
//#region src/root.ts
|
|
81
|
+
// src/root.ts
|
|
84
82
|
/**
|
|
85
83
|
* The direct `<div data-root>` child that holds the rendered snapshot. Reused
|
|
86
84
|
* across updates so other children the host appended survive; created on
|
|
@@ -96,11 +94,9 @@ function getRootContainer(host) {
|
|
|
96
94
|
return container;
|
|
97
95
|
}
|
|
98
96
|
|
|
99
|
-
|
|
100
|
-
//#region src/is-plain-click.ts
|
|
97
|
+
// src/is-plain-click.ts
|
|
101
98
|
function isPlainClick(event) {
|
|
102
99
|
return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
|
|
103
100
|
}
|
|
104
101
|
|
|
105
|
-
//#endregion
|
|
106
102
|
export { useFetch as a, getSafeUrl as i, getRootContainer as n, renderLink as r, isPlainClick as t };
|
package/dist/x/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { n as Resolver, t as FetchProps } from "../fetch-
|
|
1
|
+
import { n as Resolver, t as FetchProps } from "../fetch-gxdhOZP6.js";
|
|
2
2
|
import { HostElement, State } from "@aria-ui/core";
|
|
3
3
|
import { XPost, XPostMedia } from "@post-embed/types";
|
|
4
|
-
//#region src/x/media-click.d.ts
|
|
5
4
|
export declare const X_POST_MEDIA_CLICK = "meowdown-embed-media-click";
|
|
6
5
|
interface XPostMediaClickDetail {
|
|
7
6
|
/**
|
|
@@ -23,19 +22,13 @@ interface XPostMediaClickDetail {
|
|
|
23
22
|
element: HTMLElement;
|
|
24
23
|
}
|
|
25
24
|
type XPostMediaClickEvent = CustomEvent<XPostMediaClickDetail>;
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/x/x-post.d.ts
|
|
28
25
|
interface XPostProps extends FetchProps<XPost> {
|
|
29
26
|
mediaUrlProtocols: readonly string[] | null;
|
|
30
27
|
}
|
|
31
28
|
interface XPostElement extends HTMLElement, XPostProps {}
|
|
32
29
|
/** @internal */
|
|
33
|
-
export declare function
|
|
34
|
-
//#endregion
|
|
35
|
-
//#region src/x/register.d.ts
|
|
30
|
+
export declare function setupXPost(host: HostElement, props: State<XPostProps>): void;
|
|
36
31
|
export declare function registerXPost(name?: string): void;
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/x/index.d.ts
|
|
39
32
|
declare global {
|
|
40
33
|
interface HTMLElementTagNameMap {
|
|
41
34
|
'meowdown-embed-x': XPostElement;
|
|
@@ -44,5 +37,4 @@ declare global {
|
|
|
44
37
|
'meowdown-embed-media-click': XPostMediaClickEvent;
|
|
45
38
|
}
|
|
46
39
|
}
|
|
47
|
-
|
|
48
|
-
export type { Resolver, XPostElement, XPostMediaClickDetail, XPostMediaClickEvent, XPostProps };
|
|
40
|
+
export { type Resolver, type XPostElement, type XPostMediaClickDetail, type XPostMediaClickEvent, type XPostProps, setupXPost as useXPost };
|
package/dist/x/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as useFetch, i as getSafeUrl, n as getRootContainer, r as renderLink, t as isPlainClick } from "../is-plain-click-
|
|
1
|
+
import { a as useFetch, i as getSafeUrl, n as getRootContainer, r as renderLink, t as isPlainClick } from "../is-plain-click-Dbydr3nX.js";
|
|
2
2
|
import { defineCustomElement, defineProps, registerCustomElement, useEffect } from "@aria-ui/core";
|
|
3
3
|
import { parseXPost, parseXPostId } from "@post-embed/schema";
|
|
4
4
|
import el from "crelt";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/x/media-click.ts
|
|
7
7
|
const X_POST_MEDIA_CLICK = "meowdown-embed-media-click";
|
|
8
8
|
/**
|
|
9
9
|
* Returns false when a listener called `preventDefault()`: the host shows the
|
|
@@ -18,8 +18,7 @@ function dispatchMediaClick(target, detail) {
|
|
|
18
18
|
}));
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
//#region src/x/render-author.ts
|
|
21
|
+
// src/x/render-author.ts
|
|
23
22
|
function renderAuthor(author, protocols, date) {
|
|
24
23
|
if (!author.name && !author.handle) return;
|
|
25
24
|
const validHandle = /^\w{1,15}$/.test(author.handle);
|
|
@@ -37,8 +36,15 @@ function renderAuthor(author, protocols, date) {
|
|
|
37
36
|
}) : void 0, el("div", { "data-author-details": "" }, el("div", { "data-author-name": "" }, el("bdi", {}, author.name || author.handle)), author.handle ? el("bdi", {}, renderLink(`@${author.handle}`, validHandle ? `https://x.com/${author.handle}` : void 0)) : void 0), date ? el("span", { "data-date": "" }, date) : void 0);
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
// ../../node_modules/.pnpm/@ocavue+utils@1.11.0/node_modules/@ocavue/utils/dist/index.js
|
|
40
|
+
/**
|
|
41
|
+
* Returns true if the given value is not null or undefined.
|
|
42
|
+
*/
|
|
43
|
+
function isNotNullish(value) {
|
|
44
|
+
return value != null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/to-positive-number.ts
|
|
42
48
|
/**
|
|
43
49
|
* The value rounded to an integer, or nothing unless it is a finite number
|
|
44
50
|
* above zero.
|
|
@@ -47,8 +53,7 @@ function toPositiveNumber(value) {
|
|
|
47
53
|
if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.round(value);
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
|
|
51
|
-
//#region src/x/sort-video-sources.ts
|
|
56
|
+
// src/x/sort-video-sources.ts
|
|
52
57
|
/**
|
|
53
58
|
* Orders the sources the way a `<video>` should try them: it plays the first
|
|
54
59
|
* `<source>` it supports, so MP4 files come before HLS playlists (which only
|
|
@@ -61,8 +66,7 @@ function sortVideoSources(sources) {
|
|
|
61
66
|
});
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
|
|
65
|
-
//#region src/x/render-media.ts
|
|
69
|
+
// src/x/render-media.ts
|
|
66
70
|
function getSizeAttrs(media) {
|
|
67
71
|
return {
|
|
68
72
|
width: toPositiveNumber(media.width),
|
|
@@ -97,13 +101,13 @@ function getDisplayable(media, protocols) {
|
|
|
97
101
|
url
|
|
98
102
|
} : void 0;
|
|
99
103
|
}
|
|
100
|
-
const sources = sortVideoSources(media.sources.
|
|
104
|
+
const sources = sortVideoSources(media.sources.map((source) => {
|
|
101
105
|
const url = getSafeMediaUrl(source.url, protocols);
|
|
102
|
-
return url ?
|
|
106
|
+
return url ? {
|
|
103
107
|
...source,
|
|
104
108
|
url
|
|
105
|
-
}
|
|
106
|
-
}));
|
|
109
|
+
} : null;
|
|
110
|
+
}).filter(isNotNullish));
|
|
107
111
|
if (sources.length === 0) return;
|
|
108
112
|
const poster = media.poster && getSafeMediaUrl(media.poster, protocols);
|
|
109
113
|
return {
|
|
@@ -231,8 +235,7 @@ function renderMedia(media, protocols, permalink) {
|
|
|
231
235
|
}));
|
|
232
236
|
}
|
|
233
237
|
|
|
234
|
-
|
|
235
|
-
//#region src/x/render-shared.ts
|
|
238
|
+
// src/x/render-shared.ts
|
|
236
239
|
function getPermalink(post) {
|
|
237
240
|
return /^\w{1,15}$/.test(post.author.handle) && /^\d+$/.test(post.id) ? `https://x.com/${post.author.handle}/status/${post.id}` : void 0;
|
|
238
241
|
}
|
|
@@ -257,8 +260,7 @@ function renderDate(post) {
|
|
|
257
260
|
}).format(date)), getPermalink(post));
|
|
258
261
|
}
|
|
259
262
|
|
|
260
|
-
|
|
261
|
-
//#region src/x/render-post.ts
|
|
263
|
+
// src/x/render-post.ts
|
|
262
264
|
function renderBody(post) {
|
|
263
265
|
const permalink = getPermalink(post);
|
|
264
266
|
return el("p", {
|
|
@@ -287,10 +289,9 @@ function renderPost(post, protocols = null) {
|
|
|
287
289
|
return el("article", {}, el("div", { "data-content": "" }, renderAuthor(post.author, protocols, renderDate(post)), reply ? el("div", { "data-reply-to": "" }, renderLink(`Replying to @${reply.handle}`, replyUrl)) : void 0, renderBody(post), renderMedia(post.media, protocols, getPermalink(post)), post.quote ? renderQuoted(post.quote, protocols) : void 0, renderEdit(post)), el("details", { "data-show-more": "" }, el("summary", {})));
|
|
288
290
|
}
|
|
289
291
|
|
|
290
|
-
|
|
291
|
-
//#region src/x/x-post.ts
|
|
292
|
+
// src/x/x-post.ts
|
|
292
293
|
/** @internal */
|
|
293
|
-
function
|
|
294
|
+
function setupXPost(host, props) {
|
|
294
295
|
const { fetched, pending } = useFetch(host, props, "X post");
|
|
295
296
|
useEffect(host, () => {
|
|
296
297
|
host.dataset.meowdownEmbed = "x";
|
|
@@ -315,7 +316,7 @@ function renderFallback(pending, url) {
|
|
|
315
316
|
"data-pending": ""
|
|
316
317
|
} : { "data-fallback": "" }, el("header", { "data-author": "" }, el("bdi", {}, "X post")), el("p", { "data-body": "" }, pending ? "Loading this post…" : "This post is unavailable."), pending ? null : el("footer", { "data-footer": "" }, permalink ? renderLink("View on X", permalink) : "No saved post could be displayed."));
|
|
317
318
|
}
|
|
318
|
-
const XPost = defineCustomElement(
|
|
319
|
+
const XPost = defineCustomElement(setupXPost, defineProps({
|
|
319
320
|
data: {
|
|
320
321
|
default: null,
|
|
321
322
|
attribute: false
|
|
@@ -334,11 +335,9 @@ const XPost = defineCustomElement(useXPost, defineProps({
|
|
|
334
335
|
}
|
|
335
336
|
}));
|
|
336
337
|
|
|
337
|
-
|
|
338
|
-
//#region src/x/register.ts
|
|
338
|
+
// src/x/register.ts
|
|
339
339
|
function registerXPost(name = "meowdown-embed-x") {
|
|
340
340
|
registerCustomElement(name, class extends XPost {});
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
|
|
344
|
-
export { X_POST_MEDIA_CLICK, registerXPost, useXPost };
|
|
343
|
+
export { X_POST_MEDIA_CLICK, registerXPost, setupXPost, setupXPost as useXPost };
|
package/dist/x/theme.css
CHANGED
|
@@ -51,6 +51,22 @@
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
@keyframes meowdown-embed-fade {
|
|
55
|
+
from,
|
|
56
|
+
to {
|
|
57
|
+
mask-image: linear-gradient(to bottom, #000 calc(100% - 3rem), transparent);
|
|
58
|
+
mask-size: 100% calc(var(--_body-limit) - var(--_show-more-height) - 2 * var(--_clip-gutter));
|
|
59
|
+
mask-repeat: no-repeat;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@keyframes meowdown-embed-show {
|
|
64
|
+
from,
|
|
65
|
+
to {
|
|
66
|
+
visibility: visible;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
/*
|
|
55
71
|
* Hard reset. `all: revert` rolls every property on every box inside the card
|
|
56
72
|
* back to the user-agent default, so a host rule on `p`, `a`, `img`,
|
|
@@ -77,12 +93,13 @@
|
|
|
77
93
|
--_tint: color-mix(in srgb, currentColor 5%, transparent);
|
|
78
94
|
--_media-height: 7.5rem;
|
|
79
95
|
--_show-more-height: 2rem;
|
|
96
|
+
--_max-width: 28rem;
|
|
80
97
|
|
|
81
98
|
display: block;
|
|
82
99
|
/* As wide as the content, between 18rem and 28rem: a short text post stays
|
|
83
100
|
* small, while long text and media fill the full width. */
|
|
84
101
|
width: fit-content;
|
|
85
|
-
max-width: min(
|
|
102
|
+
max-width: min(var(--_max-width), 100%);
|
|
86
103
|
font: inherit;
|
|
87
104
|
color: var(--meowdown-embed-color, inherit);
|
|
88
105
|
text-decoration-skip-ink: none;
|
|
@@ -105,6 +122,11 @@
|
|
|
105
122
|
[data-meowdown-embed='x'] [data-root] {
|
|
106
123
|
display: block;
|
|
107
124
|
position: relative;
|
|
125
|
+
/* The host's percentage `max-width` counts as `none` when a shrink-to-fit
|
|
126
|
+
* parent (an inline-block editor wrapper) measures the card, so long text
|
|
127
|
+
* would widen that parent to its own limit. A fixed cap here keeps the
|
|
128
|
+
* card's intrinsic width at 28rem. */
|
|
129
|
+
max-width: var(--_max-width);
|
|
108
130
|
color: var(--meowdown-embed-color, inherit);
|
|
109
131
|
background: var(--meowdown-embed-background, transparent);
|
|
110
132
|
border: 1px solid var(--_hairline);
|
|
@@ -210,6 +232,9 @@
|
|
|
210
232
|
* when the card is too tall. Then the article gives up one row, which the
|
|
211
233
|
* "Show more" toggle takes, so the whole card is exactly the limit. The
|
|
212
234
|
* toggle is anchored to the card's padding box, out of the article's clip.
|
|
235
|
+
* The fade and the toggle run their own animations on the article's named
|
|
236
|
+
* timeline, which update on every scroll in every engine. Firefox applies
|
|
237
|
+
* a `style()` query on an animated value only after a full restyle.
|
|
213
238
|
* Browsers without scroll-driven animations show the whole card. */
|
|
214
239
|
& > article {
|
|
215
240
|
/* Room inside the clip for focus rings at the article's edges. */
|
|
@@ -258,6 +283,7 @@
|
|
|
258
283
|
margin-block-end: calc(var(--_overflowing) * var(--_show-more-height) - var(--_clip-gutter));
|
|
259
284
|
animation: meowdown-embed-overflowing linear both;
|
|
260
285
|
animation-timeline: scroll(self);
|
|
286
|
+
scroll-timeline: --meowdown-embed-clip block;
|
|
261
287
|
}
|
|
262
288
|
/* Opened, or holding keyboard focus that the clip could hide. */
|
|
263
289
|
& > article:has(> [data-show-more][open]),
|
|
@@ -266,21 +292,20 @@
|
|
|
266
292
|
overflow: visible;
|
|
267
293
|
margin-block-end: calc(-1 * var(--_clip-gutter));
|
|
268
294
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
295
|
+
/* On the content, not the article: a mask on the article would also
|
|
296
|
+
* hide the toggle below it. */
|
|
297
|
+
& > article > [data-content] {
|
|
298
|
+
animation: meowdown-embed-fade linear both;
|
|
299
|
+
animation-timeline: --meowdown-embed-clip;
|
|
300
|
+
}
|
|
301
|
+
& > article > [data-show-more] {
|
|
302
|
+
display: block;
|
|
303
|
+
position: absolute;
|
|
304
|
+
inset-inline-start: var(--meowdown-embed-padding, 1rem);
|
|
305
|
+
bottom: var(--meowdown-embed-padding, 1rem);
|
|
306
|
+
visibility: hidden;
|
|
307
|
+
animation: meowdown-embed-show linear both;
|
|
308
|
+
animation-timeline: --meowdown-embed-clip;
|
|
284
309
|
}
|
|
285
310
|
/* Opened, "Show less" sticks to the bottom of the scrollport until the
|
|
286
311
|
* card's end scrolls into view. */
|
|
@@ -288,6 +313,7 @@
|
|
|
288
313
|
display: block;
|
|
289
314
|
position: sticky;
|
|
290
315
|
bottom: 0.75rem;
|
|
316
|
+
visibility: visible;
|
|
291
317
|
z-index: 1;
|
|
292
318
|
width: fit-content;
|
|
293
319
|
margin: 0.5rem auto 0;
|
package/dist/youtube/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { n as Resolver, t as FetchProps } from "../fetch-
|
|
1
|
+
import { n as Resolver, t as FetchProps } from "../fetch-gxdhOZP6.js";
|
|
2
2
|
import { HostElement, State } from "@aria-ui/core";
|
|
3
3
|
import { YouTubeVideo } from "@post-embed/types";
|
|
4
|
-
//#region src/youtube/video-click.d.ts
|
|
5
4
|
export declare const YOUTUBE_VIDEO_CLICK = "meowdown-embed-youtube-click";
|
|
6
5
|
interface YouTubeVideoClickDetail {
|
|
7
6
|
/**
|
|
@@ -28,8 +27,6 @@ interface YouTubeVideoClickDetail {
|
|
|
28
27
|
element: HTMLElement;
|
|
29
28
|
}
|
|
30
29
|
type YouTubeVideoClickEvent = CustomEvent<YouTubeVideoClickDetail>;
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/youtube/youtube-video.d.ts
|
|
33
30
|
interface YouTubeVideoProps extends FetchProps<YouTubeVideo> {
|
|
34
31
|
/**
|
|
35
32
|
* `link` (default) opens the watch page; `inline` swaps in the YouTube
|
|
@@ -39,12 +36,8 @@ interface YouTubeVideoProps extends FetchProps<YouTubeVideo> {
|
|
|
39
36
|
}
|
|
40
37
|
interface YouTubeVideoElement extends HTMLElement, YouTubeVideoProps {}
|
|
41
38
|
/** @internal */
|
|
42
|
-
export declare function
|
|
43
|
-
//#endregion
|
|
44
|
-
//#region src/youtube/register.d.ts
|
|
39
|
+
export declare function setupYouTubeVideo(host: HostElement, props: State<YouTubeVideoProps>): void;
|
|
45
40
|
export declare function registerYouTubeVideo(name?: string): void;
|
|
46
|
-
//#endregion
|
|
47
|
-
//#region src/youtube/index.d.ts
|
|
48
41
|
declare global {
|
|
49
42
|
interface HTMLElementTagNameMap {
|
|
50
43
|
'meowdown-embed-youtube': YouTubeVideoElement;
|
|
@@ -53,5 +46,4 @@ declare global {
|
|
|
53
46
|
'meowdown-embed-youtube-click': YouTubeVideoClickEvent;
|
|
54
47
|
}
|
|
55
48
|
}
|
|
56
|
-
|
|
57
|
-
export type { Resolver, YouTubeVideoClickDetail, YouTubeVideoClickEvent, YouTubeVideoElement, YouTubeVideoProps };
|
|
49
|
+
export { type Resolver, type YouTubeVideoClickDetail, type YouTubeVideoClickEvent, type YouTubeVideoElement, type YouTubeVideoProps, setupYouTubeVideo as useYouTubeVideo };
|
package/dist/youtube/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as useFetch, i as getSafeUrl, n as getRootContainer, r as renderLink, t as isPlainClick } from "../is-plain-click-
|
|
1
|
+
import { a as useFetch, i as getSafeUrl, n as getRootContainer, r as renderLink, t as isPlainClick } from "../is-plain-click-Dbydr3nX.js";
|
|
2
2
|
import { defineCustomElement, defineProps, registerCustomElement, useEffect } from "@aria-ui/core";
|
|
3
3
|
import { parseYouTubeVideo } from "@post-embed/schema";
|
|
4
4
|
import el from "crelt";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/youtube/parse-url.ts
|
|
7
7
|
const YOUTUBE_HOSTS = /^(?:www\.|m\.)?(?:youtube\.com|youtube-nocookie\.com)$/i;
|
|
8
8
|
const YOUTU_BE_HOST = /^(?:www\.)?youtu\.be$/i;
|
|
9
9
|
const VIDEO_ID = /^[\w-]{11}$/;
|
|
@@ -56,8 +56,7 @@ function getEmbedUrl(ref) {
|
|
|
56
56
|
return `https://www.youtube-nocookie.com/embed/${ref.videoId}?${params}`;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
//#region src/youtube/video-click.ts
|
|
59
|
+
// src/youtube/video-click.ts
|
|
61
60
|
const YOUTUBE_VIDEO_CLICK = "meowdown-embed-youtube-click";
|
|
62
61
|
/**
|
|
63
62
|
* Returns false when a listener called `preventDefault()`: the host plays the
|
|
@@ -72,8 +71,7 @@ function dispatchVideoClick(target, detail) {
|
|
|
72
71
|
}));
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
//#region src/youtube/render-video.ts
|
|
74
|
+
// src/youtube/render-video.ts
|
|
77
75
|
function renderFrame(ref, title) {
|
|
78
76
|
return el("iframe", {
|
|
79
77
|
src: getEmbedUrl(ref),
|
|
@@ -144,10 +142,9 @@ function renderVideo(video, ref, playback) {
|
|
|
144
142
|
}, title), video.author_name ? renderLink(el("span", { "data-author": "" }, video.author_name), video.author_url) : void 0));
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
|
|
148
|
-
//#region src/youtube/youtube-video.ts
|
|
145
|
+
// src/youtube/youtube-video.ts
|
|
149
146
|
/** @internal */
|
|
150
|
-
function
|
|
147
|
+
function setupYouTubeVideo(host, props) {
|
|
151
148
|
const { fetched, pending } = useFetch(host, props, "YouTube video");
|
|
152
149
|
useEffect(host, () => {
|
|
153
150
|
host.dataset.meowdownEmbed = "youtube";
|
|
@@ -166,7 +163,7 @@ function renderFallback(pending) {
|
|
|
166
163
|
"data-pending": ""
|
|
167
164
|
} : { "data-fallback": "" }, el("div", { "data-details": "" }, el("span", { "data-title": "" }, "YouTube video")), el("p", { "data-body": "" }, pending ? "Loading this video…" : "This video is unavailable."), pending ? null : el("footer", { "data-footer": "" }, "No saved video could be displayed."));
|
|
168
165
|
}
|
|
169
|
-
const YouTubeVideoCustomElement = defineCustomElement(
|
|
166
|
+
const YouTubeVideoCustomElement = defineCustomElement(setupYouTubeVideo, defineProps({
|
|
170
167
|
data: {
|
|
171
168
|
default: null,
|
|
172
169
|
attribute: false
|
|
@@ -186,11 +183,9 @@ const YouTubeVideoCustomElement = defineCustomElement(useYouTubeVideo, definePro
|
|
|
186
183
|
}
|
|
187
184
|
}));
|
|
188
185
|
|
|
189
|
-
|
|
190
|
-
//#region src/youtube/register.ts
|
|
186
|
+
// src/youtube/register.ts
|
|
191
187
|
function registerYouTubeVideo(name = "meowdown-embed-youtube") {
|
|
192
188
|
registerCustomElement(name, class extends YouTubeVideoCustomElement {});
|
|
193
189
|
}
|
|
194
190
|
|
|
195
|
-
|
|
196
|
-
export { YOUTUBE_VIDEO_CLICK, registerYouTubeVideo, useYouTubeVideo };
|
|
191
|
+
export { YOUTUBE_VIDEO_CLICK, registerYouTubeVideo, setupYouTubeVideo, setupYouTubeVideo as useYouTubeVideo };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meowdown/embed",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@meowdown/vitest": "0.0.0",
|
|
33
33
|
"@ocavue/tsconfig": "^0.7.1",
|
|
34
|
-
"@ocavue/utils": "^1.
|
|
35
|
-
"@vitest/browser-playwright": "^5.0.
|
|
36
|
-
"tsdown": "^0.23.
|
|
37
|
-
"vitest": "^5.0.
|
|
34
|
+
"@ocavue/utils": "^1.11.0",
|
|
35
|
+
"@vitest/browser-playwright": "^5.0.5",
|
|
36
|
+
"tsdown": "^0.23.3",
|
|
37
|
+
"vitest": "^5.0.5"
|
|
38
38
|
},
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public"
|