generated at
unlink Popup menu

動機
文中リンクを手動で外すのが面倒
特に自動でリンクを貼った場合に使いたい
余計なところにリンクが貼られたりするので

実装
正規表現でリンクを検出すればいい
PopupMenuに加える

考察
別の機能と一緒に開発したほうがいいかも
リンクがないときは自動リンクに、リンクを含むときはリンク解除に機能を切り替える
……リンクを追加したい場合にネックになるかな。
リンクを避けて選択しないといけない
別の機能として実装したほうが良さそう?


2023-10-04 07:25:16 TSに移行
bundle不要の旧版は/customize/リンクを外すUserScriptを参照
リンク検知処理を複数のリンクをまとめて置換するUserScriptから流用する
リンクを外す処理を変える
正規表現をやめ、scrapbox-parserで構文解析してリンクを外す
hashtagも外すようにした
リンクがあるときだけボタンを表示する
2022-05-24 09:12:44 [(aaa] のように、記号の後にスペースがこないものはリンク扱いする
2022-04-26 10:26:40 数式記法を誤認識していた
2020-09-02 13:46:54 とりあえず作ってみた

$ deno check --remote -r=https://scrapbox.io https://scrapbox.io/api/code/takker/unlink_Popup_menu/script.ts
script.ts
import { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts"; import { getLinks } from "../複数のリンクをまとめて置換するUserScript/mod.ts"; import { convert } from "./mod.ts"; declare const scrapbox: Scrapbox; scrapbox.PopupMenu.addButton({ title: (text) => getLinks(text).length > 0 ? "\uf127" : "", onClick: (text) => { const result = convert(text); // テロメアが無駄に更新されるのを防ぐ if(text == result) return; return result; } });

mod.ts
import { CodeBlock, Line, Node, parse, Table, } from "../scrapbox-parser/mod.ts"; export const convert = (text: string): string => { const blocks = parse(text, { hasTitle: false }); return blocks.flatMap((block) => { switch (block.type) { case "title": return []; case "codeBlock": return convertCodeBlock(block); case "table": return convertTable(block); case "line": return convertLine(block); } }) .map((line) => line).join("\n"); }; /** コードブロックはそのまま復元する */ const convertCodeBlock = ( { fileName, content, indent }: CodeBlock, ) => { const tag = " ".repeat(indent); return [ `${tag}code:${fileName}`, ...content.split("\n").map((line) => `${tag} ${line}`), ]; }; /** テーブル中のリンクを外す */ const convertTable = ({ fileName, cells, indent }: Table) => { const tag = " ".repeat(indent); return [ `${tag}table:${fileName}`, ...cells.map((cell) => `${tag} ${ cell.map((nodes) => nodes.map((node) => convertNode(node)).join("")).join("\t") }` ), ]; }; /** 行内リンクを外す */ const convertLine = ({ nodes, indent }: Line) => [ `${" ".repeat(indent)}${ nodes.map((node) => `${convertNode(node)}`).join( "", ) }`, ]; /** リンクを外したnodeを作る */ const convertNode = (node: Node): string => { switch (node.type) { case "quote": return `> ${node.nodes.map((node) => convertNode(node)).join("")}`; case "strong": return `[[${node.nodes.map((node) => convertNode(node)).join("")}]]`; case "decoration": { const deco = node.decos.map((deco) => { const num = parseInt(deco.match(/\*-(\d)/)?.[1] ?? "0"); return num > 0 ? "*".repeat(num) : deco; }).join(""); return `[${deco ? `${deco} ` : ""}${ node.nodes.map((node) => convertNode(node)).join("") }]`; } case "hashTag": return node.href; // linterのバグで、何故か警告が出る // deno-lint-ignore no-fallthrough case "link": return node.pathType === "absolute" ? node.raw : node.href; default: return node.raw; } };

#2023-10-04 07:41:50
#2022-05-24 09:11:03
#2022-04-26 10:27:00
#2022-03-08 09:49:44
#2020-09-02 13:34:04
#2020-11-07 22:16:00
#2020-09-01 01:00:26