generated at
scrapbox-url-customizer
Next version
hr
移動した
hr

選択範囲にあるURLを外部リンク記法にするUserScript
daiiz-paste-urlの代替script
install
warningurl-info-proxyを事前にinstallして下さい

2021-01-05
10:15:04 Wikiwandに対応した
2020-12-05
08:32:01 URL queryを保存するようにした
従来はURL queryを取り除いてしまっていたので、https://rashita.net/blog/?p=25427 などのページのタイトルを正しく取得できなかった
2020-12-03
19:29:51 GitHubのrepo URLの処理方法を変えた
2020-11-30
22:19:25 フラグメント識別子から取得した文字列から改行を除くようにした
2020-11-29
19:09:28 リンクにフラグメント識別子をつけ忘れてたのを直した
18:19:45 フラグメント識別子に部分的に対応した
指定された要素の textContent をしゅとくする
兄弟要素の中身は取得できないので、Qiitaのようなサイトでは識別子に対応する見出しの文字を取得できない

既知の問題点
ctrl+v版
画像URLも無理やりtitleを取得しようとしてしまう
フラグメント識別子があっても見出しを取得できないサイトがある
e.g. Qiita
utf-8でないhtmlだと文字化けする
daiiz-paste-urlでも同様の問題があった
一部取得できないURLがある

code

copy操作に介入するver.
URL以外のものが混じっていたら何もしない
scrapbox.ioの場合も何もしない
scrapbox-insert-textを使用した
script.js
import {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}); });

scrapbox-insert-textを使って書き込む
非同期関数を使うと、結果が返ってくるのを待つことなくpopup menuが終了してしまう
なので代わりに独自に入力処理を行うことにする
既知の問題
既に外部リンク記法が選択範囲内に混じっているとうまく行かない
コードブロック中のURLも問答無用で変換してしまう
popup.js
import {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) : ''; // #をとる
URL.hrefにはフラグメント識別子まで含めたURLが入っているので使えない
代わりにURL.originURL.pathnaemを使う
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から貼り付けるときに介入して変換させるかのどちらかの方法しか取れないな。
いや、scrapbox-insert-textを使えばいけるか?
2020-11-29 13:13:19 いけた
script_old1.js
scrapbox.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

#2021-02-26 00:29:48
#2021-01-05 10:15:40
#2020-12-08 10:43:11
#2020-12-03 19:30:18
#2020-11-30 22:20:04
#2020-11-29 11:30:18