Markdown
で!
卒論!
を、書くぞ!!!
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
この記事はOthlotechアドベントカレンダー23日目の記事です。
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
こんにちは😳💗
僕、すぱいす!🍲😉
来年からは東京🗼🥂でエンジニア🎓💻として働くの!
とっても🌠😏楽しみなんだ!😎😎
はぁ~😪、早く来年🐗にならないかなぁ🙋💕
あれれ、何かを忘れてる😫気がする…🙄
アッ、ソツロン、ヤラナキャ
背景
「普段から親しんでいるMarkdownで、卒論も書けないだろうか?」
そう思ったのが、全ての始まりでした。
一般的に、論文を書くと言ったらWordかPages,もしくはTexを使うようですね。
しかし僕はmarkdownで卒論を書いてみたいという謎のこだわりを持ちました。
そこで、markdownで書いた文章を卒論として提出できるように奮闘している記録を残しておきたいと思います。
markdownをPDFに出力する
markdownをPDFに変換するためには、markdown-pdfというnpmパッケージを利用しました。
markdown-pdfを利用すると、markdown→HTML→PDFという流れで変換ができます。
内部では、
markdownからHTMLの変換にはremarkable、
HTMLからPDFへの変換はPhantomjs(開発終了してます)が使われています。
一度
$ npm install -g markdown-pdf
などでインストールをすれば、
変換は以下のようなコマンドを打つだけで行なえます
$ markdown-pdf [markdwonファイルのパス]
例えばこのようなMarkdownは、
# h1 Heading
## h2 Heading
### h3 Heading
#### h4 Heading
##### h5 Heading
###### h6 Heading
qiita advent
**Markdown**
で!
**卒論!**
を、書くぞ!!!
この記事はOthlotechアドベントカレンダー23日目の記事です。
あひー
>javaとjavascriptは、グレープとグレープフルーツくらい違うよ。
>メロンとメロンパンくらい違うかもしれない。
このようになります。
PDFの見た目を整える
markdown-pdfでは、独自に作成したcssをHTMLに反映することが可能です。
markdownがどのHTMLタグに変換されるのかは、基のソースコードを見てもいいですが、markdown-it demoを参照するとわかりやすいです。
僕は、本文に関しては以下のようなcssを作成しました。(きれいではない)
html {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 25px 20px;
color: black;
font-family: "Hiragino Mincho Pro";
font-size: 11px;
line-height: 180%;
}
h1 {
font-family: "Hiragino Kaku Gothic ProN", "メイリオ", sans-serif;
font-weight: 900;
margin: 0 0 -5px 0;
padding: 0;
}
h2 {
font-family: "Hiragino Kaku Gothic ProN", "メイリオ", sans-serif;
font-weight: 900;
padding-bottom: 3px;
border-bottom: solid black 1px;
margin: 15px 0;
}
h3 {
font-family: "Hiragino Kaku Gothic ProN", "メイリオ", sans-serif;
font-weight: 900;
color: black;
padding-bottom: 0;
margin-bottom: 5px;
}
p {
margin: 0;
padding: 0;
}
blockquote {
box-sizing: border-box;
padding: 20px 35px 20px 20px;
margin: 0;
border: none;
}
blockquote > p{
font-style: italic;
font-size: 80%;
color: black;
}
文章がかけて、引用や画像が加えられるだけのcssです。
コマンドは、
$ markdown-pdf [markdwonファイルのパス] -s [cssファイルのパス]
のようにcssファイルを
これを用いてmarkdwon-pdfを実行すると以下の結果になります。
before
after
自分のCSSを当てる場合、デフォルトであたっていたスタイルがなくなってしまうことに配慮が必要。
論文では強調表現などはしないので、省略しています。
複数のPDFを一枚にまとめる
ひとつのファイルに卒論の全てを書くのではなく、
一章一ファイル
で管理することにしました。
前述したmarkdown-pdfでは、複数のmdファイルをまとめてPdfにすることが出来ないようなので、
mdファイルごとにpdfを作成し、
それらのpdf最後にまとめることにしました。
ImageMagicを使用します。
使い方については、公式サイトをご覧ください!
ダウンロード
コマンドライン
注意点は、オプションを付けなければpdfの解像度や色味が荒くなってしまうことです。
オプションで解決できますが、処理時間が長くなってしまうのが難点です。
他にベターな解決策があるかもしれません。
ご存知の方はご教示ください。
自動で目次ページを作成する
それぞれのファイルから行ごとに文章をを読み取り、先頭が「#」で始まる場合は見出しと処理をします。
全てのファイルを読み取った上で取得した見出しを、別ファイルに書出せば目次ページMarkdownの完成です。
goで書いてみました。
package main
import (
"bufio"
"fmt"
"log"
"os"
"strconv"
"strings"
)
func main() {
fmt.Printf("卒論の目次を更新します\n\n")
file, err := os.OpenFile("appendix.md", os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
fmt.Fprintln(file, "")
for i := 1; i <= 5; i++ {
fmt.Println(i)
name, err := makeAppendix(strconv.Itoa(i) + ".md")
fmt.Println(name)
if err != nil {
panic(err)
}
}
fmt.Printf("卒論の目次を更新しました")
}
func makeAppendix(filename string) (string, error) {
fp, err := os.Open(filename)
if err != nil {
return filename, err
}
texts := make([]string, 0)
scanner := bufio.NewScanner(fp)
for scanner.Scan() {
texts = append(texts, scanner.Text())
// lines++
}
fp.Close()
file, err := os.OpenFile("appendix.md", os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
for _, text := range texts {
if strings.HasPrefix(text, "#") {
fmt.Println(text)
fmt.Fprintln(file, text)
}
}
return filename, nil
}
5章まで存在するmdファイルの全てから見出しを読み取り、
appendix.mdという目次ファイルを作成するプログラムです。
これを起動するとどうなるかというと、
例えば
# h1 Heading
この世界には二種類の人間がいる。プログラマーとプログラマーだ。
誰だってこのどちらかには当てはまる。君だってそうだ。
## h2 Heading
見出しばかりの人生なんていらない
### h3 Heading
qiita advent
**Markdown**
で!
**卒論!**
を、書くぞ!!!
この記事はOthlotechアドベントカレンダー23日目の記事です。
あひー
>javaとjavascriptは、グレープとグレープフルーツくらい違うよ。
>メロンとメロンパンくらい違うかもしれない。
### h3 Heading
誰も見出しがいらないなんて言ってないよ。
のようなmdファイルから見出しを抜き出して
# h1 Heading
## h2 Heading
### h3 Heading
### h3 Heading
こんな感じのmdファイルを作成できます。
ここで作成した目次ファイルも、markdown-pdfで変換するのですが、ここに当てはめるCSSは本文用とは別に作成しました。
文章の文字数をカウントする
文字数は、見出しと画像データの文字数を条件から外せば数えられます。
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
fmt.Printf("卒論の文字数\n\n")
allCount := 0
for i := 1; i <= 5; i++ {
count, ideaCount, err := textQuantity(strconv.Itoa(i) + ".md")
if err != nil {
panic(err)
}
fmt.Printf("%d章: %d文字\n 候補文の数:%dつ\n", i, count, ideaCount)
allCount += count
}
fmt.Printf("\n全ての合計: %d文字\n", allCount)
}
func textQuantity(filename string) (int, int, error) {
fp, err := os.Open(filename)
if err != nil {
return 0, 0, fmt.Errorf(filename + " can't be opened")
}
ideaCount := 0
texts := make([]string, 0)
textCounts := 0
scanner := bufio.NewScanner(fp)
for scanner.Scan() {
texts = append(texts, scanner.Text())
}
fp.Close()
for _, text := range texts {
// 見出しなどは文字数にカウントしない
if !(strings.HasPrefix(text, "#") || strings.HasPrefix(text, "-") || strings.HasPrefix(text, " ") || strings.HasPrefix(text, "「") || strings.HasPrefix(text, "!") || strings.HasPrefix(text, ">!")) {
textCounts += len([]rune(text))
} else if strings.HasPrefix(text, "「") {
ideaCount++
}
}
return textCounts, ideaCount, nil
}
これまでの処理をひとつのコマンドで行う
以上で書いた処理だけでも、
目次ページを作る
各ファイルをpdfに変換する
pdfファイルをひとつにまとめる
というコマンドを叩く必要があります。
いちいち叩きたくないので、makeコマンドで完結するようにしておきます。
makefileを作成しておけば、makeと唱えるだけで全ての処理を行ってくれます。
for the future
-
数式の表示
論文なのし数式書けない。これは論外。
しかし、Mathjaxを組み込めれば、数式もかけちゃいそうです。
ただ、僕は文系なので卒論に数式が出てこないので対応予定はないです。 -
ページ数
gofpdfを使えばできそう。
ただ、このライブラリを全く触れられていません
最悪の手段としては、iLovePDFを使用すること。これを使えばブラウザで、pdfにページ数を入れることができます。
しかし、変換に時間がかかるのと、卒論のデータを渡すことになってしまう。困る。 -
ヘッダー
ページのヘッダーには、その章の題名を書きたい。
これも、gofpdfを使えばできそうかな・・・。 -
余白の調整
ページ中に半端な余白ができる場合、レイウトを調節して次のページから見出しが始まるようにしたい。
これを自動で行うのは難しいかも。
うーん、出来なくはなさそうだけど、
卒論を書きながらこれらに対応する時間があるのかは微妙。
果たして、最後までMarkdownを貫き通すことが出来るのか……!!??
ちょっと自信無いです。。。(´・ω・`)