cbeta 3.8.0 → 4.0.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/cbeta.rb +0 -6
- data.tar.gz.sig +0 -0
- metadata +1 -10
- metadata.gz.sig +0 -0
- data/lib/cbeta/html_to_pdf.rb +0 -75
- data/lib/cbeta/html_to_text.rb +0 -151
- data/lib/cbeta/p5a_to_html.rb +0 -813
- data/lib/cbeta/p5a_to_html_for_every_edition.rb +0 -940
- data/lib/cbeta/p5a_to_html_for_pdf.rb +0 -751
- data/lib/cbeta/p5a_to_simple_html.rb +0 -426
- data/lib/data/html-for-pdf.css +0 -144
- data/lib/data/pdf-template.htm +0 -14
- data/lib/data/unicode-1.1.json +0 -1
|
@@ -1,751 +0,0 @@
|
|
|
1
|
-
require 'cgi'
|
|
2
|
-
require 'date'
|
|
3
|
-
require 'fileutils'
|
|
4
|
-
require 'json'
|
|
5
|
-
require 'nokogiri'
|
|
6
|
-
require 'set'
|
|
7
|
-
require 'erb'
|
|
8
|
-
require_relative 'cbeta_share'
|
|
9
|
-
|
|
10
|
-
# Convert CBETA XML P5a to HTML for PDF
|
|
11
|
-
#
|
|
12
|
-
# You can get CBETA XML P5a from: https://github.com/cbeta-git/xml-p5a
|
|
13
|
-
class CBETA::P5aToHTMLForPDF
|
|
14
|
-
# 內容不輸出的元素
|
|
15
|
-
PASS=['back', 'teiHeader']
|
|
16
|
-
|
|
17
|
-
# 某版用字缺的符號
|
|
18
|
-
MISSING = '-'
|
|
19
|
-
|
|
20
|
-
private_constant :PASS, :MISSING
|
|
21
|
-
|
|
22
|
-
# @param xml_root [String] 來源 CBETA XML P5a 路徑
|
|
23
|
-
# @param out_root [String] 輸出 HTML 路徑
|
|
24
|
-
# @option opts [String] :graphic_base folder of graphics
|
|
25
|
-
# * graphic_base/figures: 插圖圖檔位置
|
|
26
|
-
# * graphic_base/sd-gif: images for Siddham (悉曇字)
|
|
27
|
-
# * graphic_base/rj-gif: images for Ranjana (蘭札體)
|
|
28
|
-
# @option opts [String] :front_page 內文前可以加一段 HTML,例如「編輯說明」
|
|
29
|
-
# @option opts [String] :front_page_title 加在目錄的 front_page 標題
|
|
30
|
-
# @option opts [String] :back_page 內文後可以加一段 HTML,例如「版權聲明」
|
|
31
|
-
# @option opts [String] :back_page_title 加在目錄的 back_page 標題
|
|
32
|
-
# @option opts [Boolean] :toc 要不要放目次, 預設會有目次
|
|
33
|
-
def initialize(xml_root, out_root, opts={})
|
|
34
|
-
@config = {
|
|
35
|
-
toc: true
|
|
36
|
-
}
|
|
37
|
-
@config.merge!(opts)
|
|
38
|
-
|
|
39
|
-
@xml_root = xml_root
|
|
40
|
-
@out_root = out_root
|
|
41
|
-
@cbeta = CBETA.new
|
|
42
|
-
@gaijis = CBETA::Gaiji.new
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# 將 CBETA XML P5a 轉為 HTML 供轉為 PDF
|
|
46
|
-
#
|
|
47
|
-
# @example for convert 大正藏全部:
|
|
48
|
-
#
|
|
49
|
-
# c = CBETA::P5aToHTMLForPDF.new('/PATH/TO/CBETA/XML/P5a', '/OUTPUT/FOLDER')
|
|
50
|
-
# c.convert('T')
|
|
51
|
-
#
|
|
52
|
-
# T 是大正藏的 ID, CBETA 的藏經 ID 系統請參考: http://www.cbeta.org/format/id.php
|
|
53
|
-
def convert(target=nil)
|
|
54
|
-
return convert_all if target.nil?
|
|
55
|
-
|
|
56
|
-
arg = target.upcase
|
|
57
|
-
convert_collection(arg)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
include CbetaShare
|
|
63
|
-
|
|
64
|
-
def before_convert_work(work_id)
|
|
65
|
-
@nav_doc = Nokogiri::XML('<ul></ul>')
|
|
66
|
-
@nav_doc.remove_namespaces!()
|
|
67
|
-
@nav_root = @nav_doc.at_xpath('/ul')
|
|
68
|
-
@current_nav = [@nav_root]
|
|
69
|
-
@div_count = 0
|
|
70
|
-
@mulu_count = 0
|
|
71
|
-
@open_divs = []
|
|
72
|
-
@text = ''
|
|
73
|
-
|
|
74
|
-
@output_folder_work = File.join(@out_root, @series, work_id)
|
|
75
|
-
FileUtils.mkdir_p(@output_folder_work) unless Dir.exist? @output_folder_work
|
|
76
|
-
|
|
77
|
-
src = File.join(CBETA::DATA, 'html-for-pdf.css')
|
|
78
|
-
copy_file(src)
|
|
79
|
-
|
|
80
|
-
@cover = nil
|
|
81
|
-
if @config.key? :graphic_base
|
|
82
|
-
cover = File.join(@config[:graphic_base], 'covers', @series, "#{work_id}.jpg")
|
|
83
|
-
if File.exist? cover
|
|
84
|
-
@mulu_count += 1
|
|
85
|
-
@cover = "<a id='mulu#{@mulu_count}'></a><mulu1 title='封面'> </mulu1>"
|
|
86
|
-
@cover += "<div id='cover'><img src='#{work_id}.jpg' /></div>"
|
|
87
|
-
copy_file(cover)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
if @config[:front_page_title]
|
|
92
|
-
s = @config[:front_page_title]
|
|
93
|
-
@nav_root.add_child("<li><a href='#front'>#{s}</a></li>")
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def before_parse_xml(xml_fn)
|
|
99
|
-
@in_l = false
|
|
100
|
-
@lg_row_open = false
|
|
101
|
-
@t_buf1 = []
|
|
102
|
-
@t_buf2 = []
|
|
103
|
-
@sutra_no = File.basename(xml_fn, ".xml")
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def convert_all
|
|
107
|
-
Dir.foreach(@xml_root) { |c|
|
|
108
|
-
next unless c.match(/^[A-Z]$/)
|
|
109
|
-
convert_collection(c)
|
|
110
|
-
}
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def convert_collection(c)
|
|
114
|
-
@series = c
|
|
115
|
-
puts 'convert_collection ' + c
|
|
116
|
-
|
|
117
|
-
@orig = @cbeta.get_canon_abbr(c)
|
|
118
|
-
|
|
119
|
-
folder = File.join(@xml_root, @series)
|
|
120
|
-
@works = {}
|
|
121
|
-
prepare_work_list(folder)
|
|
122
|
-
@works.each do |work_id, xml_files|
|
|
123
|
-
convert_work(work_id, xml_files)
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def convert_work(work_id, xml_files)
|
|
128
|
-
puts "convert xml to html: work_id: #{work_id}"
|
|
129
|
-
|
|
130
|
-
before_convert_work(work_id)
|
|
131
|
-
|
|
132
|
-
# 目次
|
|
133
|
-
if @config[:back_page_title]
|
|
134
|
-
s = @config[:back_page_title]
|
|
135
|
-
@nav_root.add_child("<li><a href='#back'>#{s}</a></li>")
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if @config.key? :front_page
|
|
140
|
-
s = File.read(@config[:front_page])
|
|
141
|
-
@front = "<div id='front'>#{s}</div>"
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
if @config.key? :back_page
|
|
145
|
-
s = File.read(@config[:back_page])
|
|
146
|
-
@back = "<div id='back'>#{s}</div>"
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
xml_files.each do |fn|
|
|
150
|
-
@text += convert_xml_file(fn)
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
if @config[:toc]
|
|
154
|
-
@toc = to_html(@nav_root)
|
|
155
|
-
@toc.gsub!('<ul/>', '')
|
|
156
|
-
@toc = "<div><h1>目次</h1>#{@toc}</div>"
|
|
157
|
-
else
|
|
158
|
-
@toc = ''
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
fn = File.join(CBETA::DATA, 'pdf-template.htm')
|
|
162
|
-
template = File.read(fn)
|
|
163
|
-
output = template % {
|
|
164
|
-
cover: @cover,
|
|
165
|
-
toc: @toc,
|
|
166
|
-
front: @front,
|
|
167
|
-
text: @text,
|
|
168
|
-
back: @back
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
fn = File.join(@output_folder_work, 'main.htm')
|
|
172
|
-
File.write(fn, output)
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def convert_xml_file(xml_fn)
|
|
176
|
-
before_parse_xml(xml_fn)
|
|
177
|
-
parse_xml(xml_fn)
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def copy_file(src)
|
|
181
|
-
basename = File.basename(src)
|
|
182
|
-
dest = File.join(@output_folder_work, basename)
|
|
183
|
-
FileUtils.copy(src, dest)
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def handle_anchor(e)
|
|
187
|
-
if e.has_attribute?('type')
|
|
188
|
-
if e['type'] == 'circle'
|
|
189
|
-
return '◎'
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
''
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
def handle_app(e)
|
|
197
|
-
traverse(e)
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
def handle_byline(e)
|
|
201
|
-
s = traverse(e)
|
|
202
|
-
"<p class='byline'>#{s}</p>"
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
def handle_cell(e)
|
|
206
|
-
doc = Nokogiri::XML::Document.new
|
|
207
|
-
cell = doc.create_element('td')
|
|
208
|
-
cell['rowspan'] = e['rows'] if e.key? 'rows'
|
|
209
|
-
cell['colspan'] = e['cols'] if e.key? 'cols'
|
|
210
|
-
cell.inner_html = traverse(e)
|
|
211
|
-
to_html(cell)
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
def handle_corr(e)
|
|
216
|
-
"<span class='corr'>%s</span>" % traverse(e)
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
def handle_div(e)
|
|
220
|
-
if e.has_attribute? 'type'
|
|
221
|
-
@open_divs << e
|
|
222
|
-
r = traverse(e)
|
|
223
|
-
@open_divs.pop
|
|
224
|
-
return "<div>#{r}</div>"
|
|
225
|
-
else
|
|
226
|
-
return traverse(e)
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def handle_doc_number(e)
|
|
231
|
-
"<p>%s</p>" % traverse(e)
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
def handle_figure(e)
|
|
235
|
-
"<div class='figure'>%s</div>" % traverse(e)
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
def handle_foreign(e)
|
|
239
|
-
return '' if e.key?('place') and e['place'].include?('foot')
|
|
240
|
-
traverse(e)
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
def handle_g(e, mode)
|
|
244
|
-
# 悉曇字、蘭札體 使用圖檔
|
|
245
|
-
# 如果有對應的 unicode 且不在 Unicode Extension C, D, E 範圍裡,直接採用 unicode
|
|
246
|
-
# 呈現組字式
|
|
247
|
-
gid = e['ref'][1..-1]
|
|
248
|
-
g = @gaijis[gid]
|
|
249
|
-
abort "Line:#{__LINE__} 無缺字資料:#{gid}" if g.nil?
|
|
250
|
-
zzs = g['zzs']
|
|
251
|
-
|
|
252
|
-
if mode == 'txt'
|
|
253
|
-
return g['roman'] if gid.start_with?('SD')
|
|
254
|
-
if zzs.nil?
|
|
255
|
-
abort "缺組字式:#{g}"
|
|
256
|
-
else
|
|
257
|
-
return zzs
|
|
258
|
-
end
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
if gid.start_with?('SD')
|
|
262
|
-
case gid
|
|
263
|
-
when 'SD-E35A'
|
|
264
|
-
return '('
|
|
265
|
-
when 'SD-E35B'
|
|
266
|
-
return ')'
|
|
267
|
-
else
|
|
268
|
-
fn = "#{gid}.gif"
|
|
269
|
-
src = File.join(@config[:graphic_base], 'sd-gif', gid[3..4], fn)
|
|
270
|
-
copy_file(src)
|
|
271
|
-
return "<img src='#{fn}'/>"
|
|
272
|
-
end
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
if gid.start_with?('RJ')
|
|
276
|
-
fn = "#{gid}.gif"
|
|
277
|
-
src = File.join(@config[:graphic_base], 'rj-gif', gid[3..4], fn)
|
|
278
|
-
copy_file(src)
|
|
279
|
-
return "<img src='#{fn}'/>"
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
if g.has_key?('unicode')
|
|
283
|
-
# 如果不在 unicode ext-C, ext-D, ext-E 範圍內
|
|
284
|
-
unless (0x2A700..0x2CEAF).include? g['unicode'].hex
|
|
285
|
-
return g['unicode-char'] # 直接採用 unicode
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
zzs
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
def handle_graphic(e)
|
|
293
|
-
url = e['url']
|
|
294
|
-
url.sub!(/^.*(figures\/.*)$/, '\1')
|
|
295
|
-
|
|
296
|
-
src = File.join(@config[:graphic_base], url)
|
|
297
|
-
copy_file(src)
|
|
298
|
-
|
|
299
|
-
fn = File.basename(src)
|
|
300
|
-
"<img src='#{fn}'/>"
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
def handle_head(e)
|
|
304
|
-
if e['type'] == 'added'
|
|
305
|
-
return ''
|
|
306
|
-
elsif e.parent.name == 'list'
|
|
307
|
-
return traverse(e)
|
|
308
|
-
else
|
|
309
|
-
i = @open_divs.size
|
|
310
|
-
if i <= 6
|
|
311
|
-
return "<p class='h#{i}'>%s</p>" % traverse(e)
|
|
312
|
-
else
|
|
313
|
-
return "<p class='h#{i}'>%s</p>" % traverse(e)
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
def handle_item(e)
|
|
319
|
-
"<li>%s</li>\n" % traverse(e)
|
|
320
|
-
end
|
|
321
|
-
|
|
322
|
-
def handle_juan(e)
|
|
323
|
-
"<p class='juan'>%s</p>" % traverse(e)
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
def handle_l(e)
|
|
327
|
-
if @lg_type == 'abnormal'
|
|
328
|
-
return traverse(e)
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
@in_l = true
|
|
332
|
-
|
|
333
|
-
doc = Nokogiri::XML::Document.new
|
|
334
|
-
cell = doc.create_element('div')
|
|
335
|
-
cell['class'] = 'lg-cell'
|
|
336
|
-
cell.inner_html = traverse(e) + ' '
|
|
337
|
-
|
|
338
|
-
if e.key? 'rend'
|
|
339
|
-
cell['style'] = e['rend']
|
|
340
|
-
elsif @first_l
|
|
341
|
-
parent = e.parent()
|
|
342
|
-
if parent.has_attribute?('rend')
|
|
343
|
-
indent = parent['rend'].scan(/text-indent:[^:]*/)
|
|
344
|
-
unless indent.empty?
|
|
345
|
-
cell['style'] = indent[0]
|
|
346
|
-
end
|
|
347
|
-
end
|
|
348
|
-
end
|
|
349
|
-
@first_l = false
|
|
350
|
-
r = to_html(cell)
|
|
351
|
-
|
|
352
|
-
unless @lg_row_open
|
|
353
|
-
r = "\n<div class='lg-row'>" + r
|
|
354
|
-
@lg_row_open = true
|
|
355
|
-
end
|
|
356
|
-
@in_l = false
|
|
357
|
-
r
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
def handle_lb(e)
|
|
361
|
-
return '' if e['type']=='old'
|
|
362
|
-
|
|
363
|
-
# 卍續藏有 X 跟 R 兩種 lb, 只處理 X
|
|
364
|
-
return '' if e['ed'] != @series
|
|
365
|
-
|
|
366
|
-
r = ''
|
|
367
|
-
if @lg_row_open && !@in_l
|
|
368
|
-
# 每行偈頌放在一個 lg-row 裡面
|
|
369
|
-
# T46n1937, p. 914a01, l 包雙行夾註跨行
|
|
370
|
-
# T20n1092, 337c16, lb 在 l 中間,不結束 lg-row
|
|
371
|
-
r += "</div><!-- end of lg-row -->"
|
|
372
|
-
@lg_row_open = false
|
|
373
|
-
end
|
|
374
|
-
unless @t_buf1.empty? and @t_buf2.empty?
|
|
375
|
-
r += print_tt
|
|
376
|
-
end
|
|
377
|
-
r
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
def handle_lem(e)
|
|
381
|
-
r = nil
|
|
382
|
-
w = e['wit']
|
|
383
|
-
if e.key? 'wit'
|
|
384
|
-
if (w.include? 'CBETA') and (not w.include? @orig)
|
|
385
|
-
r = "<span class='corr'>%s</span>" % traverse(e)
|
|
386
|
-
end
|
|
387
|
-
end
|
|
388
|
-
r = traverse(e) if r.nil?
|
|
389
|
-
r
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
def handle_lg(e)
|
|
393
|
-
r = ''
|
|
394
|
-
@lg_type = e['type']
|
|
395
|
-
if @lg_type == 'abnormal'
|
|
396
|
-
r = "<p class='lg-abnormal'>" + traverse(e) + "</p>"
|
|
397
|
-
else
|
|
398
|
-
@first_l = true
|
|
399
|
-
doc = Nokogiri::XML::Document.new
|
|
400
|
-
node = doc.create_element('div')
|
|
401
|
-
node['class'] = 'lg'
|
|
402
|
-
if e.has_attribute?('rend')
|
|
403
|
-
rend = e['rend'].gsub(/text-indent:[^:]*/, '')
|
|
404
|
-
node['style'] = rend
|
|
405
|
-
end
|
|
406
|
-
@lg_row_open = false
|
|
407
|
-
node.inner_html = traverse(e)
|
|
408
|
-
if @lg_row_open
|
|
409
|
-
node.inner_html += '</div><!-- end of lg -->'
|
|
410
|
-
@lg_row_open = false
|
|
411
|
-
end
|
|
412
|
-
r = "\n" + to_html(node)
|
|
413
|
-
end
|
|
414
|
-
r
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
def handle_list(e)
|
|
418
|
-
doc = Nokogiri::XML::Document.new
|
|
419
|
-
node = doc.create_element('ul')
|
|
420
|
-
if e.key? 'rendition'
|
|
421
|
-
node['class'] = e['rendition']
|
|
422
|
-
end
|
|
423
|
-
node.inner_html = traverse(e)
|
|
424
|
-
to_html(node) + "\n"
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
def handle_milestone(e)
|
|
428
|
-
''
|
|
429
|
-
end
|
|
430
|
-
|
|
431
|
-
def handle_mulu(e)
|
|
432
|
-
return '' if e['type']=='卷'
|
|
433
|
-
@mulu_count += 1
|
|
434
|
-
level = e['level'].to_i
|
|
435
|
-
while @current_nav.size > level
|
|
436
|
-
@current_nav.pop
|
|
437
|
-
end
|
|
438
|
-
|
|
439
|
-
label = traverse(e, 'txt')
|
|
440
|
-
li = @current_nav.last.add_child("<li><a href='#mulu#{@mulu_count}'>#{label}</a></li>").first
|
|
441
|
-
ul = li.add_child('<ul></ul>').first
|
|
442
|
-
@current_nav << ul
|
|
443
|
-
|
|
444
|
-
# mulu 標記裡要有東西,prince 才會產生 pdf bookmark
|
|
445
|
-
"<a id='mulu#{@mulu_count}'></a><mulu#{level} title='#{label}'> </mulu#{level}>"
|
|
446
|
-
end
|
|
447
|
-
|
|
448
|
-
def handle_node(e, mode)
|
|
449
|
-
return '' if e.comment?
|
|
450
|
-
return handle_text(e, mode) if e.text?
|
|
451
|
-
return '' if PASS.include?(e.name)
|
|
452
|
-
r = case e.name
|
|
453
|
-
when 'anchor' then handle_anchor(e)
|
|
454
|
-
when 'app' then handle_app(e)
|
|
455
|
-
when 'byline' then handle_byline(e)
|
|
456
|
-
when 'cell' then handle_cell(e)
|
|
457
|
-
when 'corr' then handle_corr(e)
|
|
458
|
-
when 'docNumber' then handle_doc_number(e)
|
|
459
|
-
when 'div' then handle_div(e)
|
|
460
|
-
when 'figure' then handle_figure(e)
|
|
461
|
-
when 'foreign' then handle_foreign(e)
|
|
462
|
-
when 'g' then handle_g(e, mode)
|
|
463
|
-
when 'graphic' then handle_graphic(e)
|
|
464
|
-
when 'head' then handle_head(e)
|
|
465
|
-
when 'item' then handle_item(e)
|
|
466
|
-
when 'juan' then handle_juan(e)
|
|
467
|
-
when 'l' then handle_l(e)
|
|
468
|
-
when 'lb' then handle_lb(e)
|
|
469
|
-
when 'lem' then handle_lem(e)
|
|
470
|
-
when 'lg' then handle_lg(e)
|
|
471
|
-
when 'list' then handle_list(e)
|
|
472
|
-
when 'mulu' then handle_mulu(e)
|
|
473
|
-
when 'note' then handle_note(e)
|
|
474
|
-
when 'milestone' then handle_milestone(e)
|
|
475
|
-
when 'p' then handle_p(e)
|
|
476
|
-
when 'rdg' then ''
|
|
477
|
-
when 'reg' then ''
|
|
478
|
-
when 'row' then handle_row(e)
|
|
479
|
-
when 'sic' then ''
|
|
480
|
-
when 'sg' then handle_sg(e)
|
|
481
|
-
when 't' then handle_t(e)
|
|
482
|
-
when 'tt' then handle_tt(e)
|
|
483
|
-
when 'table' then handle_table(e)
|
|
484
|
-
when 'unclear' then handle_unclear(e)
|
|
485
|
-
else traverse(e)
|
|
486
|
-
end
|
|
487
|
-
r
|
|
488
|
-
end
|
|
489
|
-
|
|
490
|
-
def handle_note(e)
|
|
491
|
-
if e.has_attribute?('type')
|
|
492
|
-
t = e['type']
|
|
493
|
-
if %w(equivalent orig orig_biao orig_ke mod rest).include? t
|
|
494
|
-
return ''
|
|
495
|
-
end
|
|
496
|
-
return '' if t.start_with?('cf')
|
|
497
|
-
end
|
|
498
|
-
|
|
499
|
-
if e.has_attribute?('resp')
|
|
500
|
-
return '' if e['resp'].start_with? 'CBETA'
|
|
501
|
-
end
|
|
502
|
-
|
|
503
|
-
r = traverse(e)
|
|
504
|
-
if e.has_attribute?('place')
|
|
505
|
-
if e['place']=='inline'
|
|
506
|
-
r = "(#{r})"
|
|
507
|
-
elsif e['place']=='interlinear'
|
|
508
|
-
r = "(#{r})"
|
|
509
|
-
end
|
|
510
|
-
end
|
|
511
|
-
r
|
|
512
|
-
end
|
|
513
|
-
|
|
514
|
-
def handle_p(e)
|
|
515
|
-
doc = Nokogiri::XML::Document.new
|
|
516
|
-
node = doc.create_element('p')
|
|
517
|
-
if e.key? 'rend'
|
|
518
|
-
node['style'] = e['rend']
|
|
519
|
-
end
|
|
520
|
-
node.inner_html = traverse(e)
|
|
521
|
-
to_html(node) + "\n"
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
def handle_row(e)
|
|
525
|
-
"<tr>" + traverse(e) + "</tr>\n"
|
|
526
|
-
end
|
|
527
|
-
|
|
528
|
-
def handle_sg(e)
|
|
529
|
-
'(' + traverse(e) + ')'
|
|
530
|
-
end
|
|
531
|
-
|
|
532
|
-
def handle_sutra(xml_fn)
|
|
533
|
-
puts "convert sutra #{xml_fn}"
|
|
534
|
-
|
|
535
|
-
before_parse_xml(xml_fn)
|
|
536
|
-
|
|
537
|
-
@text = parse_xml(xml_fn)
|
|
538
|
-
|
|
539
|
-
# 目次
|
|
540
|
-
if @config[:back_page_title]
|
|
541
|
-
s = @config[:back_page_title]
|
|
542
|
-
@nav_root.add_child("<li><a href='#back'>#{s}</a></li>")
|
|
543
|
-
end
|
|
544
|
-
@toc = to_html(@nav_root)
|
|
545
|
-
@toc.gsub!('<ul/>', '')
|
|
546
|
-
|
|
547
|
-
if @config.key? :graphic_base
|
|
548
|
-
|
|
549
|
-
end
|
|
550
|
-
|
|
551
|
-
if @config.key? :front_page
|
|
552
|
-
s = File.read(@config[:front_page])
|
|
553
|
-
@front = "<div id='front'>#{s}</div>"
|
|
554
|
-
end
|
|
555
|
-
|
|
556
|
-
if @config.key? :back_page
|
|
557
|
-
s = File.read(@config[:back_page])
|
|
558
|
-
@back = "<div id='back'>#{s}</div>"
|
|
559
|
-
end
|
|
560
|
-
|
|
561
|
-
fn = File.join(CBETA::DATA, 'pdf-template.htm')
|
|
562
|
-
template = File.read(fn)
|
|
563
|
-
output = template % {
|
|
564
|
-
title: @title,
|
|
565
|
-
author: @author,
|
|
566
|
-
toc: @toc,
|
|
567
|
-
front: @front,
|
|
568
|
-
text: @text,
|
|
569
|
-
back: @back
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
fn = File.join(@output_folder_sutra, 'main.htm')
|
|
573
|
-
File.write(fn, output)
|
|
574
|
-
end
|
|
575
|
-
|
|
576
|
-
def handle_t(e)
|
|
577
|
-
if e.has_attribute? 'place'
|
|
578
|
-
return '' if e['place'].include? 'foot'
|
|
579
|
-
end
|
|
580
|
-
r = traverse(e)
|
|
581
|
-
|
|
582
|
-
# <tt type="app"> 不是 悉漢雙行對照
|
|
583
|
-
return r if @tt_type == 'app'
|
|
584
|
-
|
|
585
|
-
# 處理雙行對照
|
|
586
|
-
i = e.xpath('../t').index(e)
|
|
587
|
-
case i
|
|
588
|
-
when 0
|
|
589
|
-
@t_buf1 << r
|
|
590
|
-
when 1
|
|
591
|
-
@t_buf2 << r
|
|
592
|
-
else
|
|
593
|
-
return r
|
|
594
|
-
end
|
|
595
|
-
''
|
|
596
|
-
end
|
|
597
|
-
|
|
598
|
-
def handle_tt(e)
|
|
599
|
-
@tt_type = e['type']
|
|
600
|
-
traverse(e)
|
|
601
|
-
end
|
|
602
|
-
|
|
603
|
-
def handle_table(e)
|
|
604
|
-
"<table>" + traverse(e) + "</table>\n"
|
|
605
|
-
end
|
|
606
|
-
|
|
607
|
-
def handle_text(e, mode)
|
|
608
|
-
s = e.content().chomp
|
|
609
|
-
return '' if s.empty?
|
|
610
|
-
return '' if e.parent.name == 'app'
|
|
611
|
-
|
|
612
|
-
# cbeta xml 文字之間會有多餘的換行
|
|
613
|
-
r = s.gsub(/[\n\r]/, '')
|
|
614
|
-
|
|
615
|
-
# 把 & 轉為 &
|
|
616
|
-
r = CGI.escapeHTML(r)
|
|
617
|
-
|
|
618
|
-
r
|
|
619
|
-
end
|
|
620
|
-
|
|
621
|
-
def handle_unclear(e)
|
|
622
|
-
'▆'
|
|
623
|
-
end
|
|
624
|
-
|
|
625
|
-
def handle_vol(vol)
|
|
626
|
-
puts "convert volumn: #{vol}"
|
|
627
|
-
|
|
628
|
-
@orig = @cbeta.get_canon_abbr(vol[0])
|
|
629
|
-
abort "未處理底本" if @orig.nil?
|
|
630
|
-
puts "#{__LINE__} orig: #{@orig}"
|
|
631
|
-
|
|
632
|
-
@vol = vol
|
|
633
|
-
@series = CBETA.get_canon_from_vol(vol)
|
|
634
|
-
@out_folder = File.join(@out_root, @series, vol)
|
|
635
|
-
FileUtils.remove_dir(@out_folder, true)
|
|
636
|
-
FileUtils::mkdir_p @out_folder
|
|
637
|
-
|
|
638
|
-
source = File.join(@xml_root, @series, vol)
|
|
639
|
-
Dir.entries(source).sort.each { |f|
|
|
640
|
-
next if f.start_with? '.'
|
|
641
|
-
path = File.join(source, f)
|
|
642
|
-
handle_sutra(path)
|
|
643
|
-
}
|
|
644
|
-
end
|
|
645
|
-
|
|
646
|
-
def handle_vols(v1, v2)
|
|
647
|
-
puts "convert volumns: #{v1}..#{v2}"
|
|
648
|
-
@series = CBETA.get_canon_from_vol(v1)
|
|
649
|
-
folder = File.join(@xml_root, @series)
|
|
650
|
-
Dir.foreach(folder) { |vol|
|
|
651
|
-
next if vol < v1
|
|
652
|
-
next if vol > v2
|
|
653
|
-
handle_vol(vol)
|
|
654
|
-
}
|
|
655
|
-
end
|
|
656
|
-
|
|
657
|
-
def open_xml(fn)
|
|
658
|
-
s = File.read(fn)
|
|
659
|
-
|
|
660
|
-
if fn.include? 'T16n0657'
|
|
661
|
-
# 這個地方 雙行夾註 跨兩行偈頌
|
|
662
|
-
# 把 lb 移到 note 結束之前
|
|
663
|
-
# 讓 lg-row 先結束,再結束雙行夾註
|
|
664
|
-
s.sub!(/(<\/note>)(\n<lb n="0206b29" ed="T"\/>)/, '\2\1')
|
|
665
|
-
end
|
|
666
|
-
|
|
667
|
-
doc = Nokogiri::XML(s)
|
|
668
|
-
doc.remove_namespaces!()
|
|
669
|
-
doc
|
|
670
|
-
end
|
|
671
|
-
|
|
672
|
-
def parse_xml(xml_fn)
|
|
673
|
-
@pass = [false]
|
|
674
|
-
|
|
675
|
-
doc = open_xml(xml_fn)
|
|
676
|
-
|
|
677
|
-
e = doc.xpath("//titleStmt/title")[0]
|
|
678
|
-
@title = traverse(e, 'txt')
|
|
679
|
-
@title = @title.split()[-1]
|
|
680
|
-
|
|
681
|
-
@author = doc.at_xpath("//titleStmt/author").text
|
|
682
|
-
|
|
683
|
-
if @cover.nil?
|
|
684
|
-
@cover = "<p class='title'>#{@title}</p>\n"
|
|
685
|
-
@cover += "<p class='author'>#{@author}</p>"
|
|
686
|
-
end
|
|
687
|
-
|
|
688
|
-
e = doc.at_xpath("//editionStmt/edition/date")
|
|
689
|
-
abort "找不到版本日期" if e.nil?
|
|
690
|
-
@edition_date = e.text.sub(/\$Date: (.*?) \$$/, '\1')
|
|
691
|
-
|
|
692
|
-
e = doc.at_xpath("//projectDesc/p[@lang='zh']")
|
|
693
|
-
abort "找不到貢獻者" if e.nil?
|
|
694
|
-
@contributors = e.text
|
|
695
|
-
|
|
696
|
-
root = doc.root()
|
|
697
|
-
body = root.xpath("text/body")[0]
|
|
698
|
-
@pass = [true]
|
|
699
|
-
|
|
700
|
-
text = traverse(body)
|
|
701
|
-
text
|
|
702
|
-
end
|
|
703
|
-
|
|
704
|
-
def print_tt
|
|
705
|
-
r = "<table class='tt'>\n"
|
|
706
|
-
|
|
707
|
-
r += "<tr>\n"
|
|
708
|
-
@t_buf1.each do |s|
|
|
709
|
-
r += "<td>#{s}</td>"
|
|
710
|
-
end
|
|
711
|
-
r += "</tr>\n"
|
|
712
|
-
|
|
713
|
-
r += "<tr>\n"
|
|
714
|
-
@t_buf2.each do |s|
|
|
715
|
-
r += "<td>#{s}</td>"
|
|
716
|
-
end
|
|
717
|
-
r += "</tr>\n"
|
|
718
|
-
|
|
719
|
-
@t_buf1 = []
|
|
720
|
-
@t_buf2 = []
|
|
721
|
-
|
|
722
|
-
r + "<table>\n"
|
|
723
|
-
end
|
|
724
|
-
|
|
725
|
-
def prepare_work_list(input_folder)
|
|
726
|
-
Dir.foreach(input_folder) do |f|
|
|
727
|
-
next if f.start_with? '.'
|
|
728
|
-
p1 = File.join(input_folder, f)
|
|
729
|
-
if File.file?(p1)
|
|
730
|
-
work = f.sub(/^([A-Z]{1,2})\d{2,3}n(.*)\.xml$/, '\1\2')
|
|
731
|
-
work = 'T0220' if work.start_with? 'T0220'
|
|
732
|
-
unless @works.key? work
|
|
733
|
-
@works[work] = []
|
|
734
|
-
end
|
|
735
|
-
@works[work] << p1
|
|
736
|
-
else
|
|
737
|
-
prepare_work_list(p1)
|
|
738
|
-
end
|
|
739
|
-
end
|
|
740
|
-
end
|
|
741
|
-
|
|
742
|
-
def traverse(e, mode='html')
|
|
743
|
-
r = ''
|
|
744
|
-
e.children.each { |c|
|
|
745
|
-
s = handle_node(c, mode)
|
|
746
|
-
r += s
|
|
747
|
-
}
|
|
748
|
-
r
|
|
749
|
-
end
|
|
750
|
-
|
|
751
|
-
end
|