scrapbox-url-customizer
選択範囲内の任意のURLを外部リンク記法に書き換えるPopupMenu
/daiiz/daiiz-paste-url-titleのUserScript版
TamperMonkeyを使用する
/icons/iine.iconyosider.icon
How to use
1. url-info-proxyをinstallする
2. 次を自分のページに書く
/emoji/warning.icon継続して使う場合は、すべてのコードを自分のprojectに移植してください
code:sample.js
import {execute} from '/api/code/programming-notes/scrapbox-url-customizer/script.js';
execute();
変換処理をcustomizeしたいときは、execute()に設定を渡してください
e.g.
code:sample2.js
import {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)}];
},
}]);
変換設定の例は/takker/scrapbox-url-customizer-2のカスタム設定にあります
既知の問題
まだ一部のサイトで文字化けするみたい
どのサイトだったかは忘れたリストをここに書く
https://monoist.atmarkit.co.jp/mn/articles/2002/27/news030.html
http://home.p07.itscom.net/strmdrf/basic_com1.htm
http://www.jsce.or.jp/journal/index.shtml
https://www.yamareco.com/
https://pentan.info/php/content_disposition_filename.html
https://kakaku.com
対策
encoding.jsを使えば文字コードを判定できそう
implementation
/takker/scrapbox-url-customizerを参考に作り直した
変更点
UTF-8以外の文字コードに対応した
/icons/god.iconyosider.icon
/emoji/warning.icon応答ヘッダと<meta>タグのどちらにもエンコード情報がないページには対応していない
というかどうやって対応しろと……takker.icon
とても速くなった
https://gyazo.com/0e42860aa0c5ecee7259b4f0dfd65fc5
めっちゃ速いtakker.icon
外部のserverを経由しなくなった
/icons/すごーい.iconyosider.icon
サイトごとに個別の変換設定を作れるようにした
convertWholeText()の第2引数に渡す
e.g.
code:js
const 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
本体
code:script.js
import {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を明示しないとエラーが出ましたyosider.icon
/icons/GoogleChrome.iconです
それは変ですtakker.icon
テキストを挿入するUserScript#5ffaa5021280f00000af62a8では内部で生成したcursorを使っています
yosider.iconさんの使っているinsertTextの定義が古いのかもしれません
昔書いた/takker/scrapbox-insert-textは外部からcursorを挿入する形式だった
複数のURLを含んだテキストをまとめて変換する
code:convert.js
export 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 (!linksi) break;
map[urlsi]= linksi;
}
//console.log(map);
const result = text.replace(/https?:\/\/\S+/g, match => mapmatch ?? match);
//console.log(result);
return result;
}
URLを外部リンク記法に変換する
configに、サイトごとの設定を書く
code:convert.js
async 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の変換設定
code:convert.js
const 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)}];
}
Qiita.icon
#2021-02-26 00:15:43