Blogger に marked.js + mermaid.js + highlight.js を導入して Markdown ライクに記事を投稿できるようにする
## 動機
- Markdown 記法を用いることで、デバイスを選ばずにどこでも統一的な記事が作成しやすくなる
- フロチャートやシーケンス図も Markdown ライクに書きたい
- コードを綺麗に表示したい
## 構成要素
- [marked](https://github.com/chjj/marked)
Markdown 記法を使えるようにする
- [mermaid](https://github.com/knsv/mermaid)
チャートをテキストベースで作成できる
- [highlight.js](https://highlightjs.org/)
軽量なシンタックスハイライト
## 実装
記事の投稿は、次のように mdeditor で囲まれた部分に Markdown を記述すると mdpreview に変換されて表示される
```HTML
<div id="mdpreview">
変換表示用
</div>
<div id="mdeditor">
Markdown 編集用
</div>
```
テーマの HTML 編集で</body>タグの前に次のコードを追加する
```javascript
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'/>
<script src='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js'/>
<script src='https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.6/marked.min.js'/>
<script src='https://unpkg.com/mermaid@7.0.9/dist/mermaid.min.js'/>
<script>
//<![CDATA[
<!--
hljs.initHighlightingOnLoad();
var renderer = new marked.Renderer();
renderer.code = function (code, language) {
if(language == 'mermaid')
return '<div class="mermaid">'+code+'</div>';
else
return '<pre><code>'+code+'</code></pre>';
};
document.getElementById("mdpreview").innerHTML =
marked(document.getElementById("mdeditor").innerHTML, { renderer: renderer });
mermaid.initialize({startOnLoad:true});
$('#mdeditor').css({'display':'none'});
-->
//]]>
</script>
```
テーマの HTML 編集で<head>タグの間に次のコードを追加する
```HTML
<link href='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css' rel='stylesheet'/>
```
テーマ -> カスタマイズ -> 上級者向け -> CSS を追加 で mermaid 用の CSS を追加する
mermaid 用の CSS(mermaid.forest.css 等) はそのまま導入すると既存の要素に適用されてレイアウトが崩れるおそれがあるので mdeditor 要素内だけで適用されるようにする
```HTML
/* Flowchart variables */
/* Sequence Diagram variables */
/* Gantt chart variables */
#mdpreview .mermaid .label {
font-family: 'trebuchet ms', verdana, arial;
color: #333;
}
#mdpreview .node rect,
#mdpreview .node circle,
#mdpreview .node ellipse,
#mdpreview .node polygon {
fill: #cde498;
stroke: #13540c;
stroke-width: 1px;
}
#mdpreview .arrowheadPath {
fill: green;
}
#mdpreview .edgePath .path {
stroke: green;
stroke-width: 1.5px;
}
#mdpreview .edgeLabel {
background-color: #e8e8e8;
}
#mdpreview .cluster rect {
fill: #cdffb2 !important;
rx: 4 !important;
stroke: #6eaa49 !important;
stroke-width: 1px !important;
}
#mdpreview .cluster text {
fill: #333;
}
#mdpreview .actor {
stroke: #13540c;
fill: #cde498;
}
#mdpreview text.actor {
fill: black;
stroke: none;
}
#mdpreview .actor-line {
stroke: grey;
}
#mdpreview .messageLine0 {
stroke-width: 1.5;
stroke-dasharray: "2 2";
marker-end: "url(#arrowhead)";
stroke: #333;
}
#mdpreview .messageLine1 {
stroke-width: 1.5;
stroke-dasharray: "2 2";
stroke: #333;
}
#mdpreview #arrowhead {
fill: #333;
}
#mdpreview #crosshead path {
fill: #333 !important;
stroke: #333 !important;
}
#mdpreview .messageText {
fill: #333;
stroke: none;
}
#mdpreview .labelBox {
stroke: #326932;
fill: #cde498;
}
#mdpreview .labelText {
fill: black;
stroke: none;
}
#mdpreview .loopText {
fill: black;
stroke: none;
}
#mdpreview .loopLine {
stroke-width: 2;
stroke-dasharray: "2 2";
marker-end: "url(#arrowhead)";
stroke: #326932;
}
#mdpreview .note {
stroke: #6eaa49;
fill: #fff5ad;
}
#mdpreview .noteText {
fill: black;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
font-size: 14px;
}
/** Section styling */
#mdpreview .section {
stroke: none;
opacity: 0.2;
}
#mdpreview .section0 {
fill: #6eaa49;
}
#mdpreview .section2 {
fill: #6eaa49;
}
#mdpreview .section1,
#mdpreview .section3 {
fill: white;
opacity: 0.2;
}
#mdpreview .sectionTitle0 {
fill: #333;
}
#mdpreview .sectionTitle1 {
fill: #333;
}
#mdpreview .sectionTitle2 {
fill: #333;
}
#mdpreview .sectionTitle3 {
fill: #333;
}
#mdpreview .sectionTitle {
text-anchor: start;
font-size: 11px;
text-height: 14px;
}
/* Grid and axis */
#mdpreview .grid .tick {
stroke: lightgrey;
opacity: 0.3;
shape-rendering: crispEdges;
}
#mdpreview .grid path {
stroke-width: 0;
}
/* Today line */
#mdpreview .today {
fill: none;
stroke: red;
stroke-width: 2px;
}
/* Task styling */
/* Default task */
#mdpreview .task {
stroke-width: 2;
}
#mdpreview .taskText {
text-anchor: middle;
font-size: 11px;
}
#mdpreview .taskTextOutsideRight {
fill: black;
text-anchor: start;
font-size: 11px;
}
#mdpreview .taskTextOutsideLeft {
fill: black;
text-anchor: end;
font-size: 11px;
}
/* Specific task settings for the sections*/
#mdpreview .taskText0,
#mdpreview .taskText1,
#mdpreview .taskText2,
#mdpreview .taskText3 {
fill: white;
}
#mdpreview .task0,
#mdpreview .task1,
#mdpreview .task2,
#mdpreview .task3 {
fill: #487e3a;
stroke: #13540c;
}
#mdpreview .taskTextOutside0,
#mdpreview .taskTextOutside2 {
fill: black;
}
#mdpreview .taskTextOutside1,
#mdpreview .taskTextOutside3 {
fill: black;
}
/* Active task */
#mdpreview .active0,
#mdpreview .active1,
#mdpreview .active2,
#mdpreview .active3 {
fill: #cde498;
stroke: #13540c;
}
#mdpreview .activeText0,
#mdpreview .activeText1,
#mdpreview .activeText2,
#mdpreview .activeText3 {
fill: black !important;
}
/* Completed task */
#mdpreview .done0,
#mdpreview .done1,
#mdpreview .done2,
#mdpreview .done3 {
stroke: grey;
fill: lightgrey;
stroke-width: 2;
}
#mdpreview .doneText0,
#mdpreview .doneText1,
#mdpreview .doneText2,
#mdpreview .doneText3 {
fill: black !important;
}
/* Tasks on the critical line */
#mdpreview .crit0,
#mdpreview .crit1,
#mdpreview .crit2,
#mdpreview .crit3 {
stroke: #ff8888;
fill: red;
stroke-width: 2;
}
#mdpreview .activeCrit0,
#mdpreview .activeCrit1,
#mdpreview .activeCrit2,
#mdpreview .activeCrit3 {
stroke: #ff8888;
fill: #cde498;
stroke-width: 2;
}
#mdpreview .doneCrit0,
#mdpreview .doneCrit1,
#mdpreview .doneCrit2,
#mdpreview .doneCrit3 {
stroke: #ff8888;
fill: lightgrey;
stroke-width: 2;
cursor: pointer;
shape-rendering: crispEdges;
}
#mdpreview .doneCritText0,
#mdpreview .doneCritText1,
#mdpreview .doneCritText2,
#mdpreview .doneCritText3 {
fill: black !important;
}
#mdpreview .activeCritText0,
#mdpreview .activeCritText1,
#mdpreview .activeCritText2,
#mdpreview .activeCritText3 {
fill: black !important;
}
#mdpreview .titleText {
text-anchor: middle;
font-size: 18px;
fill: black;
}
#mdpreview g.classGroup text {
fill: #13540c;
stroke: none;
font-family: 'trebuchet ms', verdana, arial;
font-size: 10px;
}
#mdpreview g.classGroup rect {
fill: #cde498;
stroke: #13540c;
}
#mdpreview g.classGroup line {
stroke: #13540c;
stroke-width: 1;
}
#mdpreview svg .classLabel .box {
stroke: none;
stroke-width: 0;
fill: #cde498;
opacity: 0.5;
}
#mdpreview svg .classLabel .label {
fill: #13540c;
font-size: 10px;
}
#mdpreview .relation {
stroke: #13540c;
stroke-width: 1;
fill: none;
}
#mdpreview .composition {
fill: #13540c;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview #compositionStart {
fill: #13540c;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview #compositionEnd {
fill: #13540c;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview .aggregation {
fill: #cde498;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview #aggregationStart {
fill: #cde498;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview #aggregationEnd {
fill: #cde498;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview #dependencyStart {
fill: #13540c;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview #dependencyEnd {
fill: #13540c;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview #extensionStart {
fill: #13540c;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview #extensionEnd {
fill: #13540c;
stroke: #13540c;
stroke-width: 1;
}
#mdpreview .node text {
font-family: 'trebuchet ms', verdana, arial;
font-size: 14px;
}
#mdpreview div.mermaidTooltip {
position: absolute;
text-align: center;
max-width: 200px;
padding: 2px;
font-family: 'trebuchet ms', verdana, arial;
font-size: 12px;
background: #cdffb2;
border: 1px solid #6eaa49;
border-radius: 2px;
pointer-events: none;
z-index: 100;
}
```
## 使用例
### Markdown
```
# 見出し1
## 見出し2
* リスト
* リスト
* リスト
```
# 見出し1
## 見出し2
* リスト
* リスト
* リスト
### コード
~~~
```csharp
public void Hoge()
{
Console.WriteLine("hogehoge");
}
```
~~~
```csharp
public void Hoge()
{
Console.WriteLine("hogehoge");
}
```
### mermaid
~~~
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
~~~
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
コメント
コメントを投稿