xpub 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +161 -0
- data/Rakefile +2 -0
- data/bin/xpub +74 -0
- data/lib/xpub.rb +5 -0
- data/lib/xpub/dsl/book.rb +261 -0
- data/lib/xpub/dsl/builder.rb +370 -0
- data/lib/xpub/dsl/page.rb +159 -0
- data/lib/xpub/dsl/src_file.rb +139 -0
- data/lib/xpub/version.rb +3 -0
- data/skel/.gitignore +2 -0
- data/skel/Xpub +68 -0
- data/skel/output/.gitkeep +0 -0
- data/skel/src/.gitkeep +0 -0
- data/skel/src/sample.md +47 -0
- data/skel/src/sample1.jpg +0 -0
- data/skel/theme/default/epub/epub.css +204 -0
- data/skel/theme/default/epub/metadata.dat.erb +43 -0
- data/skel/theme/default/epub/pandoc-filter.rb +206 -0
- data/skel/theme/default/epub/template.html +57 -0
- data/skel/theme/default/latex/pandoc-filter.rb +269 -0
- data/skel/theme/default/latex/template.tex +376 -0
- data/skel/tmp/.gitkeep +0 -0
- data/xpub.gemspec +25 -0
- metadata +113 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
<%- @book.identifiers.each do |identifier| -%>
|
2
|
+
<dc:identifier<%- if identifier.scheme -%> opf:scheme="<%= identifier.scheme %>"<%- end -%>><%= identifier.identifier %></dc:identifier>
|
3
|
+
<%- end -%>
|
4
|
+
<%- if @book.lang -%>
|
5
|
+
<dc:language><%= @book.lang %></dc:language>
|
6
|
+
<%- end -%>
|
7
|
+
<dc:title opf:type="main"><%= @book.title %></dc:title>
|
8
|
+
<%- if @book.subtitle -%>
|
9
|
+
<dc:title opf:type="subtitle"><%= @book.subtitle %></dc:title>
|
10
|
+
<%- end -%>
|
11
|
+
<%- if @book.short -%>
|
12
|
+
<dc:title opf:type="short"><%= @book.short %></dc:title>
|
13
|
+
<%- end -%>
|
14
|
+
<%- if @book.collection -%>
|
15
|
+
<dc:title opf:type="collection"><%= @book.collection %></dc:title>
|
16
|
+
<%- end -%>
|
17
|
+
<%- if @book.edition -%>
|
18
|
+
<dc:title opf:type="edition"><%= @book.edition %></dc:title>
|
19
|
+
<%- end -%>
|
20
|
+
<%- if @book.extended -%>
|
21
|
+
<dc:title opf:type="extended"><%= @book.extended %></dc:title>
|
22
|
+
<%- end -%>
|
23
|
+
<%- if @book.publisher -%>
|
24
|
+
<dc:publisher><%= @book.publisher %></dc:publisher>
|
25
|
+
<%- end -%>
|
26
|
+
<%- @book.creators.each do |c| -%>
|
27
|
+
<dc:creator<%- if c.role -%> opf:role="<%= c.role %>"<%- end -%>><%= c.name %></dc:creator>
|
28
|
+
<%- end -%>
|
29
|
+
<%- @book.contributors.each do |c| -%>
|
30
|
+
<dc:contributor<%- if c.role -%> opf:role="<%= c.role %>"<%- end -%>><%= c.name %></dc:contributor>
|
31
|
+
<%- end -%>
|
32
|
+
<%- if @book.description -%>
|
33
|
+
<dc:description><%= @book.description %></dc:description>
|
34
|
+
<%- end -%>
|
35
|
+
<%- if @book.rights -%>
|
36
|
+
<dc:rights><%= @book.rights %></dc:rights>
|
37
|
+
<%- end -%>
|
38
|
+
<%- if @book.publication -%>
|
39
|
+
<dc:date><%= Time.parse(@book.publication).utc.iso8601 %></dc:date>
|
40
|
+
<%- end -%>
|
41
|
+
<%- if @book.modification -%>
|
42
|
+
<meta property="dcterms:modified"><%= Time.parse(@book.modification).utc.iso8601 %></meta>
|
43
|
+
<%- end -%>
|
@@ -0,0 +1,206 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class PandocFilter
|
6
|
+
|
7
|
+
def initialize filters
|
8
|
+
@filters = filters
|
9
|
+
end
|
10
|
+
|
11
|
+
def filter_str str
|
12
|
+
doc = JSON.parse str
|
13
|
+
doc.each { |child|
|
14
|
+
filter_node doc, child
|
15
|
+
}
|
16
|
+
JSON.generate doc
|
17
|
+
end
|
18
|
+
|
19
|
+
def before_filter doc, node
|
20
|
+
@filters.each { |f|
|
21
|
+
f.filter doc, node, "before"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def after_filter doc, node
|
26
|
+
@filters.each { |f|
|
27
|
+
f.filter doc, node, "after"
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def filter_node doc, node
|
32
|
+
if node.kind_of?(String)
|
33
|
+
elsif node.kind_of?(Array)
|
34
|
+
before_filter doc, node
|
35
|
+
node.each { |child|
|
36
|
+
filter_node doc, child
|
37
|
+
}
|
38
|
+
after_filter doc, node
|
39
|
+
elsif node.kind_of?(Hash)
|
40
|
+
if node.has_key? "t"
|
41
|
+
before_filter doc, node
|
42
|
+
filter_node doc, node["c"]
|
43
|
+
after_filter doc, node
|
44
|
+
end
|
45
|
+
else
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
# ルビフィルタ
|
53
|
+
# グループルビ
|
54
|
+
# {電子出版|でんししゅっぱん}を手軽に
|
55
|
+
# <ruby>電子出版<rt>でんししゅっぱん</rt></ruby>を手軽に
|
56
|
+
# 熟語ルビ
|
57
|
+
# {電子出版|でん|し|しゅっ|ぱん}を手軽に
|
58
|
+
# <ruby>電<rt>でん</rt>子<rt>し</rt>出<rt>しゅっ</rt>版<rt>ぱん</rt>を手軽に</p>
|
59
|
+
class FuriganaFilter
|
60
|
+
|
61
|
+
def pattern
|
62
|
+
/{([^|]+)\|([^|}]+(\|[^|}]+)*)}/
|
63
|
+
end
|
64
|
+
|
65
|
+
def split pattern, str
|
66
|
+
if str.match pattern
|
67
|
+
if $` == ""
|
68
|
+
[[$&,true]].concat split(pattern, $')
|
69
|
+
else
|
70
|
+
[[$`, false],[$&,true]].concat split(pattern, $')
|
71
|
+
end
|
72
|
+
else
|
73
|
+
if str == ""
|
74
|
+
[]
|
75
|
+
else
|
76
|
+
[[str, false]]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def replace str
|
83
|
+
str.match(pattern) { |md|
|
84
|
+
phrase = md[1]
|
85
|
+
ruby_chars = md[2].split('|')
|
86
|
+
if phrase.length == ruby_chars.length
|
87
|
+
# 熟語ルビ
|
88
|
+
"<ruby>" + phrase.split("").zip(ruby_chars).map {|c,r|
|
89
|
+
"#{c}<rt>#{r}</rt>"
|
90
|
+
}.join("") + "</ruby>"
|
91
|
+
else
|
92
|
+
# グループルビ
|
93
|
+
"<ruby>#{phrase}<rt>#{ruby_chars.join("")}</rt></ruby>"
|
94
|
+
end
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def filter doc, node, mode
|
99
|
+
if mode == "before" && node.kind_of?(Array)
|
100
|
+
new_node = []
|
101
|
+
node.each { |child|
|
102
|
+
if child.kind_of?(Hash) &&
|
103
|
+
child["t"] == "Str" &&
|
104
|
+
child["c"].match(pattern)
|
105
|
+
split(pattern, child["c"]).map { |str, flag|
|
106
|
+
if flag
|
107
|
+
new_node << { "t" => "RawInline","c" => ["html",replace(str)]}
|
108
|
+
else
|
109
|
+
new_node << { "t" => "Str", "c" => str }
|
110
|
+
end
|
111
|
+
}
|
112
|
+
else
|
113
|
+
new_node << child
|
114
|
+
end
|
115
|
+
}
|
116
|
+
node.replace new_node
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# 改ページフィルタ
|
122
|
+
# なにもうめこまない。chapter単位で分割する
|
123
|
+
class NewPageFilter
|
124
|
+
|
125
|
+
def pattern
|
126
|
+
/^===.*$/
|
127
|
+
end
|
128
|
+
|
129
|
+
def filter doc, node, mode
|
130
|
+
if mode == "before" && node.kind_of?(Hash)
|
131
|
+
if node["t"] == "Para" &&
|
132
|
+
node["c"].count == 1 &&
|
133
|
+
node["c"][0]["t"] == "Str" &&
|
134
|
+
node["c"][0]["c"].match(pattern)
|
135
|
+
node["c"][0]["t"] = "RawInline"
|
136
|
+
|
137
|
+
l = node["c"][0]["c"].length
|
138
|
+
node["c"][0]["c"] = ["html",""]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# 縦横中フィルタ
|
145
|
+
class TateNakaYokoFilter
|
146
|
+
|
147
|
+
def pattern
|
148
|
+
/\^([^^]+)\^/
|
149
|
+
end
|
150
|
+
|
151
|
+
def split pattern, str
|
152
|
+
if str.match pattern
|
153
|
+
if $` == ""
|
154
|
+
[[$&,true]].concat split(pattern, $')
|
155
|
+
else
|
156
|
+
[[$`, false],[$&,true]].concat split(pattern, $')
|
157
|
+
end
|
158
|
+
else
|
159
|
+
if str == ""
|
160
|
+
[]
|
161
|
+
else
|
162
|
+
[[str, false]]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
def replace str
|
169
|
+
str.match(pattern) { |md|
|
170
|
+
word = md[1]
|
171
|
+
"<span class=\"tcy\">#{word}</span>"
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
def filter doc, node, mode
|
176
|
+
if mode == "before" && node.kind_of?(Array)
|
177
|
+
new_node = []
|
178
|
+
node.each { |child|
|
179
|
+
if child.kind_of?(Hash) &&
|
180
|
+
child["t"] == "Str" &&
|
181
|
+
child["c"].match(pattern)
|
182
|
+
split(pattern, child["c"]).map { |str, flag|
|
183
|
+
if flag
|
184
|
+
new_node << { "t" => "RawInline","c" => ["html",replace(str)]}
|
185
|
+
else
|
186
|
+
new_node << { "t" => "Str", "c" => str }
|
187
|
+
end
|
188
|
+
}
|
189
|
+
else
|
190
|
+
new_node << child
|
191
|
+
end
|
192
|
+
}
|
193
|
+
node.replace new_node
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
filters = [
|
199
|
+
FuriganaFilter.new,
|
200
|
+
TateNakaYokoFilter.new,
|
201
|
+
NewPageFilter.new
|
202
|
+
]
|
203
|
+
|
204
|
+
puts PandocFilter.new(filters).filter_str STDIN.read
|
205
|
+
|
206
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE html>
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"$if(lang)$ xml:lang="$lang$"$endif$>
|
4
|
+
<head>
|
5
|
+
<meta charset="utf-8" />
|
6
|
+
<meta name="generator" content="pandoc" />
|
7
|
+
<meta name="generator" content="ebc" />
|
8
|
+
<title>$pagetitle$</title>
|
9
|
+
$if(quotes)$
|
10
|
+
<style type="text/css">
|
11
|
+
q { quotes: "“" "”" "‘" "’"; }
|
12
|
+
</style>
|
13
|
+
$endif$
|
14
|
+
$if(highlighting-css)$
|
15
|
+
<style type="text/css">
|
16
|
+
$highlighting-css$
|
17
|
+
</style>
|
18
|
+
$endif$
|
19
|
+
$for(css)$
|
20
|
+
<link rel="stylesheet" type="text/css" href="$css$" />
|
21
|
+
$endfor$
|
22
|
+
</head>
|
23
|
+
<body$if(coverpage)$ id="cover"$endif$>
|
24
|
+
$if(titlepage)$
|
25
|
+
<section epub:type="titlepage">
|
26
|
+
$for(title)$
|
27
|
+
$if(title.type)$
|
28
|
+
<h1 class="$title.type$">$title.text$</h1>
|
29
|
+
$else$
|
30
|
+
<h1 class="title">$title$</h1>
|
31
|
+
$endif$
|
32
|
+
$endfor$
|
33
|
+
$if(subtitle)$
|
34
|
+
<h1 class="subtitle">$subtitle$</h1>
|
35
|
+
$endif$
|
36
|
+
$for(author)$
|
37
|
+
<h2 class="author">$author$</h2>
|
38
|
+
$endfor$
|
39
|
+
$for(creator)$
|
40
|
+
<h2 class="$creator.type$">$creator.text$</h2>
|
41
|
+
$endfor$
|
42
|
+
$if(publisher)$
|
43
|
+
<p class="publisher">$publisher$</p>
|
44
|
+
$endif$
|
45
|
+
$if(date)$
|
46
|
+
<p class="date">$date$</p>
|
47
|
+
$endif$
|
48
|
+
$if(rights)$
|
49
|
+
<p class="rights">$rights$</p>
|
50
|
+
$endif$
|
51
|
+
</section>
|
52
|
+
$else$
|
53
|
+
$body$
|
54
|
+
$endif$
|
55
|
+
</body>
|
56
|
+
</html>
|
57
|
+
|
@@ -0,0 +1,269 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class PandocFilter
|
6
|
+
|
7
|
+
def initialize filters
|
8
|
+
@filters = filters
|
9
|
+
end
|
10
|
+
|
11
|
+
def filter_str str
|
12
|
+
doc = JSON.parse str
|
13
|
+
doc.each { |child|
|
14
|
+
filter_node doc, child
|
15
|
+
}
|
16
|
+
JSON.generate doc
|
17
|
+
end
|
18
|
+
|
19
|
+
def before_filter doc, node
|
20
|
+
@filters.each { |f|
|
21
|
+
f.filter doc, node, "before"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def after_filter doc, node
|
26
|
+
@filters.each { |f|
|
27
|
+
f.filter doc, node, "after"
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def filter_node doc, node
|
32
|
+
if node.kind_of?(String)
|
33
|
+
elsif node.kind_of?(Array)
|
34
|
+
before_filter doc, node
|
35
|
+
node.each { |child|
|
36
|
+
filter_node doc, child
|
37
|
+
}
|
38
|
+
after_filter doc, node
|
39
|
+
elsif node.kind_of?(Hash)
|
40
|
+
if node.has_key? "t"
|
41
|
+
before_filter doc, node
|
42
|
+
filter_node doc, node["c"]
|
43
|
+
after_filter doc, node
|
44
|
+
end
|
45
|
+
else
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
# ルビフィルタ
|
53
|
+
# グループルビ
|
54
|
+
# {電子出版|でんししゅっぱん}を手軽に
|
55
|
+
# \ruby{>電子出版}{でんししゅっぱん}を手軽に
|
56
|
+
# 熟語ルビ
|
57
|
+
# {電子出版|でん|し|しゅっ|ぱん}を手軽に
|
58
|
+
# \ruby{電}{でん}\ruby{子}{し}\ruby{出}{しゅっ}\ruby{版}{ぱん}を手軽に</p>
|
59
|
+
class FuriganaFilter
|
60
|
+
|
61
|
+
def pattern
|
62
|
+
/{(([^|]|\s)+)\|(([^|}]|\s)+(\|([^|}]|\s)+)*)}/
|
63
|
+
end
|
64
|
+
|
65
|
+
def split pattern, str
|
66
|
+
if str.match pattern
|
67
|
+
if $` == ""
|
68
|
+
[[$&,true]].concat split(pattern, $')
|
69
|
+
else
|
70
|
+
[[$`, false],[$&,true]].concat split(pattern, $')
|
71
|
+
end
|
72
|
+
else
|
73
|
+
if str == ""
|
74
|
+
[]
|
75
|
+
else
|
76
|
+
[[str, false]]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def replace str
|
83
|
+
str.match(pattern) { |md|
|
84
|
+
phrase = md[1]
|
85
|
+
ruby_chars = md[3].split('|')
|
86
|
+
if phrase.length == ruby_chars.length
|
87
|
+
# 熟語ルビ
|
88
|
+
phrase.split("").zip(ruby_chars).map {|c,r|
|
89
|
+
"\\ruby{#{c}}{#{r}}"
|
90
|
+
}.join ""
|
91
|
+
else
|
92
|
+
# グループルビ
|
93
|
+
"\\ruby{#{phrase}}{#{ruby_chars.join("")}}"
|
94
|
+
end
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def filter doc, node, mode
|
99
|
+
if mode == "before" && node.kind_of?(Array)
|
100
|
+
new_node = []
|
101
|
+
node.each { |child|
|
102
|
+
if child.kind_of?(Hash) &&
|
103
|
+
child["t"] == "Str" &&
|
104
|
+
child["c"].match(pattern)
|
105
|
+
split(pattern, child["c"]).map { |str, flag|
|
106
|
+
if flag
|
107
|
+
new_node << { "t" => "RawInline","c" => ["tex",replace(str)]}
|
108
|
+
else
|
109
|
+
new_node << { "t" => "Str", "c" => str }
|
110
|
+
end
|
111
|
+
}
|
112
|
+
else
|
113
|
+
new_node << child
|
114
|
+
end
|
115
|
+
}
|
116
|
+
node.replace new_node
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# 改ページフィルタ
|
122
|
+
# === だと\\newpage
|
123
|
+
# ==== だと\\clearpage
|
124
|
+
# ===== かそれ以上だと \\cleardoublepage
|
125
|
+
class NewPageFilter
|
126
|
+
|
127
|
+
def pattern
|
128
|
+
/^===.*$/
|
129
|
+
end
|
130
|
+
|
131
|
+
def filter doc, node, mode
|
132
|
+
if mode == "before" && node.kind_of?(Hash)
|
133
|
+
if node["t"] == "Para" &&
|
134
|
+
node["c"].count == 1 &&
|
135
|
+
node["c"][0]["t"] == "Str" &&
|
136
|
+
node["c"][0]["c"].match(pattern)
|
137
|
+
node["c"][0]["t"] = "RawInline"
|
138
|
+
|
139
|
+
l = node["c"][0]["c"].length
|
140
|
+
if l == 3
|
141
|
+
node["c"][0]["c"] = ["tex","\\newpage"]
|
142
|
+
elsif l == 4
|
143
|
+
node["c"][0]["c"] = ["tex","\\clearpage"]
|
144
|
+
else
|
145
|
+
node["c"][0]["c"] = ["tex","\\cleardoublepage"]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# 縦横中フィルタ
|
153
|
+
class TateNakaYokoFilter
|
154
|
+
|
155
|
+
def pattern
|
156
|
+
/\^([^^]+)\^/
|
157
|
+
end
|
158
|
+
|
159
|
+
def split pattern, str
|
160
|
+
if str.match pattern
|
161
|
+
if $` == ""
|
162
|
+
[[$&,true]].concat split(pattern, $')
|
163
|
+
else
|
164
|
+
[[$`, false],[$&,true]].concat split(pattern, $')
|
165
|
+
end
|
166
|
+
else
|
167
|
+
if str == ""
|
168
|
+
[]
|
169
|
+
else
|
170
|
+
[[str, false]]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
def replace str
|
177
|
+
str.match(pattern) { |md|
|
178
|
+
word = md[1]
|
179
|
+
"\\pbox<y>{#{word}}"
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
def filter doc, node, mode
|
184
|
+
if mode == "before" && node.kind_of?(Array)
|
185
|
+
new_node = []
|
186
|
+
node.each { |child|
|
187
|
+
if child.kind_of?(Hash) &&
|
188
|
+
child["t"] == "Str" &&
|
189
|
+
child["c"].match(pattern)
|
190
|
+
split(pattern, child["c"]).map { |str, flag|
|
191
|
+
if flag
|
192
|
+
new_node << { "t" => "RawInline","c" => ["tex",replace(str)]}
|
193
|
+
else
|
194
|
+
new_node << { "t" => "Str", "c" => str }
|
195
|
+
end
|
196
|
+
}
|
197
|
+
else
|
198
|
+
new_node << child
|
199
|
+
end
|
200
|
+
}
|
201
|
+
node.replace new_node
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
# 改行フィルタ
|
208
|
+
# Markdownで文章を改行したあとに、空行を挿入せずに文章を続けるときに、単なる改行になるようなフィルタ
|
209
|
+
# Pandocに同様のオプションがあるためこのフィルタは使わない
|
210
|
+
class NewLineFilter
|
211
|
+
def filter doc, node, mode
|
212
|
+
if mode == "before" && node.kind_of?(Hash)
|
213
|
+
if node["t"] == "Para"
|
214
|
+
node["c"].each { |child|
|
215
|
+
if child.kind_of?(Hash)
|
216
|
+
if child["t"] == "Space"
|
217
|
+
child["t"] = "RawInline"
|
218
|
+
child["c"] = ["tex", "\\\\"]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
}
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
class ColumnFilter
|
228
|
+
def pattern
|
229
|
+
/\s*<!--\s*%%(twocolumn|onecolumn)%%\s*-->\s*/
|
230
|
+
end
|
231
|
+
def filter doc, node, mode
|
232
|
+
if mode == "before" && node.kind_of?(Hash)
|
233
|
+
if node["t"] == "RawBlock" && node["c"][0] == "html" && node["c"][1].match(pattern)
|
234
|
+
node["c"][0] = "tex"
|
235
|
+
node["c"][1].match(pattern) { |md|
|
236
|
+
node["c"][1] = "\\" + md[1]
|
237
|
+
}
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class TocFilter
|
244
|
+
def pattern
|
245
|
+
/\s*<!--\s*%%toc%%\s*-->\s*/
|
246
|
+
end
|
247
|
+
def filter doc, node, mode
|
248
|
+
if mode == "before" && node.kind_of?(Hash)
|
249
|
+
if node["t"] == "RawBlock" && node["c"][0] == "html" && node["c"][1].match(pattern)
|
250
|
+
node["c"][0] = "tex"
|
251
|
+
node["c"][1] = "\\tableofcontents"
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
filters = [
|
259
|
+
FuriganaFilter.new,
|
260
|
+
TateNakaYokoFilter.new,
|
261
|
+
NewPageFilter.new,
|
262
|
+
ColumnFilter.new,
|
263
|
+
TocFilter.new,
|
264
|
+
# NewLineFilter.new
|
265
|
+
]
|
266
|
+
|
267
|
+
puts PandocFilter.new(filters).filter_str STDIN.read
|
268
|
+
|
269
|
+
|