Markhor_Engineは、Markdownで書かれた文章をHTMLに変換するJSプラグインです。
ほかのライブラリには依存せず、ブラウザでもNode.jsでも使えます。
IE 5.5以上、Chrome 1以上、Safari 1以上、Firefox 1以上で動作します。
<script type="text/javascript" src="https://ohiro.ndjp.net/js/markhor_engine.js"></script>を、
<head>か<body>のどこかしらに記述しておいてください。
バージョンを指定したURLでも配信しています。バージョンを固定して使いたいときは、こちらをお使いください。
https://ohiro.ndjp.net/js/markhor_engine/1.3.0/markhor_engine.js
(1.3.0の部分を、使いたいバージョンに変えてください。バージョンを指定しない上のURLは、常に最新版です。)
Node.jsで使うときは、ダウンロードしたファイルをrequireで読み込みます。
var Markhor = require('./markhor_engine.js');
Markhor.render(Markdownの文字列, 設定)を呼ぶと、変換後のHTML文字列が返ってきます。
設定は省略できます(詳しくは「設定」をご覧ください)。
nullやundefinedを渡したときは、空の文字列が返ります。
例
<textarea id="src"></textarea>
<div id="out"></div>
<script type="text/javascript">
document.getElementById('src').onkeyup = function () {
document.getElementById('out').innerHTML = Markhor.render(this.value);
};
</script>
下のテキストボックスに書くと、その下に変換結果が出ます。
| 種類 | 書き方 | 出力されるHTML |
|---|---|---|
| 見出し(Atx形式) | # 見出し(#は1〜6個。後ろに空白が必要。行末に空白を空けて#を書くと、取り除かれる) | <h1>〜<h6> |
| 見出し(Setext形式) | 文字の次の行に===(h1)、---(h2)(=も-も1個以上で成立。上にある複数行の段落が、まとめて見出しになる) | <h1>、<h2> |
| 太字 | **太字**、__太字__ | <b> |
| 斜体 | *斜体*、_斜体_(語の途中の_は斜体にならない。*は語の途中でも効く。) | <i> |
| 打ち消し線 | ~~打ち消し~~(~が2個のときだけ) | <del> |
| インラインコード | `code`(バッククォートで囲む。中にバッククォートを書くときは、囲む個数を増やす。中ではMarkdown記法は効かず、そのまま表示される。) | <code> |
| コードブロック | ```か~~~(3個以上)の行で囲む。開始行に言語名を書ける(閉じる行は、開始と同じ文字で、同じ個数以上)。または行頭を空白4個かタブで字下げ。 | <pre><code> |
| リンク | [文字](URL)、[文字](URL "title")('title'や(title)でもよい。title属性がつく)。URLに空白を含めるときは<URL>で囲む。URLの中の(と)は、対になっていれば書ける。 | <a> |
| 参照リンク | [文字][ID]と、別の行に[ID]: URLか[ID]: URL "title"(IDは大文字小文字を区別しない。[文字][]や[文字]とIDを省略すると、文字がIDになる。定義の行は、段落の途中ではなく、段落の先頭にあるものだけが有効)。 | <a> |
| 自動リンク | <https://...>(スキーム)、または<someone@example.com>(mailto:のリンクになる)。<>の中にはhttp系やftp以外のスキームも書けるが、「URLの検査」で許可されたものだけがリンクになる。<>がなくても、行頭、空白、* _ ~ (の後ろにある、http:// https:// ftp://で始まる文字列はリンクになる。 | <a> |
| 画像 | 、、![代替テキスト][ID] | <img> |
| 引用 | 行頭に> | <blockquote> |
| 箇条書き | 行頭に- * +と空白。項目の文字の位置まで字下げすると入れ子になる。 | <ul> |
| 番号つきリスト | 行頭に1.か1)と空白(数字は9桁まで)。最初の番号がstart属性になる。 | <ol> |
| タスクリスト | - [ ] 未完了、- [x] 完了 | 操作できないチェックボックス |
| 表 | |で区切る。1行目が見出し行(<th>)になる。見出し行のすぐ下に、区切りの行(---|---のように-だけのセル。見出し行とセルの数が同じであること)が必要で、無いと表にならず普通の文になる。区切りの行に:を書くと、列ごとに寄せを指定できる(:---左、:---:中央、---:右)。本体の行はセルが足りなければ空欄、多ければ切り捨て。空行や、他のブロック(見出しなど)で表は終わる。セルの中に|を書くときは\| | <table> |
| 水平線 | ---、***、___(3個以上。- - -のように空白を挟んでもよい。) | <hr> |
| エスケープ | \*のように、記号の前に\。対象はASCIIの記号すべて(! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~)。それ以外の文字の前の\は、そのまま表示される。コードの中では効かない。 | 記号そのもの |
| 文字参照 | © © ©のような文字参照は、文字に変換される(名前はHTML5のもの。未知の名前や、;のないものはそのまま表示される)。コードの中では効かない。\©と書くと、変換されない。リンクのURL・title・画像の代替テキストの中でも変換される。 | 文字そのもの |
| 行末の改行 | 行末に空白2個以上か\を書くと、その行で折り返す。コードの中や、段落の最後の行では効かない。 | <br> |
| HTMLタグ | <div>のようなタグは、HTMLとしては出力されず、文字としてそのまま表示される。 | <div> |
補足
・続けて書いた行は1つの<p>にまとまり、行の区切りは改行文字になります(画面上は空白と同じ)。引用の>のない続きの行も、同じ段落になります。
・リストの項目の間に空行があると、各項目が<p>で囲まれます。別のリストに分けたいときは、記号を変えるか(-の次は*など)、番号つきなら区切りの文字を変えて(.と))ください。
・リストの項目の中に、字下げした段落、コードブロック、引用、入れ子のリストを書けます。入れ子の<ul>や<ol>は、<li>の中に出力されます。
・表の寄せ指定は、<th>と<td>のalign属性になります。表のセルの中で使えるのはインライン記法(太字やリンクなど)だけです。
・リンクと画像は、URLの後ろに空白を空けて"title"と書くと、title属性がつきます。titleの中では、太字などの記法は変換されず、そのまま表示されます。titleが空のときは、つきません。
・画像のaltには、代替テキストから太字などの記号を除いた文字だけが入ります。
・リンクと画像のURLは、日本語や空白などが%E3...のようにパーセントエンコードされ、&は&になって出力されます(すでにある%XXはそのままです)。
・コードブロックの言語名は、開始行の最初の単語がそのまま使われます。コードブロックが閉じられていないときは、文章の最後(囲んでいる引用やリストの終わり)で閉じられます。
・コードブロックの言語名は、class="language-言語名"になるほか、ラベル用の<span>として出力されます。ラベルの見た目は、CSSで指定してください。表示する文字はcodeLangLabelで変えられます。
・引用とリストの入れ子は、合わせて255段までです。それより深いものは、文字として表示されます。極端に入り組んだ文章で処理が続けられないときは、全体が<pre>に入った文字として返ります。
出力されるクラス
| クラス | 付く場所 |
|---|---|
markhor-code-labeled | 言語名つきのコードブロックの<pre> |
markhor-code-label | 言語名のラベル(<span>) |
language-言語名 | 言語名つきのコードブロックの<code>(language-jsなど) |
markhor-task | タスクリストの<li> |
markhor-task-box | タスクリストのチェックボックス(<input>) |
第2引数に、次のような項目をもつオブジェクトを渡します。すべて省略できます。
var html = Markhor.render(text, {
linkTarget: '',
linkRel: 'noopener noreferrer',
allowImages: false
});
| 項目 | 初期値 | 説明 |
|---|---|---|
linkTarget | "_blank" | リンクのtargetです。空文字列にすると、targetをつけません。 |
linkRel | なし | リンクのrelです。_blankのままなら、"noopener noreferrer"をおすすめします。 |
allowImages | true | falseにすると画像を表示せず、代替テキストだけを出力します。 |
allowedSchemes | なし | リンクに追加で許可するスキームの配列です。例:['sms', 'line'](画像には効きません) |
urlFilter | なし | URLごとに許可するかどうかを決める関数です。「URLの検査」をご覧ください。 |
unsafeUrls | false | trueにすると、スキームの検査をやめます。自分で書いた文章だけを変換するときのみ使ってください。 |
codeLangLabel | なし(言語名を表示) | falseにすると、コードブロックのラベルを出力しません。function (lang)という関数を渡すと、その戻り値(文字列)がラベルになります。戻り値が空文字列のときも、ラベルは出ません。言語名のないコードブロックには、もともとラベルがつきません。 |
closeUnterminated | false | 1.3系のみ(1.4系以降は常にtrueで、指定しても効果がありません)。 閉じられていないコードブロックを、文章の最後で閉じます。 falseのままだと、</code></pre>がつかないままHTMLが終わります。 |
リンクと画像のURLは、変換のときに検査されます。許可されなかったリンクは文字だけ、画像は代替テキストだけになります。
http https ftp mailto tel…リンクで使えます
http https ftp、およびdata:image/のpng jpeg gif webp bmp…画像で使えます
スキームのない相対URL(/a/b、#topなど)…どちらでも使えます
javascript:など、上にないもの…使えません(:や空白を混ぜて隠したものも検出します)
urlFilterは、function (url, kind, ok)という形で書きます。
url…元のURLです(&なども書いたままの、エスケープ前のものです)。
kind…リンクなら"link"、画像なら"image"です。
ok…標準の検査で許可されたかどうか(trueかfalse)です。
戻り値によって、次のように動きます。
false…使わない
文字列…そのURLに置き換える(置き換えたURLには標準の検査が行われません)
true…使う(標準の検査で許可されなくても使うので、javascript:も通ってしまいます)
それ以外(undefinedなど)…標準の検査のとおりにする
例(画像は自分のサイトのものだけ許可する)
Markhor.render(text, {
urlFilter: function (url, kind, ok) {
if (kind === 'image' && url.indexOf('https://ohiro.ndjp.net/') !== 0) {
return false;
}
return ok;
}
});
Markhor.version…バージョンの文字列("1.3.0"など)です。
Markhor.escapeHtml(文字列)…& < > "をエスケープした文字列を返します。
Markhor.isSafeUrl(URL, 種類, 設定)…そのURLが許可されるかどうかをtrueかfalseで返します。種類は"link"か"image"で、設定にはrenderと同じものを渡せます。
1.3系では、CommonMarkの仕様とは違う動作がいくつかありました。
1.4系で、CommonMarkの仕様に合わせました。
文章の組み立て
| 項目 | 1.3系まで | 1.4系以降 |
|---|---|---|
| 段落 | 改行ごとに別々の<p>になる | 続けて書いた行は1つの段落になる(行末の空白2個か\で<br>) |
| Setext形式の見出し | すぐ上の1行だけが見出しになる | 上の複数行の段落が、まとめて見出しになる |
| 水平線 | ---のように、同じ文字を続けて書いたものだけ | - - -のように空白を挟んでもよい |
| リストの入れ子 | 字下げが深くなると入れ子になり、<ul>が<li>と<li>の間に出力された | 項目の文字の位置まで字下げすると入れ子になり、<li>の中に出力される |
| 番号つきリストの番号 | 無視され、常に1から数える | 最初の番号がstart属性になる |
| リストの間の空行 | 空行で別のリストに分かれる | 同じリストのまま、項目が<p>で囲まれる。分けたいときは記号を変える。 |
| リストの項目の中身 | 1行の文字だけ。続きの行は別の段落になりリストが終わる。 | 複数行、複数の段落、コードブロック、引用、入れ子のリストを書ける |
| 引用 | 1行ごとに<p>。中は段落だけで、見出し、リスト、入れ子の引用は使えない。 | 続く行は1つの段落。見出し、リスト、コードブロック、入れ子の引用も書ける。 |
| コードブロックの字下げ | 引用・リスト・表の中では使えない | 引用とリストの中でも使える |
| コードブロックを閉じる行 | 同じ文字が3個以上あれば閉じる | 開始と同じ文字で、同じ個数以上のときだけ閉じる |
| 閉じられていないコードブロック | closeUnterminatedがfalse(初期値)だと、</code></pre>が出力されない | 常に最後で閉じる(closeUnterminatedは効果なし) |
| コードブロックの言語名 | 英数字と_ + # . -の部分だけ。先頭がほかの文字なら言語名なし。 | 開始行の最初の単語がそのまま言語名になる |
| 表 | |を含む行は、ふつうの文やリストの中でも表の行になった。区切りの行は何行目でも読み飛ばされ、セルの数も揃えない。セルの中の\|でも区切られた | 見出し行のすぐ下に、セル数の合った区切りの行がないと表にならない。本体の行は列の数に揃えられる。\|はセルの中の|になる。 |
| 参照リンクの定義 | 1行で完結するものだけ。段落の途中にあっても有効。 | URLやtitleが次の行にあってもよい。段落の途中にあるものは無効。 |
文字の記法
| 項目 | 1.3系まで | 1.4系以降 |
|---|---|---|
| エスケープできる記号 | \ ` * _ { } [ ] ( ) # + - . !のみ。~ | < >などは対象外 | ASCIIの記号すべて。記号以外の前の\は、そのまま表示される。 |
| 文字参照 | ©は&copy;になり、そのまま「©」と表示される。 | 文字(©)に変換される |
| 太字・斜体の判定 | 単純な置き換え。snake_case_wordの_も斜体になる。 | 前後の文字で判定する。語の途中の_は斜体にならない。 |
| 打ち消し線 | 内側に~があると効かない。前後が空白の~~でも効く。 | 前後が空白の~~は効かない(*や_と同じ規則)。~が3個以上並んでいるものは効かない。 |
| 改行 | 行末の空白2個や\では折り返せない | 折り返せる |
| リンクのURL | )を含められない | 対になった()は書ける。空白を含めるときは<URL>で囲む。 |
| リンクのtitle | "..."か'...'だけで、中に)は書けない | (...)でもよい。中に)を書ける。 |
| 出力されるURL | 日本語などは書いたままの文字で出力される | %E6%97%A5のように、パーセントエンコードされる |
画像のalt | 代替テキストにコードを書くと、<code>などのタグがaltに入ることがある | 記号を除いた文字だけが入る |
<...>の自動リンク | http https ftpのみ。URLに&があると使えない。 | メールアドレスも使える。&も書ける。スキームは「URLの検査」で許可されたもののみ。 |
| 行の途中の自動リンク | 行頭と空白の後ろのみ。最後の. , ; : ! ?のうち1文字だけを除いた | * _ ~ (の後ろでもよい。最後の? ! . , : * _ ~ ' "、対になっていない)、&のような終わりは、いくつでも除かれる。 |
| 入力のU+0001〜U+0004 | 内部で使うため、取り除く。 | 取り除かない(U+0000だけがU+FFFDに変わる) |