MarkdownをCosense記法に置換するUserScript
Cosense(旧称Scrapbox)で使用するUserScriptです。
更新履歴
2024-06-22:イタリックを置換する行をコメントアウト(置換対象のURLにアンダーバーを含む場合に干渉するのを防ぐため)
2019-12-17:Markdownのエスケープを元に戻す機能を追加
2019-12-15:番号付きリストの置換機能を追加
2019-12-12:リストの置換機能を追加
2019-12-10:公開
置換できるもの
ここに挙げているものだけを置換できます。
強調を太字へ置換
**hoge**
→ [* hoge]
__hoge__
→ [* hoge]
取り消し線
~~hoge~~
→ [- hoge]
見出し(レベル1〜6)を、それぞれに対応する大きな字へ置換
# hoge
→ [******* hoge]
## hoge
→ [****** hoge]
### hoge
→ [***** hoge]
#### hoge
→ [**** hoge]
##### hoge
→ [*** hoge]
###### hoge
→ [** hoge]
外部リンク
[Google](https://www.google.com)
→ [Google https://www.google.com]
[](https://www.google.com)
→ [https://www.google.com]
<https://www.google.com>
→ [https://www.google.com]
画像

→ [Scrapbox logo https://scrapbox.io/assets/img/logo.png]

→ [https://scrapbox.io/assets/img/logo.png]
リスト(番号なしリスト)
半角の
*
,
+
,
-
のいずれかで始まっている行(Markdownのリスト)を
箇条書きに置換します。
番号付きリスト
1. hoge
のように〈半角数字+ドット+半角スペース1個〉で始まっている行(Markdownの数字付きリスト)は
数字付きリストに置換します。
置換前のときに、番号( 1.
など)が行頭にある場合のみに対応しています。
半角のアスタリスク( *
)、ハイフン( -
)、アンダーバー( _
)のいずれかが、行頭から3個以上連続している箇所(Markdownの水平線)は、水平線の画像に置き換えます。
記号のエスケープを元に戻す
Markdownでは \*_{}[]()#+-.!
という14種類の記号やバッククォートを記入する際は、バックスラッシュを付けて \+
などのように書きますが、これをバックスラッシュが付かない形に戻します。
なお、Markdownにおける引用(行頭に >
)とインラインコード(文字をバッククォートで囲む)は、Cosense記法においてもそれらと同じ書き方をするので、Cosenseで元通り再現されます。
導入の仕方
下記のコードを、Cosenseの「
自分のページ」に貼り付けてからブラウザをリロードし、ページ上部に表示される"Load new UserScript"をクリックします。それで完了です。
コード
script.js scrapbox.PopupMenu.addButton({
title: 'MdSc', //"MdSc" is the name of popup button.
onClick: text =>{
////リスト////
//リストのマーカーが行頭にある場合
text=text.split(/\n/).map(line => line.replace(/^[\*\-\+] /g,' ')).join('\n')
//行頭以外にあるリストのマーカー(*, -, +)を消す
text=text.split(/\n/).map(line => line.replace(/[\*\-\+] /g,'')).join('\n')
//リストのインデントが半角スペース2個ずつの場合
//text=text.split(/\n/).map(line => line.replace(/ {2}/g,' ')).join('\n')
//リストのインデントが半角スペース4個ずつの場合
text=text.split(/\n/).map(line => line.replace(/ {4}/g,' ')).join('\n')
////数字付きリスト
text=text.split(/\n/).map(line => line.replace(/^([0-9]+\. )/g,' $1')).join('\n')
////強調////
//太字
text=text.split(/\n/).map(line => line.replace(/\*{2}([^*]+)\*{2}/g,'[* $1]')).join('\n')
text=text.split(/\n/).map(line => line.replace(/\_{2}([^_]+)\_{2}/g,'[* $1]')).join('\n')
//イタリック(URLにアンダーバーを含むハイパーリンクの置換を妨害するのでコメントアウト)
//text=text.split(/\n/).map(line => line.replace(/\_([^_]+)\_/g,'[/ $1]')).join('\n')
////取り消し線////
text=text.split(/\n/).map(line => line.replace(/\~\~(\~+|[^~]+)\~\~/g,'[- $1]')).join('\n')
////Header level 1-6////
//Header level 1
text=text.split(/\n/).map(line => line.replace(/^# (.*)/g,'[******* $1]')).join('\n')
//Header level 2
text=text.split(/\n/).map(line => line.replace(/^#{2} (.*)/g,'[****** $1]')).join('\n')
//Header level 3
text=text.split(/\n/).map(line => line.replace(/^#{3} (.*)/g,'[***** $1]')).join('\n')
//Header level 4
text=text.split(/\n/).map(line => line.replace(/^#{4} (.*)/g,'[**** $1]')).join('\n')
//Header level 5
text=text.split(/\n/).map(line => line.replace(/^#{5} (.*)/g,'[*** $1]')).join('\n')
//Header level 6
text=text.split(/\n/).map(line => line.replace(/^#{6} (.*)/g,'[** $1]')).join('\n')
////リンクと画像////
//Hyperlink without linktext / Image without alt text
//e.g. [](https://www.google.com) or 
text=text.split(/\n/).map(line => line.replace(/!?\[\]\((https?:\/\/[\w/:%#\$&\?\(\)~\.=\+\-]+)\)/g,'[$1]')).join('\n')
//Image with alt text
//e.g. 
text=text.split(/\n/).map(line => line.replace(/!\[([^\]]+)\]\((https?:\/\/[\w/:%#\$&\?\(\)~\.=\+\-]+)\)/g,'[$1 $2]')).join('\n')
//Hyperlink with linktext
//e.g. [Google](https://www.google.com)
text=text.split(/\n/).map(line => line.replace(/\[([^\]]+)\]\((https?:\/\/[\w/:%#\$&\?\(\)~\.=\+\-]+)\)/g,'[$1 $2]')).join('\n')
//URL with angle brackets
//e.g <https://www.google.com>
text=text.split(/\n/).map(line => line.replace(/<(https?:\/\/[\w/:%#\$&\?\(\)~\.=\+\-]+)>/g,'[$1]')).join('\n')
////水平線////
text=text.split(/\n/).map(line => line.replace(/^([\*|\-|\_]){3,}/g,'[/icons/hr.icon]')).join('\n')
////エスケープを元に戻す////
text=text.split(/\n/).map(line => line.replace(/\\([\\|`|\*|_|\{|\}|\[|\]|\(|\)|#|\+|\-|\.|\!])/g,'$1')).join('\n')
return text;
}
})
使い方
Markdownで書かれたテキストをCosenseのページに貼り付けて、その部分をマウスなどで選択し、そこにポップアップするボタンの中にある"MdSc"をクリックすると置換されます。
(置換前:太字/イタリック/取り消し線/見出し)
(置換後)
(置換前:外部リンク/画像/水平線)
(置換後)
使用時の注意点
想定外の置換が起こる例
置換対象の範囲に、Markdownのリストのインデント(階層下げ)以外の用途で、半角スペースが4個以上もしくは2個以上連続している箇所があると、Cosense記法への置換後には、その半角スペースの個数は改変されます。デフォルトでは、4個以上の連続で置換対象になります。
例: hoge fuga
など
「半角スペース4個以上もしくは2個以上の連続」は、Markdownのリストのインデント部分と同一なので、置換対象に該当してしまうためです。
置換対象の範囲に、Markdownにおけるコードブロック記法(行頭からタブ1個または半角スペース4個)があると、その箇所は、Cosense記法への置換後には「箇条書き」の状態へ置換されてしまいます。
「タブ1個または半角スペース4個」はリストのインデントとして置換対象に該当するためです。
置換対象の範囲に、Cosense記法の太字( [* hoge]
)や取り消し線( [- hoge]
)が既に含まれている場合は、その箇所に対してこのUserScriptを適用すると、Cosense記法が壊されます。 *
と -
の部分が「Markdownのリストのマーカー」と同一なので、置換対象に該当してしまうためです。それらを置換対象の範囲に含めないように注意してください。
リストのマーカー( *
, +
, -
のいずれか)の直後に半角スペースがある場合は、それを箇条書きに置換した際に、階層が正しく再現されません。
再現されない例: * hoge
( *
の直後に半角スペースがある)
正しく再現される例: * hoge
Markdownが入れ子になっている場合は、正しい置換結果にならないと思います。
例: ~~**hoge**~~
など
コードの編集
番号なしリストのインデントが〈半角スペース2個ずつ〉で行われている場合
置換前のMarkdownにおいて、番号なしリストの階層をインデントする(1段下げる)ごとに〈半角スペース2個ずつ〉が使われている場合は、上掲のコードの中の、下記の部分の2行目の行頭にある //
を取り除き、かつ4行目の行頭に //
を書き加えます。
編集前の状態//リストのインデントが半角スペース2個ずつの場合
//text=text.split(/\n/).map(line => line.replace(/ {2}/g,' ')).join('\n')
//リストのインデントが半角スペース4個ずつの場合
text=text.split(/\n/).map(line => line.replace(/ {4}/g,' ')).join('\n')
そのように編集したら、ブラウザをリロードし、ページ上部に表示される"Load new UserScript"をマウスでクリックします。
関連記事
MarkdownをCosense記法に置換する機能をもつツールは他にもあります。