Markedカスタマイズ:テーブルの1列目をヘッダーにする
概要
Markedを使ってマークダウンでテーブルの1列目をthタグにするために、独自構文+renderメソッドで関数定義することで対応した。
Markedとは
マークダウン構文で書いたテキストをhtmlに変換するjavascriptライブラリ。
簡単な使い方
- マークダウンを記述(タグにid属性を書いておく)
- jsを読み込む
- maked関数でid指定して、htmlに変換して表示する
<div id="markdownText">
| | A | B | C | D | E | F | G | H |
|---|---|---|---|---|---|---|---|----|
| A | H | F | E | C | D | G | B | A! |
| B | - | H | D | A | C | D | E | B! |
| C | - | - | H | F | G | B | A | C! |
| D | - | - | - | H | B | E | G | D! |
| E | - | - | - | - | H | A | F | E! |
| F | - | - | - | - | - | H | C | F! |
| G | - | - | - | - | - | - | H | G! |
| H | - | - | - | - | - | - | - | - |
</div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
document.getElementById("markdownText").innerHTML = marked(document.getElementById("markdownText").innerHTML.trim());
</script>
実行すると、以下のような表示になる。
A | B | C | D | E | F | G | H | |
---|---|---|---|---|---|---|---|---|
A | H | F | E | C | D | G | B | A! |
B | - | H | D | A | C | D | E | B! |
C | - | - | H | F | G | B | A | C! |
D | - | - | - | H | B | E | G | D! |
E | - | - | - | - | H | A | F | E! |
F | - | - | - | - | - | H | C | F! |
G | - | - | - | - | - | - | H | G! |
H | - | - | - | - | - | - | - | - |
htmlは以下のようなソースになっている。
<div id="markdownText"><table>
<thead>
<tr>
<th></th>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
<th>E</th>
<th>F</th>
<th>G</th>
<th>H</th>
</tr>
</thead>
<tbody><tr>
<td>A</td>
<td>H</td>
<td>F</td>
<td>E</td>
<td>C</td>
<td>D</td>
<td>G</td>
<td>B</td>
<td>A!</td>
</tr>
(中略)
</tbody></table>
</div>
1列目をthタグにしたい
マークダウンで1列目をthタグにするような構文は定義されていない?ので、Markedのrendererメソッドで拡張した。
1: 独自構文の定義
Markedのrendererメソッドでは "n列目" という情報を取得できなかったので、
まずは独自の構文を定義した。
以下のように、先頭に「:」をつけたものをthタグでレンダリングする事とする。
| | A | B | C | D | E | F | G | H |
|---|---|---|---|---|---|---|---|----|
| :A | H | F | E | C | D | G | B | A! |
| :B | - | H | D | A | C | D | E | B! |
| :C | - | - | H | F | G | B | A | C! |
| :D | - | - | - | H | B | E | G | D! |
| :E | - | - | - | - | H | A | F | E! |
| :F | - | - | - | - | - | H | C | F! |
| :G | - | - | - | - | - | - | H | G! |
| :H | - | - | - | - | - | - | - | - |
2: Markedのrendererメソッドで拡張
詳しくはドキュメントを参照するとして、renderer.tablecellでテーブルセルの生成をカスタマイズ可能。 marked.js.org
あとはrenderer.tablecellメソッドで、
tbodyのセルのときだけテキストの先頭1文字目が「:」の場合は、thタグで生成するように書く。
var renderer = new marked.Renderer();
// tableタグ
renderer.tablecell = function(content, flags) {
//thead
if (flags.header) {
return '<th>' + content + '</th>';
}
//tbody
if (content.substring(0, 1) === ':') {
return '<th>' + content.substring(1) + '</th>';
}
return '<td>' + content + '</td>';
};
marked.setOptions({
renderer: renderer,
});
document.getElementById("markdownText").innerHTML = marked(document.getElementById("markdownText").innerHTML.trim());
これを実行すると以下のような表示になる。
A | B | C | D | E | F | G | H | |
---|---|---|---|---|---|---|---|---|
A | H | F | E | C | D | G | B | A! |
B | - | H | D | A | C | D | E | B! |
C | - | - | H | F | G | B | A | C! |
D | - | - | - | H | B | E | G | D! |
E | - | - | - | - | H | A | F | E! |
F | - | - | - | - | - | H | C | F! |
G | - | - | - | - | - | - | H | G! |
H | - | - | - | - | - | - | - | - |
生成するhtmlは以下のようになっており、1列目がthタグになっている。
<div id="markdownText"><table>
<thead>
<tr>
<th></th>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
<th>E</th>
<th>F</th>
<th>G</th>
<th>H</th>
</tr>
</thead>
<tbody><tr>
<th>A</th>
<th>H</th>
<th>F</th>
<th>E</th>
<th>C</th>
<th>D</th>
<th>G</th>
<th>B</th>
<th>A!</th>
</tr>
(中略)
</tbody></table>
</div>
※html/js全文
<div id="markdownText">
| | A | B | C | D | E | F | G | H |
|---|---|---|---|---|---|---|---|----|
| :A | H | F | E | C | D | G | B | A! |
| :B | - | H | D | A | C | D | E | B! |
| :C | - | - | H | F | G | B | A | C! |
| :D | - | - | - | H | B | E | G | D! |
| :E | - | - | - | - | H | A | F | E! |
| :F | - | - | - | - | - | H | C | F! |
| :G | - | - | - | - | - | - | H | G! |
| :H | - | - | - | - | - | - | - | - |
</div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
var renderer = new marked.Renderer();
// tableタグ
renderer.tablecell = function(content, flags) {
//thead
if (flags.header) {
return '<th>' + content + '</th>';
}
//tbody
if (content.substring(0, 1) === ':') {
return '<th>' + content.substring(1) + '</th>';
}
return '<td>' + content + '</td>';
};
marked.setOptions({
renderer: renderer,
});
document.getElementById("markdownText").innerHTML = marked(document.getElementById("markdownText").innerHTML.trim());
</script>