generated at
問合せ対応中のトグルボタンUserScript


#問合せ対応中 というリンクを #問合せ対応完了 に置き換える


動作確認用テキスト
確認したら、 ctrl(command) + z でundoしてくださいshokai
インデントされた文字装飾記法の中のhashtag
1つのページに#問合せ対応中 #問合せ対応完了 の両方がついてるのはまずいので、どちらかに寄せる



以下、UserScriptと解説ですshokai

グローバル汚染しないようにスコープを作る
script.js
(() => {

Page menuにボタン追加
script.js
cosense.PageMenu.addMenu({ title: '問合せ対応中・対応完了', icon: 'fas fa-question', onClick: updateContactState });

Page menuに追加したボタンを押したら呼び出される関数
script.js
async function updateContactState () { if (updateAllLinksInPage({ from: '問合せ対応中', to: '問合せ対応完了' })) return; if (updateAllLinksInPage({ from: '問合せ対応完了', to: '問合せ対応中' })) return; alert('このページは #問合せ対応中 でも #問合せ対応完了 でもありません'); }
置換対象がなかった場合、 #問合せ対応完了 #問合せ対応中 に置換する
それもなかった場合、どちらでもないページだ、と表示する

ページ内の全てのリンク記法とハッシュタグを置換する関数
返り値
1つでも置換したらtrue、置換しなければfalseを返す
script.js
function updateAllLinksInPage({ from, to }) { let updated = false; for (const [index, line] of cosense.Page.lines.entries()) { if (!line.nodes) continue; const result = updateLink({ node: line.nodes, from, to }); if (result !== line.text) { cosense.Page.updateLine(result, index); updated = true; } } return updated; }
これはオペレーターが編集したら自動的にレビュー待ちタグを付けるUserScriptとまったく同じなので、共通化しても良いかもしれないshokai

1行を処理する関数
script.js
function updateLink({ node, from, to }) { const args = { from, to }; if (typeof node === 'string') return node; if (Array.isArray(node)) return node.map(i => updateLink({ node: i, ...args })).join(''); switch (node.type) { case 'link': case 'hashTag': { if (!node.unit.project && node.unit.page === from) { node.unit.page = to; } return node.unit.whole; } case 'indent': case 'quote': { return node.unit.tag + updateLink({ node: node.children, ...args }); } case 'deco': { return '[' + node.unit.deco + ' ' + updateLink({ node: node.children, ...args }) + ']'; } case 'strong': { return '[[' + updateLink({ node: node.children, ...args }) + ']]'; } } return node.unit.whole; }
node treeを再帰でたどる
リンク記法もしくはhashTagを対象に
fromをtoに置換する
node treeを文字列に戻して返す

グローバル汚染しないように作ったスコープを閉じる