refactor: use context style

This commit is contained in:
Acid Chicken (硫酸鶏) 2024-05-30 18:21:47 +09:00
parent c953d238a6
commit 475ba6baba
No known key found for this signature in database
GPG Key ID: 3E87B98A3F6BAB99
22 changed files with 220 additions and 188 deletions

5
src/context.ts Normal file
View File

@ -0,0 +1,5 @@
export default interface Context {
html: HTMLRewriter
request: Request
url: URL
}

View File

@ -2,6 +2,7 @@ import { Hono } from "hono"
import { requestInit } from "./config" import { requestInit } from "./config"
import { normalize } from "./encoding" import { normalize } from "./encoding"
import summary from "./summary" import summary from "./summary"
import type Context from "./context"
export interface Env { export interface Env {
// Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/ // Example binding to KV. Learn more at https://developers.cloudflare.com/workers/runtime-apis/kv/
// MY_KV_NAMESPACE: KVNamespace; // MY_KV_NAMESPACE: KVNamespace;
@ -33,7 +34,11 @@ app.get("/url", async (context) => {
const response = (await fetch(url, requestInit(context.req.raw))) as any as Response const response = (await fetch(url, requestInit(context.req.raw))) as any as Response
url = new URL(response.url) url = new URL(response.url)
const rewriter = new HTMLRewriter() const rewriter = new HTMLRewriter()
const summarized = summary(context.req.raw, url, rewriter) const summarized = summary({
html: rewriter,
request: context.req.raw,
url,
})
const reader = (rewriter.transform(await normalize(response)).body as ReadableStream<Uint8Array>).getReader() const reader = (rewriter.transform(await normalize(response)).body as ReadableStream<Uint8Array>).getReader()
while (!(await reader.read()).done); while (!(await reader.read()).done);
return context.json(await summarized) return context.json(await summarized)

View File

@ -2,20 +2,22 @@ import { decode } from "html-entities"
import clip from "summaly/built/utils/clip" import clip from "summaly/built/utils/clip"
import { BufferedTextHandler, assign } from "../common" import { BufferedTextHandler, assign } from "../common"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
import type Context from "../../context"
export default function getDescription(url: URL, html: HTMLRewriter) { export default function getDescription(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 3, // 0-7 bits: 3, // 0-7
priority: 0, priority: 0,
content: null, content: null,
} }
html.on( context.html.on(
"#productDescription", "#productDescription",
new BufferedTextHandler((text) => { new BufferedTextHandler((text) => {
assign(result, 7, decode(text)) assign(result, 7, decode(text))
}), }),
) )
html.on('meta[property="og:description"]', { context.html.on('meta[property="og:description"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -23,7 +25,7 @@ export default function getDescription(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:description"]', { context.html.on('meta[name="twitter:description"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -31,7 +33,7 @@ export default function getDescription(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="description"]', { context.html.on('meta[name="description"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -39,11 +41,10 @@ export default function getDescription(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content && clip(result.content, 300))
resolve(result.content && clip(result.content, 300)) },
},
})
}) })
return promise
} }

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign, toAbsoluteURL } from "../common" import { assign, toAbsoluteURL } from "../common"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
import type Context from "../../context"
export default function getImage(url: URL, html: HTMLRewriter) { export default function getImage(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 4, // 0-15 bits: 4, // 0-15
priority: 0, priority: 0,
content: null, content: null,
} }
html.on("#landingImage", { context.html.on("#landingImage", {
element(element) { element(element) {
const content = element.getAttribute("src") const content = element.getAttribute("src")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[property="og:image"]', { context.html.on('meta[property="og:image"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -24,7 +26,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:image"]', { context.html.on('meta[name="twitter:image"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -32,7 +34,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('link[rel="image_src"]', { context.html.on('link[rel="image_src"]', {
element(element) { element(element) {
const content = element.getAttribute("href") const content = element.getAttribute("href")
if (content) { if (content) {
@ -40,7 +42,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('link[rel="apple-touch-icon"]', { context.html.on('link[rel="apple-touch-icon"]', {
element(element) { element(element) {
const content = element.getAttribute("href") const content = element.getAttribute("href")
if (content) { if (content) {
@ -48,7 +50,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('link[rel="apple-touch-icon image_src"]', { context.html.on('link[rel="apple-touch-icon image_src"]', {
element(element) { element(element) {
const content = element.getAttribute("href") const content = element.getAttribute("href")
if (content) { if (content) {
@ -56,11 +58,10 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content ? toAbsoluteURL(result.content, context.url.href) : null)
resolve(result.content ? toAbsoluteURL(result.content, url.href) : null) },
},
})
}) })
return promise
} }

View File

@ -10,12 +10,13 @@ import getPlayerUrlWidth from "../general/playerUrlWidth"
import getSiteName from "../general/siteName" import getSiteName from "../general/siteName"
import getTitle from "./title" import getTitle from "./title"
import getSensitive from "../general/sensitive" import getSensitive from "../general/sensitive"
import type Context from "../../context"
export default function amazon(url: URL, html: HTMLRewriter) { export default function amazon(context: Context) {
const card = getCard(url, html) const card = getCard(context)
const title = getTitle(url, html) const title = getTitle(context)
const thumbnail = getImage(url, html) const thumbnail = getImage(context)
const player = Promise.all([card, getPlayerUrlGeneral(url, html), getPlayerUrlCommon(url, html), getPlayerUrlWidth(url, html), getPlayerUrlHeight(url, html)]).then(([card, general, common, width, height]) => { const player = Promise.all([card, getPlayerUrlGeneral(context), getPlayerUrlCommon(context), getPlayerUrlWidth(context), getPlayerUrlHeight(context)]).then(([card, general, common, width, height]) => {
const url = (card !== "summary_large_image" && general) || common const url = (card !== "summary_large_image" && general) || common
if (url !== null && width !== null && height !== null) { if (url !== null && width !== null && height !== null) {
return { return {
@ -31,10 +32,10 @@ export default function amazon(url: URL, html: HTMLRewriter) {
} }
} }
}) })
const description = getDescription(url, html) const description = getDescription(context)
const siteName = getSiteName(url, html) const siteName = getSiteName(context)
const favicon = getFavicon(url, html) const favicon = getFavicon(context)
const sensitive = getSensitive(url, html) const sensitive = getSensitive(context)
return Promise.all([title, thumbnail, player, description, siteName, favicon, sensitive]).then(([title, thumbnail, player, description, siteName, favicon, sensitive]) => { return Promise.all([title, thumbnail, player, description, siteName, favicon, sensitive]).then(([title, thumbnail, player, description, siteName, favicon, sensitive]) => {
if (title === null) { if (title === null) {
@ -51,7 +52,7 @@ export default function amazon(url: URL, html: HTMLRewriter) {
sitename: siteName, sitename: siteName,
icon: favicon, icon: favicon,
sensitive, sensitive,
url: url.href, url: context.url.href,
} }
}) })
} }

View File

@ -2,20 +2,22 @@ import { decode } from "html-entities"
import clip from "summaly/built/utils/clip" import clip from "summaly/built/utils/clip"
import { BufferedTextHandler, assign } from "../common" import { BufferedTextHandler, assign } from "../common"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
import type Context from "../../context"
export default function getTitle(url: URL, html: HTMLRewriter) { export default function getTitle(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 3, // 0-7 bits: 3, // 0-7
priority: 0, priority: 0,
content: null, content: null,
} }
html.on( context.html.on(
"#title", "#title",
new BufferedTextHandler((text) => { new BufferedTextHandler((text) => {
assign(result, 7, decode(text)) assign(result, 7, decode(text))
}), }),
) )
html.on('meta[property="og:title"]', { context.html.on('meta[property="og:title"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -23,7 +25,7 @@ export default function getTitle(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:title"]', { context.html.on('meta[name="twitter:title"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -31,17 +33,16 @@ export default function getTitle(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on( context.html.on(
"title", "title",
new BufferedTextHandler((text) => { new BufferedTextHandler((text) => {
assign(result, 1, decode(text)) assign(result, 1, decode(text))
}), }),
) )
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content && clip(result.content, 100))
resolve(result.content && clip(result.content, 100)) },
},
})
}) })
return promise
} }

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign } from "../common" import { assign } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getCard(url: URL, html: HTMLRewriter) { export default function getCard(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: null, content: null,
} }
html.on('meta[name="twitter:card"]', { context.html.on('meta[name="twitter:card"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getCard(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[property="twitter:card"]', { context.html.on('meta[property="twitter:card"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -24,11 +26,10 @@ export default function getCard(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content)
resolve(result.content) },
},
})
}) })
return promise
} }

View File

@ -1,15 +1,17 @@
import { decode } from "html-entities"
import clip from "summaly/built/utils/clip" import clip from "summaly/built/utils/clip"
import { assign } from "../common" import { assign } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
import { decode } from "html-entities"
export default function getDescription(url: URL, html: HTMLRewriter) { export default function getDescription(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: null, content: null,
} }
html.on('meta[property="og:description"]', { context.html.on('meta[property="og:description"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -17,7 +19,7 @@ export default function getDescription(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:description"]', { context.html.on('meta[name="twitter:description"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -25,7 +27,7 @@ export default function getDescription(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="description"]', { context.html.on('meta[name="description"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -33,11 +35,10 @@ export default function getDescription(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content && clip(result.content, 300))
resolve(result.content && clip(result.content, 300)) },
},
})
}) })
return promise
} }

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign, toAbsoluteURL } from "../common" import { assign, toAbsoluteURL } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getFavicon(url: URL, html: HTMLRewriter) { export default function getFavicon(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string>()
const result: PrioritizedReference<string> = { const result: PrioritizedReference<string> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: "/favicon.ico", content: "/favicon.ico",
} }
html.on('link[rel="shortcut icon"]', { context.html.on('link[rel="shortcut icon"]', {
element(element) { element(element) {
const content = element.getAttribute("href") const content = element.getAttribute("href")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getFavicon(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('link[rel="icon"]', { context.html.on('link[rel="icon"]', {
element(element) { element(element) {
const content = element.getAttribute("href") const content = element.getAttribute("href")
if (content) { if (content) {
@ -24,11 +26,10 @@ export default function getFavicon(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(toAbsoluteURL(result.content, context.url.href))
resolve(toAbsoluteURL(result.content, url.href)) },
},
})
}) })
return promise
} }

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign, toAbsoluteURL } from "../common" import { assign, toAbsoluteURL } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getImage(url: URL, html: HTMLRewriter) { export default function getImage(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 3, // 0-7 bits: 3, // 0-7
priority: 0, priority: 0,
content: null, content: null,
} }
html.on('meta[property="og:image"]', { context.html.on('meta[property="og:image"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:image"]', { context.html.on('meta[name="twitter:image"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -24,7 +26,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('link[rel="image_src"]', { context.html.on('link[rel="image_src"]', {
element(element) { element(element) {
const content = element.getAttribute("href") const content = element.getAttribute("href")
if (content) { if (content) {
@ -32,7 +34,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('link[rel="apple-touch-icon"]', { context.html.on('link[rel="apple-touch-icon"]', {
element(element) { element(element) {
const content = element.getAttribute("href") const content = element.getAttribute("href")
if (content) { if (content) {
@ -40,7 +42,7 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('link[rel="apple-touch-icon image_src"]', { context.html.on('link[rel="apple-touch-icon image_src"]', {
element(element) { element(element) {
const content = element.getAttribute("href") const content = element.getAttribute("href")
if (content) { if (content) {
@ -48,11 +50,10 @@ export default function getImage(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content ? toAbsoluteURL(result.content, context.url.href) : null)
resolve(result.content ? toAbsoluteURL(result.content, url.href) : null) },
},
})
}) })
return promise
} }

View File

@ -7,12 +7,13 @@ import getSiteName from "./siteName"
import getTitle from "./title" import getTitle from "./title"
import getSensitive from "./sensitive" import getSensitive from "./sensitive"
import getPlayer, { Player } from "./player" import getPlayer, { Player } from "./player"
import type Context from "../../context"
export default function general(request: Request, url: URL, html: HTMLRewriter) { export default function general(context: Context) {
const card = getCard(url, html) const card = getCard(context)
const title = getTitle(url, html) const title = getTitle(context)
const image = getImage(url, html) const image = getImage(context)
const player = Promise.all([card, getPlayer(request, url, html)]).then<Player>(([card, parsedPlayer]) => { const player = Promise.all([card, getPlayer(context)]).then<Player>(([card, parsedPlayer]) => {
return { return {
url: (card !== "summary_large_image" && parsedPlayer.urlGeneral) || parsedPlayer.urlCommon, url: (card !== "summary_large_image" && parsedPlayer.urlGeneral) || parsedPlayer.urlCommon,
width: parsedPlayer.width, width: parsedPlayer.width,
@ -20,10 +21,10 @@ export default function general(request: Request, url: URL, html: HTMLRewriter)
allow: parsedPlayer.allow, allow: parsedPlayer.allow,
} }
}) })
const description = getDescription(url, html) const description = getDescription(context)
const siteName = getSiteName(url, html) const siteName = getSiteName(context)
const favicon = getFavicon(url, html) const favicon = getFavicon(context)
const sensitive = getSensitive(url, html) const sensitive = getSensitive(context)
return Promise.all([card, title, image, player, description, siteName, favicon, sensitive]).then(([card, title, image, player, description, siteName, favicon, sensitive]) => { return Promise.all([card, title, image, player, description, siteName, favicon, sensitive]).then(([card, title, image, player, description, siteName, favicon, sensitive]) => {
if (title === null) { if (title === null) {
@ -41,7 +42,7 @@ export default function general(request: Request, url: URL, html: HTMLRewriter)
icon: favicon, icon: favicon,
sensitive, sensitive,
large: card === "summary_large_image", large: card === "summary_large_image",
url: url.href, url: context.url.href,
} }
}) })
} }

View File

@ -3,6 +3,7 @@ import getPlayerUrlCommon from "./playerUrlCommon"
import getPlayerUrlGeneral from "./playerUrlGeneral" import getPlayerUrlGeneral from "./playerUrlGeneral"
import getPlayerUrlHeight from "./playerUrlHeight" import getPlayerUrlHeight from "./playerUrlHeight"
import getPlayerUrlWidth from "./playerUrlWidth" import getPlayerUrlWidth from "./playerUrlWidth"
import type Context from "../../context"
export interface Player { export interface Player {
url: string | null url: string | null
@ -16,12 +17,12 @@ export interface ParsedPlayer extends Omit<Player, "url"> {
urlGeneral: string | null urlGeneral: string | null
} }
export default function getPlayer(request: Request, url: URL, html: HTMLRewriter): Promise<ParsedPlayer> { export default function getPlayer(context: Context): Promise<ParsedPlayer> {
const oEmbed = getPlayerOEmbed(request, url, html) const oEmbed = getPlayerOEmbed(context)
const urlGeneral = getPlayerUrlGeneral(url, html) const urlGeneral = getPlayerUrlGeneral(context)
const urlCommon = getPlayerUrlCommon(url, html) const urlCommon = getPlayerUrlCommon(context)
const width = getPlayerUrlWidth(url, html) const width = getPlayerUrlWidth(context)
const height = getPlayerUrlHeight(url, html) const height = getPlayerUrlHeight(context)
return Promise.all([oEmbed, urlGeneral, urlCommon, width, height]).then(([oEmbed, urlGeneral, urlCommon, width, height]) => { return Promise.all([oEmbed, urlGeneral, urlCommon, width, height]).then(([oEmbed, urlGeneral, urlCommon, width, height]) => {
if (oEmbed) { if (oEmbed) {

View File

@ -2,6 +2,7 @@ import { decode } from "html-entities"
import { z } from "zod" import { z } from "zod"
import { requestInit } from "../../config" import { requestInit } from "../../config"
import { assign, PrioritizedReference } from "../common" import { assign, PrioritizedReference } from "../common"
import type Context from "../../context"
import type { ParsedPlayer } from "./player" import type { ParsedPlayer } from "./player"
const oEmbedBase = z.object({ const oEmbedBase = z.object({
@ -41,7 +42,7 @@ const oEmbed = z.union([
}), }),
]) ])
export default function getPlayerOEmbed(request: Request, url: URL, html: HTMLRewriter) { export default function getPlayerOEmbed(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<ParsedPlayer>() const { promise, resolve, reject } = Promise.withResolvers<ParsedPlayer>()
const result: PrioritizedReference<ParsedPlayer> = { const result: PrioritizedReference<ParsedPlayer> = {
bits: 1, // 0-1 bits: 1, // 0-1
@ -54,7 +55,7 @@ export default function getPlayerOEmbed(request: Request, url: URL, html: HTMLRe
allow: [], allow: [],
}, },
} }
html.on('link[type="application/json+oembed"]', { context.html.on('link[type="application/json+oembed"]', {
async element(element) { async element(element) {
const oEmbedHref = decode(element.getAttribute("href") ?? "") const oEmbedHref = decode(element.getAttribute("href") ?? "")
if (!oEmbedHref) { if (!oEmbedHref) {
@ -62,7 +63,7 @@ export default function getPlayerOEmbed(request: Request, url: URL, html: HTMLRe
} }
let init: RequestInit let init: RequestInit
try { try {
init = requestInit(request) init = requestInit(context.request)
} catch (e) { } catch (e) {
reject(e) reject(e)
return return
@ -120,7 +121,7 @@ export default function getPlayerOEmbed(request: Request, url: URL, html: HTMLRe
} }
}, },
}) })
html.onDocument({ context.html.onDocument({
end() { end() {
resolve(result.content) resolve(result.content)
}, },

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign, toAbsoluteURL } from "../common" import { assign, toAbsoluteURL } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getPlayerUrlCommon(url: URL, html: HTMLRewriter) { export default function getPlayerUrlCommon(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: null, content: null,
} }
html.on('meta[property="og:video"]', { context.html.on('meta[property="og:video"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getPlayerUrlCommon(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[property="og:video:secure_url"]', { context.html.on('meta[property="og:video:secure_url"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -24,7 +26,7 @@ export default function getPlayerUrlCommon(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[property="og:video:url"]', { context.html.on('meta[property="og:video:url"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -32,11 +34,10 @@ export default function getPlayerUrlCommon(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content ? toAbsoluteURL(result.content, context.url.href) : null)
resolve(result.content ? toAbsoluteURL(result.content, url.href) : null) },
},
})
}) })
return promise
} }

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign, toAbsoluteURL } from "../common" import { assign, toAbsoluteURL } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getPlayerUrlGeneral(url: URL, html: HTMLRewriter) { export default function getPlayerUrlGeneral(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: null, content: null,
} }
html.on('meta[property="twitter:player"]', { context.html.on('meta[property="twitter:player"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getPlayerUrlGeneral(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:player"]', { context.html.on('meta[name="twitter:player"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -24,11 +26,10 @@ export default function getPlayerUrlGeneral(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content ? toAbsoluteURL(result.content, context.url.href) : null)
resolve(result.content ? toAbsoluteURL(result.content, url.href) : null) },
},
})
}) })
return promise
} }

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign } from "../common" import { assign } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getPlayerUrlHeight(url: URL, html: HTMLRewriter) { export default function getPlayerUrlHeight(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<number | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: null, content: null,
} }
html.on('meta[property="twitter:player:height"]', { context.html.on('meta[property="twitter:player:height"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getPlayerUrlHeight(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:player:height"]', { context.html.on('meta[name="twitter:player:height"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -24,7 +26,7 @@ export default function getPlayerUrlHeight(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[property="og:video:height"]', { context.html.on('meta[property="og:video:height"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -32,12 +34,11 @@ export default function getPlayerUrlHeight(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<number | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { const content = parseInt(result.content!, 10)
const content = parseInt(result.content!, 10) resolve(Number.isNaN(content) ? null : content)
resolve(Number.isNaN(content) ? null : content) },
},
})
}) })
return promise
} }

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign } from "../common" import { assign } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getPlayerUrlWidth(url: URL, html: HTMLRewriter) { export default function getPlayerUrlWidth(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<number | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: null, content: null,
} }
html.on('meta[property="twitter:player:width"]', { context.html.on('meta[property="twitter:player:width"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getPlayerUrlWidth(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:player:width"]', { context.html.on('meta[name="twitter:player:width"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -24,7 +26,7 @@ export default function getPlayerUrlWidth(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[property="og:video:width"]', { context.html.on('meta[property="og:video:width"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -32,12 +34,11 @@ export default function getPlayerUrlWidth(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<number | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { const content = parseInt(result.content!, 10)
const content = parseInt(result.content!, 10) resolve(Number.isNaN(content) ? null : content)
resolve(Number.isNaN(content) ? null : content) },
},
})
}) })
return promise
} }

View File

@ -1,22 +1,23 @@
import { assign } from "../common" import { assign } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getSensitive(url: URL, html: HTMLRewriter) { export default function getSensitive(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<boolean>()
const result: PrioritizedReference<boolean> = { const result: PrioritizedReference<boolean> = {
bits: 1, // 0-1 bits: 1, // 0-1
priority: 0, priority: 0,
content: false, content: false,
} }
html.on('.tweet[data-possibly-sensitive="true"]', { context.html.on('.tweet[data-possibly-sensitive="true"]', {
element() { element() {
assign(result, 1, true) assign(result, 1, true)
}, },
}) })
return new Promise<boolean>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content)
resolve(result.content) },
},
})
}) })
return promise
} }

View File

@ -1,14 +1,16 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import { assign } from "../common" import { assign } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getSiteName(url: URL, html: HTMLRewriter) { export default function getSiteName(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: url.hostname, content: context.url.hostname,
} }
html.on('meta[property="og:site_name"]', { context.html.on('meta[property="og:site_name"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -16,7 +18,7 @@ export default function getSiteName(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="application-name"]', { context.html.on('meta[name="application-name"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -24,11 +26,10 @@ export default function getSiteName(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content)
resolve(result.content) },
},
})
}) })
return promise
} }

View File

@ -1,15 +1,17 @@
import { decode } from "html-entities" import { decode } from "html-entities"
import clip from "summaly/built/utils/clip" import clip from "summaly/built/utils/clip"
import { BufferedTextHandler, assign } from "../common" import { BufferedTextHandler, assign } from "../common"
import type Context from "../../context"
import type { PrioritizedReference } from "../common" import type { PrioritizedReference } from "../common"
export default function getTitle(url: URL, html: HTMLRewriter) { export default function getTitle(context: Context) {
const { promise, resolve, reject } = Promise.withResolvers<string | null>()
const result: PrioritizedReference<string | null> = { const result: PrioritizedReference<string | null> = {
bits: 2, // 0-3 bits: 2, // 0-3
priority: 0, priority: 0,
content: null, content: null,
} }
html.on('meta[property="og:title"]', { context.html.on('meta[property="og:title"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -17,7 +19,7 @@ export default function getTitle(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on('meta[name="twitter:title"]', { context.html.on('meta[name="twitter:title"]', {
element(element) { element(element) {
const content = element.getAttribute("content") const content = element.getAttribute("content")
if (content) { if (content) {
@ -25,17 +27,16 @@ export default function getTitle(url: URL, html: HTMLRewriter) {
} }
}, },
}) })
html.on( context.html.on(
"title", "title",
new BufferedTextHandler((text) => { new BufferedTextHandler((text) => {
assign(result, 1, decode(text)) assign(result, 1, decode(text))
}), }),
) )
return new Promise<string | null>((resolve) => { context.html.onDocument({
html.onDocument({ end() {
end() { resolve(result.content && clip(result.content, 100))
resolve(result.content && clip(result.content, 100)) },
},
})
}) })
return promise
} }

View File

@ -1,13 +1,14 @@
import amazon from "./amazon" import amazon from "./amazon"
import general from "./general" import general from "./general"
import wikipedia from "./wikipedia" import wikipedia from "./wikipedia"
import type Context from "../context"
export default function summary(request: Request, url: URL, html: HTMLRewriter) { export default function summary(context: Context) {
if (url.hostname === "www.amazon.com" || url.hostname === "www.amazon.co.jp" || url.hostname === "www.amazon.ca" || url.hostname === "www.amazon.com.br" || url.hostname === "www.amazon.com.mx" || url.hostname === "www.amazon.co.uk" || url.hostname === "www.amazon.de" || url.hostname === "www.amazon.fr" || url.hostname === "www.amazon.it" || url.hostname === "www.amazon.es" || url.hostname === "www.amazon.nl" || url.hostname === "www.amazon.cn" || url.hostname === "www.amazon.in" || url.hostname === "www.amazon.au") { if (context.url.hostname === "www.amazon.com" || context.url.hostname === "www.amazon.co.jp" || context.url.hostname === "www.amazon.ca" || context.url.hostname === "www.amazon.com.br" || context.url.hostname === "www.amazon.com.mx" || context.url.hostname === "www.amazon.co.uk" || context.url.hostname === "www.amazon.de" || context.url.hostname === "www.amazon.fr" || context.url.hostname === "www.amazon.it" || context.url.hostname === "www.amazon.es" || context.url.hostname === "www.amazon.nl" || context.url.hostname === "www.amazon.cn" || context.url.hostname === "www.amazon.in" || context.url.hostname === "www.amazon.au") {
return amazon(url, html) return amazon(context)
} }
if (`.${url.hostname}`.endsWith(".wikipedia.org")) { if (`.${context.url.hostname}`.endsWith(".wikipedia.org")) {
return wikipedia(url, html) return wikipedia(context)
} }
return general(request, url, html) return general(context)
} }

View File

@ -1,10 +1,12 @@
import clip from "summaly/built/utils/clip" import clip from "summaly/built/utils/clip"
import { requestInit } from "../../config"
import type Context from "../../context"
export default async function wikipedia(url: URL, html: HTMLRewriter) { export default async function wikipedia(context: Context) {
const lang = url.hostname.split(".")[0] const lang = context.url.hostname.split(".")[0]
const title = url.pathname.split("/")[2] const title = context.url.pathname.split("/")[2]
const response = await fetch(`https://${lang}.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=${title}`) const response = await fetch(`https://${lang}.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=${title}`, requestInit(context.request))
const json = await response.json<any>() const json: any = await response.json()
const info = json.query.pages[Object.keys(json.query.pages)[0]] const info = json.query.pages[Object.keys(json.query.pages)[0]]
return { return {
title: info.title, title: info.title,
@ -15,8 +17,9 @@ export default async function wikipedia(url: URL, html: HTMLRewriter) {
url: null, url: null,
width: null, width: null,
height: null, height: null,
allow: [],
}, },
sitename: "Wikipedia", sitename: "Wikipedia",
url: url.href, url: context.url.href,
} }
} }