Markdownで書かれたスライドをHTMLとポータブルPDFと印刷用PDFにする
書き捨てユーティリティコード
- TOP
- Old Archives
- Markdownで書かれたスライドをHTMLとポータブルPDFと印刷用PDFにする
Aki SI&EのPR用に書いたものだが、Markdownで書き、Web(HTML)、配布用PDF、印刷用PDFの3種類を生成する考えでいた。
手でやろうかと思っていたのだが、再生成の回数も多そうだったので、自動化できるようにした。
Markdownで記述したドキュメントと、オリジナルサイズの画像ディレクトリ、mogrify -geometry x300
でリサイズした画像ディレクトリが用意されている。
Web用のものについてはHTMLで出力し、リサイズされた画像のWebサーバー上のコピーを参照しなければならない。
PDFについては、MarkdownをLaTeXに変換してという方法もあるにはあったが、画像を含めた細かなデザインを施したかったため、HTMLをベースにPDFに変換することにした。
MarkdownコンバータはRubyのKramdownを使用。改ページはないため、wkhtmltopdf
を用いてPDFに変換することとした。
参照しているディレクトリの違いで2回ループを回す。
それぞれHTMLは別に出力し、テンポラリファイルとして出力したHTMLを元にPDFのテンポラリファイルを生成、unitepdf
を使ってこれを結合する。
専用のコードなので多くをハードコーディングしているが、これで正常に機能する。
#!/usr/bin/ruby
# -*- mode: ruby; coding: UTF-8 -*-
require 'kramdown'
require 'erb'
def treat_md(file, findex)
$article_body = doc = Kramdown::Document.new(File.read(file)).to_html
$article_title = doc[/<h1[^>]*>(.*?)<\/h1>/, 1]
foot = Array.new
if findex > 0
foot << '<a href="' + ( SOURCEFILES[findex - 1].sub(/\.md$/, '') + ".html" ) + '">前へ</a>'
end
foot << '<a href="/si/" target="_top">Aki SI&Eトップページへ</a>'
if findex < ( SOURCEFILES.length - 1 )
foot << '<a href="' + ( SOURCEFILES[findex + 1].sub(/\.md$/, '') + ".html" ) + '">次へ</a>'
end
$article_footer = foot.join
end
TEMPLATE = <<'END'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/dtd/xhtml1-transitional.dtd">
<html>
<head>
<title><%= $article_title %></title>
<meta http-equiv="content-language" content="ja" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
body {
% case $mode
% when :Web
font-size: 130%;
color: #333;
font-weight: bold;
margin: 0px;
padding: 0px;
% else
font-size: 18pt;
color: #000;
font-weight: bold;
margin: 2cm auto;
padding: auto;
% end
background-color: #fff;
font-family: "Migu 1C"
}
h3 {
font-size: 135%;
}
#Container {
margin: auto auto 100px;
max-width: 950px;
text-align: center;
}
img {
% case $mode
% when :Web
height: 300px;
% else
height: 18em;
max-width: 100%;
% end
}
ul {
text-align: left;
margin: auto 1.8em;
}
#ArticleFooter {
% if $mode != :Web
display:none;
% end
position: fixed;
bottom: 0px;
margin: 0px;
width: 100%;
max-height: 100px;
background-color: #339;
color: #fff;
text-align: center;
}
#ArticleFooter a {
padding: 0 0.8em;
text-decoration: none;
color: #fff
}
#ArticleFooter a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div id="Container">
<%= $article_body.gsub(
%r{src="img/},
%(src="#{$img_type}_img/)
)
%>
</div>
<div id="ArticleFooter">
<%= $article_footer %>
</div>
</body>
</html>
END
$article_body = nil
$article_footer = nil
$article_title = nil
SOURCEFILES = Dir.entries(".").select {|i| i =~ /\.md$/ }.sort
# HTML
$img_type = "/img/si/intro_slideshow/resized"
$mode = :Web
SOURCEFILES.each_with_index do |x, i|
begin
treat_md(x, i)
File.open("out/#{x.sub(".md", ".html")}", "w") do |f|
f.puts(ERB.new(TEMPLATE, nil, "%<").result)
end
ensure
$article_body = nil
$article_footer = nil
$article_title = nil
end
end
# Web PDF
$img_type = "resized"
$mode = :PDF
SOURCEFILES.each_with_index do |x, i|
begin
treat_md(x, i)
fn = "out/_tmp_#{x.sub(".md", ".html")}"
File.open(fn, "w") do |f|
f.puts(ERB.new(TEMPLATE, nil, "%<").result)
end
system('wkhtmltopdf "%s" "%s"' % [ fn, fn.gsub(".html", ".pdf") ])
ensure
$article_body = nil
$article_footer = nil
$article_title = nil
end
end
system 'pdfunite out/_tmp_*.pdf out/portable.pdf'
system 'rm out/_tmp_*'
# Printable
$img_type = "original"
$mode = :PDF
SOURCEFILES.each_with_index do |x, i|
begin
treat_md(x, i)
fn = "out/_tmp_#{x.sub(".md", ".html")}"
File.open(fn, "w") do |f|
f.puts(ERB.new(TEMPLATE, nil, "%<").result)
end
system('wkhtmltopdf "%s" "%s"' % [ fn, fn.gsub(".html", ".pdf") ])
ensure
$article_body = nil
$article_footer = nil
$article_title = nil
end
end
system 'pdfunite out/_tmp_*.pdf out/printable.pdf'
system 'rm out/_tmp_*'
完成したものについては
Google DOCs Viewerはスライドショー向きではないので、ウェブ版を使うか、PDFをダウンロードするのがお勧め。