script.jsscrapbox.PopupMenu.addButton({
title: '-md',
onClick: text => {
const transformations = [
removeListMarkers,
removeStrongFormatting,
removeHeadingFormatting,
convertInlineTex,
convertBlockTex,
convertCodeBlocks,
removeBackticks,
];
return transformations.reduce((acc, t) => t(acc), text);
},
});
// 行頭のリストマーカー(*, -, +)を消す
function removeListMarkers(text) {
return text
.split(/\n/)
.map(l => l.replace(/^(\s*)[\*\-\+] /, '$1'))
.join('\n');
}
// strong(**, __)を外す
function removeStrongFormatting(text) {
return text
.split(/\n/)
.map(l => l.replace(/\*{2}([^*]+)\*{2}/g, '$1'))
.map(l => l.replace(/\_{2}([^_]+)\_{2}/g, '$1'))
.join('\n');
}
// 見出し(heading)を削除する
function removeHeadingFormatting(text) {
return text
.split(/\n/)
.map(l => l.replace(/(#{1,6}) (.*)/g, '$2'))
.join('\n');
}
// tex記法の\( ... \)を[$ ...]に書き換える
function convertInlineTex(text) {
return text
.split(/\n/)
.map(l => l.replace(/\\\((.*?)\\\)/g, '[$ $1 ]'))
.join('\n');
}
// 複数行のtex記法の書き換え
function convertBlockTex(text) {
return text
.split(/\n/)
.map(l => l.replace(/^\s*\\\[$/, match => match.replace('\\[', '[$')))
.map(l => l.replace(/^\s*\\\]$/, match => match.replace('\\]', ' ] ')))
.join('\n');
}
// ```hoge を code:hoge に変換
function convertCodeBlocks(text) {
return text
.split(/\n/)
.map(l => l.replace(/```(\S+)/g, 'code:$1'))
.join('\n');
}
// ``` を削除
function removeBackticks(text) {
return text
.split(/\n/)
.map(l => l.replace(/```$/, ''))
.join('\n');
}