Cosense(Scrapbox)で文字装飾のネストを解消する
ChatGPTが一秒でやってくれました。
code:script.js
scrapbox.PopupMenu.addButton({
title: 'Resolve nested styles',
onClick: text => {
function resolveNestedBlocks(text) {
const pattern = /\[(*_/\-+) ([^\\]*?(?:\^\[\+?\][^\\]*?)*?)\]/g;
function processBlock(marker, content) {
// まず、content中にさらに装飾が含まれているか判定
if (!content.match(pattern)) {
return [${marker} ${content}]; // ネストがなければそのまま返す
}
let result = '';
let i = 0;
let buffer = '';
let depth = 0;
while (i < content.length) {
if (contenti === '&& content.slice(i).match(/^\[([*_/\-+) /)) {
if (depth === 0 && buffer.trim()) {
result += [${marker} ${buffer}];
buffer = '';
}
buffer += contenti;
depth++;
} else if (contenti === ']') {
buffer += ']';
depth--;
if (depth === 0) {
// 再帰的に処理してからマーカーを合わせてラップ
const inner = buffer.match(/^\[(*_/\-+) (.*)\]$/s);
if (inner) {
const innerMarker = inner1;
const innerContent = inner2;
result += resolveNestedBlocks([${marker}${innerMarker} ${innerContent}]);
} else {
result += [${marker} ${buffer}]; // フォールバック(万一)
}
buffer = '';
}
} else {
buffer += contenti;
}
i++;
}
if (buffer.trim()) {
result += [${marker} ${buffer}];
}
return result;
}
let newText = text;
let prev;
do {
prev = newText;
newText = newText.replace(pattern, (match, marker, content) => processBlock(marker, content));
} while (newText !== prev);
return newText;
}
return resolveNestedBlocks(text);
}
});
[* test [/ test] test]が[* test ][*/ test][* test]になる
そもそもこれが必要になるような、文字装飾が重なるような書き方はCosenseでは避けるべきである。
のだけれど、たとえば斜体を含む引用文の一部分を強調したい時などにこういうのがやはり欲しくはなる。