Skip to content

Commit 6b5f282

Browse files
authored
Merge pull request #70 from takker99/thumbnail
🐛 Youtubeのサムネイルをページカードのサムネイルにできていなかった
2 parents c6bc021 + 2895b43 commit 6b5f282

File tree

3 files changed

+91
-17
lines changed

3 files changed

+91
-17
lines changed

browser/websocket/makeChanges.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,35 @@ import {
1010
import type { Change } from "../../deps/socket.ts";
1111
import type { HeadData } from "./pull.ts";
1212
import { toTitleLc } from "../../title.ts";
13+
import { parseYoutube } from "../../parseYoutube.ts";
1314

1415
export interface Init {
1516
userId: string;
1617
head: HeadData;
1718
}
18-
export const makeChanges = (
19+
export function* makeChanges(
1920
left: Pick<Line, "text" | "id">[],
2021
right: string[],
2122
{ userId, head }: Init,
22-
): Change[] => {
23+
): Generator<Change, void, unknown> {
2324
// 改行文字が入るのを防ぐ
2425
const right_ = right.flatMap((text) => text.split("\n"));
25-
// 本文の差分
26-
const changes: Change[] = [...diffToChanges(left, right_, { userId })];
26+
// 本文の差分を先に返す
27+
for (const change of diffToChanges(left, right_, { userId })) {
28+
yield change;
29+
}
2730

2831
// titleの差分を入れる
2932
// 空ページの場合もタイトル変更commitを入れる
3033
if (left[0].text !== right_[0] || !head.persistent) {
31-
changes.push({ title: right_[0] });
34+
yield { title: right_[0] };
3235
}
3336

3437
// descriptionsの差分を入れる
3538
const leftDescriptions = left.slice(1, 6).map((line) => line.text);
3639
const rightDescriptions = right_.slice(1, 6);
3740
if (leftDescriptions.join("") !== rightDescriptions.join("")) {
38-
changes.push({ descriptions: rightDescriptions });
41+
yield { descriptions: rightDescriptions };
3942
}
4043

4144
// リンクと画像の差分を入れる
@@ -44,14 +47,12 @@ export const makeChanges = (
4447
head.links.length !== links.length ||
4548
!head.links.every((link) => links.includes(link))
4649
) {
47-
changes.push({ links });
50+
yield { links };
4851
}
4952
if (head.image !== image) {
50-
changes.push({ image });
53+
yield { image };
5154
}
52-
53-
return changes;
54-
};
55+
}
5556

5657
/** テキストに含まれる全てのリンクと最初の画像を探す */
5758
const findLinksAndImage = (text: string): [string[], string | null] => {
@@ -86,11 +87,20 @@ const findLinksAndImage = (text: string): [string[], string | null] => {
8687
links.push(node.href);
8788
return;
8889
case "link":
89-
if (node.pathType !== "relative") return;
90-
if (linksLc.get(toTitleLc(node.href))) return;
91-
linksLc.set(toTitleLc(node.href), true);
92-
links.push(node.href);
93-
return;
90+
switch (node.pathType) {
91+
case "relative":
92+
if (linksLc.get(toTitleLc(node.href))) return;
93+
linksLc.set(toTitleLc(node.href), true);
94+
links.push(node.href);
95+
return;
96+
case "absolute": {
97+
const props = parseYoutube(node.href);
98+
if (!props) return;
99+
return `https://i.ytimg.com/vi/${props.videoId}/mqdefault.jpg`;
100+
}
101+
default:
102+
return;
103+
}
94104
case "image":
95105
case "strongImage": {
96106
image ??= node.src.endsWith("/thumb/1000")

browser/websocket/patch.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ export const patch = async (
6565
});
6666
}
6767

68-
const changes = makeChanges(head.lines, newLines, { userId, head });
68+
const changes = [
69+
...makeChanges(head.lines, newLines, { userId, head }),
70+
];
6971
await pushCommit(request, changes, {
7072
parentId: head.commitId,
7173
projectId,

parseYoutube.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// ported from https://github.com/takker99/ScrapBubble/blob/0.4.0/Page.tsx#L662
2+
3+
export interface YoutubeProps {
4+
params: URLSearchParams;
5+
videoId: string;
6+
}
7+
8+
const youtubeRegExp =
9+
/https?:\/\/(?:www\.|)youtube\.com\/watch\?((?:[^\s]+&|)v=([a-zA-Z\d_-]+)(?:&[^\s]+|))/;
10+
const youtubeShortRegExp =
11+
/https?:\/\/youtu\.be\/([a-zA-Z\d_-]+)(?:\?([^\s]{0,100})|)/;
12+
const youtubeListRegExp =
13+
/https?:\/\/(?:www\.|)youtube\.com\/playlist\?((?:[^\s]+&|)list=([a-zA-Z\d_-]+)(?:&[^\s]+|))/;
14+
15+
/** YoutubeのURLを解析してVideo IDなどを取り出す
16+
*
17+
* @param url YoutubeのURL
18+
* @return 解析結果 YoutubeのURLでなかったときは`undefined`を返す
19+
*/
20+
export const parseYoutube = (url: string): YoutubeProps | undefined => {
21+
{
22+
const matches = url.match(youtubeRegExp);
23+
if (matches) {
24+
const [, params, videoId] = matches;
25+
const _params = new URLSearchParams(params);
26+
_params.delete("v");
27+
_params.append("autoplay", "0");
28+
return {
29+
videoId,
30+
params: _params,
31+
};
32+
}
33+
}
34+
{
35+
const matches = url.match(youtubeShortRegExp);
36+
if (matches) {
37+
const [, videoId] = matches;
38+
return {
39+
videoId,
40+
params: new URLSearchParams("autoplay=0"),
41+
};
42+
}
43+
}
44+
{
45+
const matches = url.match(youtubeListRegExp);
46+
if (matches) {
47+
const [, params, listId] = matches;
48+
49+
const _params = new URLSearchParams(params);
50+
const videoId = _params.get("v");
51+
if (!videoId) return;
52+
_params.delete("v");
53+
_params.append("autoplay", "0");
54+
_params.append("list", listId);
55+
return {
56+
videoId,
57+
params: _params,
58+
};
59+
}
60+
}
61+
return undefined;
62+
};

0 commit comments

Comments
 (0)