omakase-links
選択範囲にある
文章に含まれる、すでに
ページとして存在するタイトルを自動でリンク付けする機能
英文にも対応させた
ing, ed, es, sなどの変化形に対して対応
reなどのリンクが英単語に部分的に引っかからないようにした
script.jsfunction isEnglish(text) {
return !text.split('').some(char => char.charCodeAt() > 255);
}
script.js
// based on https://scrapbox.io/daiiz/omakase-links
// 既に記法になっているなどの理由で、置換すべきでない範囲を取得する
const detectLocked = text => {
const syntax = /\[(\/\w|[^\[!"#%&'()\*\+,\-\.\/\{\|\}<>_~])[^\[\]]*\]/g;
const locked = text.split('').map(_ => false)
const matches = text.matchAll(syntax);
for (const match of matches) {
locked.fill(true, match.index, match.index + match[0].length);
}
return locked;
}
const escapeRegExp = string => string.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&');
const autoLink = text => {
if (!text) return;
const excluded_list = [
"できる",
"re", "RE",
"機能", "存在", ""
];
// リンクを長い順に並べる
const titles = scrapbox.Project.pages
.map(p => p.title)
.sort((a, b) => b.length - a.length)
.filter(e =>
e != scrapbox.Page.title
&& !excluded_list.includes(e)
&& e.length > 1
)
const is_english = isEnglish(text);
const locked = detectLocked(text)
const matched = text.split('').map(_ => null)
const allNull = arr => arr.every(x => x === null);
for (const title of titles) {
const regexp_text = is_english ?
`${escapeRegExp(title)}(ed|ing|s|es)?[/-;,. )]` :
escapeRegExp(title);
if (["but", "and"].includes(title.toLowerCase())) { continue; }
const regexp = new RegExp(regexp_text , 'gi');
const matches = text.matchAll(regexp);
for (const match of matches) {
let len = title.length;
let idx = match.index;
if (is_english && !( idx == 0 || /[\s\n(]/.test(text[idx - 1])) ) { continue; }
if (allNull(matched.slice(idx, idx + len)) && !locked[idx]) {
for (let i = 0; i < len; i++) {
let c = text[idx + i];
if (i === 0) c = `[${c}`;
if (i === len - 1) c = `${c}]`;
matched[idx + i] = c;
}
}
}
}
// 無駄にテロメアがupdateされるのを防ぐ為、何も置換しない時は何も返さない
if (allNull(matched)) return
// 配列matchedでnullの位置を、元のtextの文字に置き換える
return matched.map((c, idx) => c ?? text[idx]).join('')
}
scrapbox.PopupMenu.addButton({
title: '[✨]',
onClick: autoLink
})
script.js// リンクを外す
scrapbox.PopupMenu.addButton({
title: 'unlink',
onClick: text => {
const result = text.split(/\n/)
.map(line => line.replace(/\[([^\[!"#%&'()\*\+,\-\.\/\{\|\}<>_~][^\[\]]*)\]/g,'$1')).join('\n');
// テロメアが無駄に更新されるのを防ぐ
if(text == result) return;
return result;
}
});
今自分が操作している
ページの
タイトルと、一文字タイトルを
置換候補に含めないようにするなどした。

大文字小文字が一致している場合にのみマッチさせるようにする
reassembleで

が引っかかって困る
あかんわこれ マッチする単語が少なくなってしまう
文頭の"Short"がshortにひっかからなくなる
英語 = 空白になっているところだけを見る?
追加