generated at
url-info-proxy
scrapbox-url-customizerで任意のdomainのweb pageのデータを取得するのに必要なGreasemonkey UserScript
TamperMonkeyにコピペしてinstallして下さい
実行するたびに、cross domainへの接続確認画面が表示されます
適宜許可を出してください
確認画面を出さないように設定することも出来ます

特徴
外部のserverless functionを使わず、web browserのみで処理が完結する
任意のdomainのdataをfetchする事ができるとわかったので、url-infoを使う必要がなくなりました
Shift-JISなど変な文字コードのweb pageのデータも文字化けせずに取得できる
へえ〜 なんでだろうyosider
TextDecoderを使ってエンコードしているだけですtakker

使い方
js
const data = await fetchURLInfo('https://example.com', {DOM: false});
DOM (optional)
true : 解析したweb pageのDOMを付与する
false (default): DOMを付与しない
返り値
ts
type Result = Promise<{ title: string; // web pageのタイトル encoding: string; // web pageの文字コード meta: { [key: string]: string }[]; // <meta>に入っている属性 }>;

tampermonkey.js
// ==UserScript== // @name url-info-proxy // @namespace https://scrapbox.io // @version 0.2 // @description fetch the title and OGP data from URL // @author takker // @match https://scrapbox.io/* // @connect * // @grant GM_xmlhttpRequest // @license MIT // @copyright Copyright (c) 2021 takker // ==/UserScript== "use strict" unsafeWindow.fetchURLInfo = (url, {DOM = false} = {}) => new Promise(resolve => GM_xmlhttpRequest({ method: "GET", url, onload: ({response: arrayBuffer, responseText}) => { const encoding = getEncoding(responseText); const html = new TextDecoder(encoding).decode(arrayBuffer); const dom = new DOMParser().parseFromString(html, 'text/html'); resolve({ encoding, ...(DOM ? {DOM: dom} : {}), ...getPageInfo(dom)}); }, withCredentials: true,
tampermonkey.js
responseType: 'arraybuffer', }) );

文字コードを判別する
tampermonkey.js
function getEncoding(responseText) { const dom = new DOMParser().parseFromString(responseText, 'text/html'); return dom.querySelector('meta[charset]')?.getAttribute?.('charset') ?? dom.querySelector('meta[http-equiv="content-type"]') ?.content?.match?.(/charset=([^;]+)/)?.[1] ?? 'utf-8'; }

DOMを解析して、meta dataを返す
tampermonkey.js
function getPageInfo(dom) { const metaData = [...dom.head.getElementsByTagName('meta')] .map(meta => { const names = meta.getAttributeNames(); let result = {}; for (const name of names) { result[name] = meta.getAttribute(name); } return result; }); return {meta: metaData, title: dom.title}; }

#2021-02-25 22:33:43