generated at
いい感じにリンクするomakase-links
自動リンクを貼るUserScript
LGTMLGTMLGTM めちゃくちゃ便利です!!!
手動でリンクを外す仕組みもほしいですねtakker
別のUserScriptで作る
作った
もしくは、リンク入り文章を選ぶとリンクを外すメニューに切り替わるとか

APIの代わりにscrapbox.Project.pagesを使うバージョン
script.js
// based on https://scrapbox.io/daiiz/omakase-links // 既に記法になっているなどの理由で、置換すべきでない範囲を取得する const detectLocked = text => { const syntax = /\[(\/\w|[^\[!"#%&'()\*\+,\-\.\/\{\|\}<>_~])[^\[\]]*\]/g; const locked = text.split('').map(_ => false)

script.js
const matches = text.matchAll(syntax); for (const match of matches) { locked.fill(true, match.index, match.index + match[0].length); } return locked; }

script.js
const escapeRegExp = string =>string.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&'); const autoLink = text => { if (!text) return; // リンクを長い順に並べる const titles = scrapbox.Project.pages.map(p => p.title).sort((a, b) => b.length - a.length); 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 = new RegExp(escapeRegExp(title), 'gi'); const matches = text.matchAll(regexp); for (const match of matches) { const len = match[0].length; const idx = match.index; 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 })