scrapbox-url-customizer
How to use
2. 次を自分のページに書く
継続して使う場合は、すべてのコードを自分のprojectに移植してください
sample.jsimport {execute} from '/api/code/programming-notes/scrapbox-url-customizer/script.js';
execute();
変換処理をcustomizeしたいときは、 execute()
に設定を渡してください
e.g.
sample2.jsimport {execute} from '/api/code/programming-notes/scrapbox-url-customizer/script.js';
const format = text => text
.trim().replace(/[\n\r\f]/g, '').replace(' ?[', '[').replace('] ?', ']');
execute([{
match: /https:\/\/qiita\.com/,
text: ({url, title, meta, dom, hash}) => {
console.log({url, title, hash});
const span = dom.getElementById(hash);
if (!span) return `[${url} ${title}]`;
const subtitle = span.parentNode.textContent;
return `[${url} ${format(subtitle)} | ${format(title)}]`;
},
}]);
既知の問題
まだ一部のサイトで文字化けするみたい
どのサイトだったかは忘れたリストをここに書く
対策
implementation
変更点
UTF-8以外の文字コードに対応した
応答ヘッダと
<meta>
タグのどちらにもエンコード情報がないページには対応していない
というかどうやって対応しろと……
とても速くなった
めっちゃ速い
外部のserverを経由しなくなった
サイトごとに個別の変換設定を作れるようにした
convertWholeText()
の第2引数に渡す
e.g.
jsconst format = text => text
.trim().replace(/[\n\r\f]/g, '').replace(' ?[', '[').replace('] ?', ']');
export const config = [
{
match: /https:\/\/qiita\.com/,
text: ({url, title, meta, dom, hash}) => {
const span = dom.getElementById(hash);
if (!span) return `[${url} ${title}]`;
const subtitle = span.parentNode.textContent;
return `[${url} ${format(subtitle)} | ${format(title)}]`;
},
},
// 任意のweb pageに対するカスタム設定
{
match: /.*/,
text: ({url, title, meta, dom, hash}) => {
const subtitle = dom.getElementById(hash)?.textContent;
return subtitle ? `[${url} ${format(subtitle)} | ${format(title)}]`
: `[${url} ${format(title)}]`;
},
},
];
code
本体
script.jsimport {convertWholeText} from './convert.js';
import {insertText} from '../テキストを挿入するUserScript/script.js';
export const execute = (config = []) =>
scrapbox.PopupMenu.addButton({
title: text => /https?:\/\/\S+/.test(text) ? 'URL' : '.',// URLがなければボタンを押しにくくする
onClick: text => {
if (!/https?:\/\/\S+/.test(text)) return; // URLがなければ何もしない
convertWholeText(text, config).then(text => insertText({text}));
/*const cursor = document.getElementById('text-input');
convertWholeText(text, config).then(text => insertText({ text, cursor }));*/
return '';// 入力しやすいよう選択範囲を先に消しておく
},
});
cursorを明示しないとエラーが出ました
です
それは変です
さんの使っている
insertText
の定義が古いのかもしれません
複数のURLを含んだテキストをまとめて変換する
convert.jsexport async function convertWholeText(text, config = []) {
const urls = text.match(/https?:\/\/\S+/g) ?? [];
if (urls.length === 0) return undefined;
const links = await Promise.all(urls.map(url => convert(url, config)));
let map = {};
for (let i = 0; i < urls.length; i++) {
if (!links[i]) break;
map[urls[i]]= links[i];
}
//console.log(map);
const result = text.replace(/https?:\/\/\S+/g, match => map[match] ?? match);
//console.log(result);
return result;
}
URLを外部リンク記法に変換する
config
に、サイトごとの設定を書く
convert.jsasync function convert(url, config) {
if (!window.fetchURLInfo) {
alert('Please install "fetchURLInfo" from https://scrapbox.io/programming-notes/url-info-proxy');
return;
}
const pending = fetchURLInfo(url);
// hashを分離する
const urlObj = new URL(url);
//console.log(urlObj);
let hash = urlObj.hash !== '' ? decodeURIComponent(urlObj.hash).slice(1) : ''; // #をとる
let pureURL = `${urlObj.origin}${urlObj.pathname}${urlObj.search}`;
const {title, meta, DOM} = await fetchURLInfo(pureURL, {DOM: true});
//console.log({title, meta, DOM});
return (config.find(({match}) => match.test(url))?.text ?? defaultConfig)({
url,
pureURL,
title,
hash,
meta,
dom: DOM,
});
}
defaultの変換設定
convert.jsconst format = text => text
.trim().replace(/[\n\r\f]/g, '').replace(' ?[', '[').replace('] ?', ']');
function defaultConfig({url, title, hash, dom}) {
if (!title) return url;
const subtitle = dom.getElementById(hash)?.textContent;
return subtitle ?
`[${url} ${format(subtitle)} | ${format(title)}]` :
`[${url} ${format(title)}]`;
}