scrapbox-url-customizer
Next version
移動した
install
2021-01-05
10:15:04 Wikiwandに対応した
2020-12-05
2020-12-03
19:29:51 GitHubのrepo URLの処理方法を変えた
2020-11-30
2020-11-29
指定された要素の textContent
をしゅとくする
兄弟要素の中身は取得できないので、Qiitaのようなサイトでは識別子に対応する見出しの文字を取得できない
既知の問題点
ctrl+v版
画像URLも無理やりtitleを取得しようとしてしまう
e.g. Qiita
utf-8でないhtmlだと文字化けする
一部取得できないURLがある
code
copy操作に介入するver.
URL以外のものが混じっていたら何もしない
scrapbox.ioの場合も何もしない
script.jsimport {convert} from '/api/code/takker/scrapbox-url-customizer/convert.js';
import {insertText} from '/api/code/takker/scrapbox-insert-text/script.js';
const cursor = document.getElementById('text-input');
cursor.addEventListener('paste', async (event) => {
const url = (event.clipboardData ?? window.clipboardData).getData('text');
if (!/^https?:\/\/\S+$/.test(url)) return;
if (/^https:\/\/scrapbox.io/.test(url)) return;
event.preventDefault();
const link = await convert(url);
insertText({text: link, cursor: cursor});
});
非同期関数を使うと、結果が返ってくるのを待つことなくpopup menuが終了してしまう
なので代わりに独自に入力処理を行うことにする
既知の問題
既に外部リンク記法が選択範囲内に混じっているとうまく行かない
コードブロック中のURLも問答無用で変換してしまう
popup.jsimport {convertWholeText} from '/api/code/takker/scrapbox-url-customizer/convert.js';
import {insertText} from '/api/code/takker/scrapbox-insert-text/script.js';
scrapbox.PopupMenu.addButton({
title: 'URL',
onClick: text => {
if (!/https?:\/\/\S+/.test(text)) return; // URLがなければ何もしない
const cursor = document.getElementById('text-input')
convertWholeText(text).then(text => insertText({text: text, cursor: cursor}));
// 入力しやすいよう選択範囲を先に消しておく
return '';
},
});
core
convert.js// 複数のURLを含んだテキストをまとめて変換する
export async function convertWholeText(text) {
const urls = text.match(/https?:\/\/\S+/g) ?? [];
if (urls.length === 0) return undefined;
const links = await Promise.all(urls.map(url => convert(url)));
let map = {};
for (const originalUrl of urls) {
const i = urls.indexOf(originalUrl);
if (!links[i]) break;
map[originalUrl]= links[i];
}
//console.log(map);
const result = text.replace(/https?:\/\/\S+/g, match => map[match] ?? match);
//console.log(result);
return result;
}
// urlを外部リンク記法に変換する
export async function convert(url) {
if (!window.getUrlInfo) {
alert('Please install "getUrlInfo from https://scrapbox.io/takker/url-info-proxy"');
return;
}
// hashを分離する
const urlObj = new URL(url);
console.log(urlObj);
let hash = urlObj.hash !== '' ? urlObj.hash.slice(1) : ''; // #をとる
convert.js let pureUrl = `${urlObj.origin}${urlObj.pathname}${urlObj.search}`;
特定のDomainに対して特別な処理をする
Github
convert.js if (urlObj.hostname === 'github.com'
&& /^\/[^\/]+\/[^\/]+\/?$/.test(urlObj.pathname)) {
return `[${pureUrl} ${urlObj.pathname.slice(1)}]`;
}
Wikipediaにredirectする
convert.js if (urlObj.hostname === 'www.wikiwand.com') {
pureUrl = pureUrl.replace(/www\.wikiwand\.com\/(\w+)\//,'$1.wikipedia.org/wiki/');
// 先頭の/を取り除く
hash = hash !== '' ? hash.slice(1) : hash;
}
convert.js console.log(`url = ${pureUrl}, hash = ${hash}`);
const params = hash !== '' ? `url=${pureUrl}&hash=${hash}` : `url=${pureUrl}`;
console.log(`start fetching https://url-info.vercel.app/api/page?${params}...`);
const urlInfo = await window.getUrlInfo(`https://url-info.vercel.app/api/page?${params}`)
.then(req => req.response);
if(!urlInfo.title) return undefined;
const result = {
href: urlInfo.url + (!urlInfo?.fragment?.hash ? '' : urlInfo?.fragment?.hash),
title: (!urlInfo?.fragment?.content ? '' : `${urlInfo.fragment.content.replace(/\n/g,'').trim()} | `) + urlInfo.title,
};
return `[${result.href} ${result.title}]`;
}
没コード
選択範囲内の最初のURLだけ変換してclipboardに貼り付けるか、clipboardから貼り付けるときに介入して変換させるかのどちらかの方法しか取れないな。
2020-11-29 13:13:19 いけた
script_old1.jsscrapbox.PopupMenu.addButton({
title: 'URL',
onClick: async text => {
if (!window.getUrlInfo) {
alert('Please install "getUrlInfo from https://scrapbox.io/takker/url-info-proxy"');
return;
}
const urls = text.match(/https?:\/\/\S+/g) ?? [];
if (urls.length === 0) return;
const urlInfos = await Promise.all(urls.map(url =>
window.getUrlInfo(`https://url-info.vercel.app/api/page?url=${url}`)
.then(req => req.response)));
let map = {};
for (const originalUrl of urls) {
const i = urls.indexOf(originalUrl);
const {url, title} = urlInfos[i];
if (!title) break;
map[originalUrl]= urlInfos[i];
}
console.log(map);
const result = text.replace(/https?:\/\/\S+/g, match => map[match] ?
`[${map[match].url} ${map[match].title}]` : match);
console.log(result);
return result;
},
});
参考にしたcode
> MIT License Copyright (c) 2020 ci7lus