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
data/lib/cbeta/p5a_to_html.rb
DELETED
|
@@ -1,813 +0,0 @@
|
|
|
1
|
-
require 'cgi'
|
|
2
|
-
require 'date'
|
|
3
|
-
require 'fileutils'
|
|
4
|
-
require 'json'
|
|
5
|
-
require 'nokogiri'
|
|
6
|
-
require 'set'
|
|
7
|
-
require_relative 'cbeta_share'
|
|
8
|
-
|
|
9
|
-
# Convert CBETA XML P5a to HTML
|
|
10
|
-
#
|
|
11
|
-
# CBETA XML P5a 可由此取得: https://github.com/cbeta-git/xml-p5a
|
|
12
|
-
#
|
|
13
|
-
# 轉檔規則請參考: http://wiki.ddbc.edu.tw/pages/CBETA_XML_P5a_轉_HTML
|
|
14
|
-
class CBETA::P5aToHTML
|
|
15
|
-
# 內容不輸出的元素
|
|
16
|
-
PASS=['back', 'teiHeader']
|
|
17
|
-
|
|
18
|
-
# 某版用字缺的符號
|
|
19
|
-
MISSING = '-'
|
|
20
|
-
|
|
21
|
-
private_constant :PASS, :MISSING
|
|
22
|
-
|
|
23
|
-
# @param xml_root [String] 來源 CBETA XML P5a 路徑
|
|
24
|
-
# @param out_root [String] 輸出 HTML 路徑
|
|
25
|
-
def initialize(xml_root, out_root)
|
|
26
|
-
@xml_root = xml_root
|
|
27
|
-
@out_root = out_root
|
|
28
|
-
@cbeta = CBETA.new
|
|
29
|
-
@gaijis = CBETA::Gaiji.new
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# 將 CBETA XML P5a 轉為 HTML
|
|
33
|
-
#
|
|
34
|
-
# @example for convert 大正藏第一冊:
|
|
35
|
-
#
|
|
36
|
-
# x2h = CBETA::P5aToHTML.new('/PATH/TO/CBETA/XML/P5a', '/OUTPUT/FOLDER')
|
|
37
|
-
# x2h.convert('T01')
|
|
38
|
-
#
|
|
39
|
-
# @example for convert 大正藏全部:
|
|
40
|
-
#
|
|
41
|
-
# x2h = CBETA::P5aToHTML.new('/PATH/TO/CBETA/XML/P5a', '/OUTPUT/FOLDER')
|
|
42
|
-
# x2h.convert('T')
|
|
43
|
-
#
|
|
44
|
-
# @example for convert 大正藏第五冊至第七冊:
|
|
45
|
-
#
|
|
46
|
-
# x2h = CBETA::P5aToHTML.new('/PATH/TO/CBETA/XML/P5a', '/OUTPUT/FOLDER')
|
|
47
|
-
# x2h.convert('T05..T07')
|
|
48
|
-
#
|
|
49
|
-
# T 是大正藏的 ID, CBETA 的藏經 ID 系統請參考: http://www.cbeta.org/format/id.php
|
|
50
|
-
def convert(target=nil)
|
|
51
|
-
return convert_all if target.nil?
|
|
52
|
-
|
|
53
|
-
arg = target.upcase
|
|
54
|
-
if arg.size == 1
|
|
55
|
-
handle_collection(arg)
|
|
56
|
-
else
|
|
57
|
-
if arg.include? '..'
|
|
58
|
-
arg.match(/^([^\.]+?)\.\.([^\.]+)$/) {
|
|
59
|
-
handle_vols($1, $2)
|
|
60
|
-
}
|
|
61
|
-
else
|
|
62
|
-
handle_vol(arg)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
private
|
|
68
|
-
|
|
69
|
-
include CbetaShare
|
|
70
|
-
|
|
71
|
-
def convert_all
|
|
72
|
-
Dir.foreach(@xml_root) { |c|
|
|
73
|
-
next unless c.match(/^[A-Z]$/)
|
|
74
|
-
handle_collection(c)
|
|
75
|
-
}
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def e_anchor(e)
|
|
79
|
-
id = e['id']
|
|
80
|
-
if e.has_attribute?('id')
|
|
81
|
-
if id.start_with?('nkr_note_orig')
|
|
82
|
-
note = @notes[id]
|
|
83
|
-
note_text = traverse(note)
|
|
84
|
-
n = id[/^nkr_note_orig_(.*)$/, 1]
|
|
85
|
-
@back[@juan] += "<span class='footnote' id='n#{n}'>#{note_text}</span>\n"
|
|
86
|
-
return "<a class='noteAnchor' href='#n#{n}'></a>"
|
|
87
|
-
elsif id.start_with? 'fx'
|
|
88
|
-
return "<span class='star'>[*]</span>"
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
if e.has_attribute?('type')
|
|
93
|
-
if e['type'] == 'circle'
|
|
94
|
-
return '◎'
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
''
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def e_app(e)
|
|
102
|
-
r = ''
|
|
103
|
-
if e['type'] == 'star'
|
|
104
|
-
c = e['corresp'][1..-1]
|
|
105
|
-
r = "<a class='noteAnchor star' href='#n#{c}'></a>"
|
|
106
|
-
end
|
|
107
|
-
r + traverse(e)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def e_byline(e)
|
|
111
|
-
r = '<p class="byline">'
|
|
112
|
-
r += "<span class='lineInfo' line='#{@lb}'></span>"
|
|
113
|
-
r += traverse(e)
|
|
114
|
-
r + '</p>'
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def e_cell(e)
|
|
118
|
-
doc = Nokogiri::XML::Document.new
|
|
119
|
-
cell = doc.create_element('div')
|
|
120
|
-
cell['class'] = 'bip-table-cell'
|
|
121
|
-
cell['rowspan'] = e['rows'] if e.key? 'rows'
|
|
122
|
-
cell['colspan'] = e['cols'] if e.key? 'cols'
|
|
123
|
-
cell.inner_html = traverse(e)
|
|
124
|
-
to_html(cell)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def e_corr(e)
|
|
128
|
-
r = ''
|
|
129
|
-
if e.parent.name == 'choice'
|
|
130
|
-
sic = e.parent.at_xpath('sic')
|
|
131
|
-
unless sic.nil?
|
|
132
|
-
@dila_note += 1
|
|
133
|
-
r = "<a class='noteAnchor dila' href='#dila_note#{@dila_note}'></a>"
|
|
134
|
-
|
|
135
|
-
note = @orig
|
|
136
|
-
sic_text = traverse(sic, 'back')
|
|
137
|
-
if sic_text.empty?
|
|
138
|
-
note += MISSING
|
|
139
|
-
else
|
|
140
|
-
note += sic_text
|
|
141
|
-
end
|
|
142
|
-
@back[@juan] += "<span class='footnote_dila' id='dila_note#{@dila_note}'>#{note}</span>\n"
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
r + "<span class='cbeta'>%s</span>" % traverse(e)
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def e_div(e)
|
|
149
|
-
@div_count += 1
|
|
150
|
-
n = @div_count
|
|
151
|
-
if e.has_attribute? 'type'
|
|
152
|
-
@open_divs << e
|
|
153
|
-
r = traverse(e)
|
|
154
|
-
@open_divs.pop
|
|
155
|
-
return "<!-- begin div#{n}--><div class='div-#{e['type']}'>#{r}</div><!-- end of div#{n} -->"
|
|
156
|
-
else
|
|
157
|
-
return traverse(e)
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def e_figure(e)
|
|
162
|
-
"<p class='figure'>%s</p>" % traverse(e)
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def e_foreign(e)
|
|
166
|
-
return '' if e.key?('place') and e['place'].include?('foot')
|
|
167
|
-
traverse(e)
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def e_g(e, mode)
|
|
171
|
-
# if 有 <mapping type="unicode">
|
|
172
|
-
# if 不在 Unicode Extension C, D, E 範圍裡
|
|
173
|
-
# 直接採用
|
|
174
|
-
# else
|
|
175
|
-
# 預設呈現 unicode, 但仍包缺字資訊,供點選開 popup
|
|
176
|
-
# else if 有 <mapping type="normal_unicode">
|
|
177
|
-
# 預設呈現 normal_unicode, 但仍包缺字資訊,供點選開 popup
|
|
178
|
-
# else if 有 normalized form
|
|
179
|
-
# 預設呈現 normalized form, 但仍包缺字資訊,供點選開 popup
|
|
180
|
-
# else
|
|
181
|
-
# 預設呈現組字式, 但仍包缺字資訊,供點選開 popup
|
|
182
|
-
gid = e['ref'][1..-1]
|
|
183
|
-
g = @gaijis[gid]
|
|
184
|
-
abort "Line:#{__LINE__} 無缺字資料:#{gid}" if g.nil?
|
|
185
|
-
zzs = g['zzs']
|
|
186
|
-
|
|
187
|
-
if mode == 'txt'
|
|
188
|
-
return g['roman'] if gid.start_with?('SD')
|
|
189
|
-
if zzs.nil?
|
|
190
|
-
abort "缺組字式:#{g}"
|
|
191
|
-
else
|
|
192
|
-
return zzs
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
@char_count += 1
|
|
197
|
-
|
|
198
|
-
if gid.start_with?('SD')
|
|
199
|
-
case gid
|
|
200
|
-
when 'SD-E35A'
|
|
201
|
-
return '('
|
|
202
|
-
when 'SD-E35B'
|
|
203
|
-
return ')'
|
|
204
|
-
else
|
|
205
|
-
return "<span class='siddam' roman='#{g['roman']}' code='#{gid}' char='#{g['sd-char']}'/>"
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
if gid.start_with?('RJ')
|
|
210
|
-
return "<span class='ranja' roman='#{g['roman']}' code='#{gid}' char='#{g['rj-char']}'/>"
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
default = ''
|
|
214
|
-
if g.has_key?('unicode')
|
|
215
|
-
#if @unicode1.include?(g['unicode'])
|
|
216
|
-
# 如果在 unicode ext-C, ext-D, ext-E 範圍內
|
|
217
|
-
if (0x2A700..0x2CEAF).include? g['unicode'].hex
|
|
218
|
-
default = g['unicode-char']
|
|
219
|
-
else
|
|
220
|
-
return g['unicode-char'] # 直接採用 unicode
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
nor = ''
|
|
225
|
-
if g.has_key?('normal_unicode')
|
|
226
|
-
nor = g['normal_unicode']
|
|
227
|
-
default = nor if default.empty?
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
if g.has_key?('normal')
|
|
231
|
-
nor += ', ' unless nor==''
|
|
232
|
-
nor += g['normal']
|
|
233
|
-
default = g['normal'] if default.empty?
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
default = zzs if default.empty?
|
|
237
|
-
|
|
238
|
-
href = 'http://dict.cbeta.org/dict_word/gaiji-cb/%s/%s.gif' % [gid[2, 2], gid]
|
|
239
|
-
unless @back[@juan].include?(href)
|
|
240
|
-
@back[@juan] += "<span id='#{gid}' class='gaijiInfo' figure_url='#{href}' zzs='#{zzs}' nor='#{nor}'>#{default}</span>\n"
|
|
241
|
-
end
|
|
242
|
-
"<a class='gaijiAnchor' href='##{gid}'>#{default}</a>"
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def e_graphic(e)
|
|
246
|
-
url = File.basename(e['url'])
|
|
247
|
-
"<span imgsrc='#{url}' class='graphic'></span>"
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
def e_head(e)
|
|
251
|
-
r = ''
|
|
252
|
-
unless e['type'] == 'added'
|
|
253
|
-
i = @open_divs.size
|
|
254
|
-
r = "<p class='head' data-head-level='#{i}'>%s</p>" % traverse(e)
|
|
255
|
-
end
|
|
256
|
-
r
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def e_item(e)
|
|
260
|
-
"<li>%s</li>\n" % traverse(e)
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
def e_juan(e)
|
|
264
|
-
"<p class='juan'>%s</p>" % traverse(e)
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
def e_l(e)
|
|
268
|
-
if @lg_type == 'abnormal'
|
|
269
|
-
return traverse(e)
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
@in_l = true
|
|
273
|
-
|
|
274
|
-
doc = Nokogiri::XML::Document.new
|
|
275
|
-
cell = doc.create_element('div')
|
|
276
|
-
cell['class'] = 'lg-cell'
|
|
277
|
-
cell.inner_html = traverse(e)
|
|
278
|
-
|
|
279
|
-
if e.key? 'rend'
|
|
280
|
-
cell['style'] = e['rend']
|
|
281
|
-
elsif @first_l
|
|
282
|
-
parent = e.parent()
|
|
283
|
-
if parent.has_attribute?('rend')
|
|
284
|
-
indent = parent['rend'].scan(/text-indent:[^:]*/)
|
|
285
|
-
unless indent.empty?
|
|
286
|
-
cell['style'] = indent[0]
|
|
287
|
-
end
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
@first_l = false
|
|
291
|
-
|
|
292
|
-
r = to_html(cell)
|
|
293
|
-
|
|
294
|
-
unless @lg_row_open
|
|
295
|
-
r = "\n<div class='lg-row'>" + r
|
|
296
|
-
@lg_row_open = true
|
|
297
|
-
end
|
|
298
|
-
@in_l = false
|
|
299
|
-
r
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
def e_lb(e)
|
|
303
|
-
return '' if e['type']=='old'
|
|
304
|
-
|
|
305
|
-
# 卍續藏有 X 跟 R 兩種 lb, 只處理 X
|
|
306
|
-
return '' if e['ed'] != @series
|
|
307
|
-
|
|
308
|
-
@char_count = 1
|
|
309
|
-
@lb = e['n']
|
|
310
|
-
line_head = CBETA.get_linehead(@sutra_no, @lb)
|
|
311
|
-
|
|
312
|
-
r = ''
|
|
313
|
-
#if e.parent.name == 'lg' and $lg_row_open
|
|
314
|
-
if @lg_row_open && !@in_l
|
|
315
|
-
# 每行偈頌放在一個 lg-row 裡面
|
|
316
|
-
# T46n1937, p. 914a01, l 包雙行夾註跨行
|
|
317
|
-
# T20n1092, 337c16, lb 在 l 中間,不結束 lg-row
|
|
318
|
-
r += "</div><!-- end of lg-row -->"
|
|
319
|
-
@lg_row_open = false
|
|
320
|
-
end
|
|
321
|
-
r += "<span class='lb' \nid='#{line_head}'>#{line_head}</span>"
|
|
322
|
-
unless @next_line_buf.empty?
|
|
323
|
-
r += @next_line_buf
|
|
324
|
-
@next_line_buf = ''
|
|
325
|
-
end
|
|
326
|
-
r
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
def e_lem(e)
|
|
330
|
-
r = ''
|
|
331
|
-
w = e['wit']
|
|
332
|
-
if w.include? 'CBETA' and not w.include? @orig
|
|
333
|
-
@dila_note += 1
|
|
334
|
-
r = "<a class='noteAnchor dila' href='#dila_note#{@dila_note}'></a>"
|
|
335
|
-
r += "<span class='cbeta'>%s</span>" % traverse(e)
|
|
336
|
-
|
|
337
|
-
note = lem_note_cf(e)
|
|
338
|
-
note += lem_note_rdg(e)
|
|
339
|
-
@back[@juan] += "<span class='footnote_dila' id='dila_note#{@dila_note}'>#{note}</span>\n"
|
|
340
|
-
else
|
|
341
|
-
r = traverse(e)
|
|
342
|
-
end
|
|
343
|
-
r
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
def e_lg(e)
|
|
347
|
-
r = ''
|
|
348
|
-
@lg_type = e['type']
|
|
349
|
-
if @lg_type == 'abnormal'
|
|
350
|
-
r = "<p class='lg-abnormal'>" + traverse(e) + "</p>"
|
|
351
|
-
else
|
|
352
|
-
@first_l = true
|
|
353
|
-
doc = Nokogiri::XML::Document.new
|
|
354
|
-
node = doc.create_element('div')
|
|
355
|
-
node['class'] = 'lg'
|
|
356
|
-
if e.has_attribute?('rend')
|
|
357
|
-
rend = e['rend'].gsub(/text-indent:[^:]*/, '')
|
|
358
|
-
node['style'] = rend
|
|
359
|
-
end
|
|
360
|
-
@lg_row_open = false
|
|
361
|
-
node.inner_html = traverse(e)
|
|
362
|
-
if @lg_row_open
|
|
363
|
-
node.inner_html += '</div><!-- end of lg -->'
|
|
364
|
-
@lg_row_open = false
|
|
365
|
-
end
|
|
366
|
-
r = "\n" + to_html(node)
|
|
367
|
-
end
|
|
368
|
-
r
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
def e_list(e)
|
|
372
|
-
"<ul>%s</ul>" % traverse(e)
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
def e_milestone(e)
|
|
376
|
-
r = ''
|
|
377
|
-
if e['unit'] == 'juan'
|
|
378
|
-
|
|
379
|
-
r += "</div>" * @open_divs.size # 如果有 div 跨卷,要先結束, ex: T55n2154, p. 680a29, 跨 19, 20 兩卷
|
|
380
|
-
@juan = e['n'].to_i
|
|
381
|
-
@back[@juan] = @back[0]
|
|
382
|
-
r += "<juan #{@juan}>"
|
|
383
|
-
@open_divs.each { |d|
|
|
384
|
-
r += "<div class='div-#{d['type']}'>"
|
|
385
|
-
}
|
|
386
|
-
end
|
|
387
|
-
r
|
|
388
|
-
end
|
|
389
|
-
|
|
390
|
-
def e_mulu(e)
|
|
391
|
-
r = ''
|
|
392
|
-
if e['type'] == '品'
|
|
393
|
-
@pass << false
|
|
394
|
-
r = "<mulu class='pin' s='%s'/>" % traverse(e, 'txt')
|
|
395
|
-
@pass.pop
|
|
396
|
-
end
|
|
397
|
-
r
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
def e_note(e)
|
|
401
|
-
n = e['n']
|
|
402
|
-
if e.has_attribute?('type')
|
|
403
|
-
t = e['type']
|
|
404
|
-
case t
|
|
405
|
-
when 'equivalent'
|
|
406
|
-
return ''
|
|
407
|
-
when 'orig'
|
|
408
|
-
return handle_note_orig(e)
|
|
409
|
-
when 'orig_biao'
|
|
410
|
-
return handle_note_orig(e, 'biao')
|
|
411
|
-
when 'orig_ke'
|
|
412
|
-
return handle_note_orig(e, 'ke')
|
|
413
|
-
when 'mod'
|
|
414
|
-
@pass << false
|
|
415
|
-
s = traverse(e)
|
|
416
|
-
@pass.pop
|
|
417
|
-
@back[@juan] += "<span class='footnote cb' id='n#{n}'>#{s}</span>\n"
|
|
418
|
-
return "<a class='noteAnchor cb' href='#n#{n}'></a>"
|
|
419
|
-
when 'rest'
|
|
420
|
-
return ''
|
|
421
|
-
else
|
|
422
|
-
return '' if t.start_with?('cf')
|
|
423
|
-
end
|
|
424
|
-
end
|
|
425
|
-
|
|
426
|
-
if e.has_attribute?('resp')
|
|
427
|
-
return '' if e['resp'].start_with? 'CBETA'
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
r = traverse(e)
|
|
431
|
-
if e.has_attribute?('place')
|
|
432
|
-
if e['place']=='inline'
|
|
433
|
-
r = "<span class='doube-line-note'>#{r}</span>"
|
|
434
|
-
elsif e['place']=='interlinear'
|
|
435
|
-
r = "<span class='interlinear-note'>#{r}</span>"
|
|
436
|
-
end
|
|
437
|
-
end
|
|
438
|
-
r
|
|
439
|
-
end
|
|
440
|
-
|
|
441
|
-
def e_p(e)
|
|
442
|
-
if e.key? 'type'
|
|
443
|
-
r = "<p class='%s'>" % e['type']
|
|
444
|
-
else
|
|
445
|
-
r = '<p>'
|
|
446
|
-
end
|
|
447
|
-
r += "<span class='lineInfo' line='#{@lb}'></span>"
|
|
448
|
-
r += traverse(e)
|
|
449
|
-
r + '</p>'
|
|
450
|
-
end
|
|
451
|
-
|
|
452
|
-
def e_row(e)
|
|
453
|
-
"<div class='bip-table-row'>" + traverse(e) + "</div>"
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
def e_sg(e)
|
|
457
|
-
'(' + traverse(e) + ')'
|
|
458
|
-
end
|
|
459
|
-
|
|
460
|
-
def e_t(e)
|
|
461
|
-
if e.has_attribute? 'place'
|
|
462
|
-
return '' if e['place'].include? 'foot'
|
|
463
|
-
end
|
|
464
|
-
r = traverse(e)
|
|
465
|
-
|
|
466
|
-
# <tt type="app"> 不是 悉漢雙行對照
|
|
467
|
-
return r if @tt_type == 'app'
|
|
468
|
-
|
|
469
|
-
# 處理雙行對照
|
|
470
|
-
i = e.xpath('../t').index(e)
|
|
471
|
-
case i
|
|
472
|
-
when 0
|
|
473
|
-
return r + ' '
|
|
474
|
-
when 1
|
|
475
|
-
@next_line_buf += r + ' '
|
|
476
|
-
return ''
|
|
477
|
-
else
|
|
478
|
-
return r
|
|
479
|
-
end
|
|
480
|
-
end
|
|
481
|
-
|
|
482
|
-
def e_tt(e)
|
|
483
|
-
@tt_type = e['type']
|
|
484
|
-
traverse(e)
|
|
485
|
-
end
|
|
486
|
-
|
|
487
|
-
def e_table(e)
|
|
488
|
-
"<div class='bip-table'>" + traverse(e) + "</div>"
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
def e_unclear(e)
|
|
492
|
-
'▆'
|
|
493
|
-
end
|
|
494
|
-
|
|
495
|
-
def handle_collection(c)
|
|
496
|
-
@series = c
|
|
497
|
-
puts 'handle_collection ' + c
|
|
498
|
-
folder = File.join(@xml_root, @series)
|
|
499
|
-
Dir.entries(folder).sort.each { |vol|
|
|
500
|
-
next if ['.', '..', '.DS_Store'].include? vol
|
|
501
|
-
handle_vol(vol)
|
|
502
|
-
}
|
|
503
|
-
end
|
|
504
|
-
|
|
505
|
-
def handle_node(e, mode)
|
|
506
|
-
return '' if e.comment?
|
|
507
|
-
return handle_text(e, mode) if e.text?
|
|
508
|
-
return '' if PASS.include?(e.name)
|
|
509
|
-
r = case e.name
|
|
510
|
-
when 'anchor' then e_anchor(e)
|
|
511
|
-
when 'app' then e_app(e)
|
|
512
|
-
when 'byline' then e_byline(e)
|
|
513
|
-
when 'cell' then e_cell(e)
|
|
514
|
-
when 'corr' then e_corr(e)
|
|
515
|
-
when 'div' then e_div(e)
|
|
516
|
-
when 'figure' then e_figure(e)
|
|
517
|
-
when 'foreign' then e_foreign(e)
|
|
518
|
-
when 'g' then e_g(e, mode)
|
|
519
|
-
when 'graphic' then e_graphic(e)
|
|
520
|
-
when 'head' then e_head(e)
|
|
521
|
-
when 'item' then e_item(e)
|
|
522
|
-
when 'juan' then e_juan(e)
|
|
523
|
-
when 'l' then e_l(e)
|
|
524
|
-
when 'lb' then e_lb(e)
|
|
525
|
-
when 'lem' then e_lem(e)
|
|
526
|
-
when 'lg' then e_lg(e)
|
|
527
|
-
when 'list' then e_list(e)
|
|
528
|
-
when 'mulu' then e_mulu(e)
|
|
529
|
-
when 'note' then e_note(e)
|
|
530
|
-
when 'milestone' then e_milestone(e)
|
|
531
|
-
when 'p' then e_p(e)
|
|
532
|
-
when 'rdg' then ''
|
|
533
|
-
when 'reg' then ''
|
|
534
|
-
when 'row' then e_row(e)
|
|
535
|
-
when 'sic' then ''
|
|
536
|
-
when 'sg' then e_sg(e)
|
|
537
|
-
when 't' then e_t(e)
|
|
538
|
-
when 'tt' then e_tt(e)
|
|
539
|
-
when 'table' then e_table(e)
|
|
540
|
-
when 'unclear' then e_unclear(e)
|
|
541
|
-
else traverse(e)
|
|
542
|
-
end
|
|
543
|
-
r
|
|
544
|
-
end
|
|
545
|
-
|
|
546
|
-
def handle_note_orig(e, anchor_type=nil)
|
|
547
|
-
n = e['n']
|
|
548
|
-
@pass << false
|
|
549
|
-
s = traverse(e)
|
|
550
|
-
@pass.pop
|
|
551
|
-
|
|
552
|
-
c = @series
|
|
553
|
-
|
|
554
|
-
# 如果 CBETA 沒有修訂,就跟底本的註一樣
|
|
555
|
-
c += " cb" unless @mod_notes.include? n
|
|
556
|
-
|
|
557
|
-
@back[@juan] += "<span class='footnote #{c}' id='n#{n}'>#{s}</span>\n"
|
|
558
|
-
|
|
559
|
-
label = case anchor_type
|
|
560
|
-
when 'biao' then " data-label='標#{n[-2..-1]}'"
|
|
561
|
-
when 'ke' then " data-label='科#{n[-2..-1]}'"
|
|
562
|
-
else ''
|
|
563
|
-
end
|
|
564
|
-
|
|
565
|
-
return "<a class='noteAnchor #{c}' href='#n#{n}'#{label}></a>"
|
|
566
|
-
end
|
|
567
|
-
|
|
568
|
-
def handle_sutra(xml_fn)
|
|
569
|
-
puts "convert sutra #{xml_fn}"
|
|
570
|
-
@back = { 0 => '' }
|
|
571
|
-
@char_count = 1
|
|
572
|
-
@dila_note = 0
|
|
573
|
-
@div_count = 0
|
|
574
|
-
@in_l = false
|
|
575
|
-
@juan = 0
|
|
576
|
-
@lg_row_open = false
|
|
577
|
-
@mod_notes = Set.new
|
|
578
|
-
@next_line_buf = ''
|
|
579
|
-
@open_divs = []
|
|
580
|
-
@sutra_no = File.basename(xml_fn, ".xml")
|
|
581
|
-
|
|
582
|
-
if @sutra_no.match(/^(T05|T06|T07)n0220/)
|
|
583
|
-
@sutra_no = "#{$1}n0220"
|
|
584
|
-
end
|
|
585
|
-
|
|
586
|
-
text = parse_xml(xml_fn)
|
|
587
|
-
|
|
588
|
-
# 註標移到 lg-cell 裡面,不然以 table 呈現 lg 會有問題
|
|
589
|
-
text.gsub!(/(<a class='noteAnchor'[^>]*><\/a>)(<div class="lg-cell"[^>]*>)/, '\2\1')
|
|
590
|
-
|
|
591
|
-
juans = text.split(/(<juan \d+>)/)
|
|
592
|
-
juan_no = nil
|
|
593
|
-
buf = ''
|
|
594
|
-
# 一卷一檔
|
|
595
|
-
juans.each { |j|
|
|
596
|
-
if j =~ /<juan (\d+)>$/
|
|
597
|
-
juan_no = $1.to_i
|
|
598
|
-
elsif juan_no.nil?
|
|
599
|
-
buf = j
|
|
600
|
-
else
|
|
601
|
-
write_juan(juan_no, buf+j)
|
|
602
|
-
end
|
|
603
|
-
}
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
def handle_text(e, mode)
|
|
607
|
-
s = e.content().chomp
|
|
608
|
-
return '' if s.empty?
|
|
609
|
-
return '' if e.parent.name == 'app'
|
|
610
|
-
|
|
611
|
-
# cbeta xml 文字之間會有多餘的換行
|
|
612
|
-
r = s.gsub(/[\n\r]/, '')
|
|
613
|
-
|
|
614
|
-
# 把 & 轉為 &
|
|
615
|
-
r = CGI.escapeHTML(r)
|
|
616
|
-
|
|
617
|
-
# 正文區的文字外面要包 span
|
|
618
|
-
if @pass.last and mode=='html'
|
|
619
|
-
r = "<span class='t' l='#{@lb}' w='#{@char_count}'>#{r}</span>"
|
|
620
|
-
@char_count += r.size
|
|
621
|
-
end
|
|
622
|
-
r
|
|
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
|
-
|
|
631
|
-
@vol = vol
|
|
632
|
-
@series = CBETA.get_canon_from_vol(vol)
|
|
633
|
-
@out_folder = File.join(@out_root, @series, vol)
|
|
634
|
-
FileUtils.remove_dir(@out_folder, true)
|
|
635
|
-
FileUtils::mkdir_p @out_folder
|
|
636
|
-
|
|
637
|
-
source = File.join(@xml_root, @series, vol)
|
|
638
|
-
Dir[source+"/*"].each { |f|
|
|
639
|
-
handle_sutra(f)
|
|
640
|
-
}
|
|
641
|
-
end
|
|
642
|
-
|
|
643
|
-
def handle_vols(v1, v2)
|
|
644
|
-
puts "convert volumns: #{v1}..#{v2}"
|
|
645
|
-
@series = CBETA.get_canon_from_vol(v1)
|
|
646
|
-
folder = File.join(@xml_root, @series)
|
|
647
|
-
Dir.foreach(folder) { |vol|
|
|
648
|
-
next if vol < v1
|
|
649
|
-
next if vol > v2
|
|
650
|
-
handle_vol(vol)
|
|
651
|
-
}
|
|
652
|
-
end
|
|
653
|
-
|
|
654
|
-
def lem_note_cf(e)
|
|
655
|
-
# ex: T32n1670A.xml, p. 703a16
|
|
656
|
-
# <note type="cf1">K30n1002_p0257a01-a23</note>
|
|
657
|
-
refs = []
|
|
658
|
-
e.xpath('./note').each { |n|
|
|
659
|
-
if n.key?('type') and n['type'].start_with? 'cf'
|
|
660
|
-
s = n.content
|
|
661
|
-
if linehead_exist_in_cbeta(s)
|
|
662
|
-
s = "<span class='note_cf'>#{s}</span>"
|
|
663
|
-
end
|
|
664
|
-
refs << s
|
|
665
|
-
end
|
|
666
|
-
}
|
|
667
|
-
if refs.empty?
|
|
668
|
-
''
|
|
669
|
-
else
|
|
670
|
-
'修訂依據:' + refs.join(';') + '。'
|
|
671
|
-
end
|
|
672
|
-
end
|
|
673
|
-
|
|
674
|
-
def lem_note_rdg(lem)
|
|
675
|
-
r = ''
|
|
676
|
-
app = lem.parent
|
|
677
|
-
@pass << false
|
|
678
|
-
app.xpath('rdg').each { |rdg|
|
|
679
|
-
if rdg['wit'].include? @orig
|
|
680
|
-
s = traverse(rdg, 'back')
|
|
681
|
-
s = MISSING if s.empty?
|
|
682
|
-
r += @orig + s
|
|
683
|
-
end
|
|
684
|
-
}
|
|
685
|
-
@pass.pop
|
|
686
|
-
r += '。' unless r.empty?
|
|
687
|
-
r
|
|
688
|
-
end
|
|
689
|
-
|
|
690
|
-
def linehead_exist_in_cbeta(s)
|
|
691
|
-
fn = CBETA.linehead_to_xml_file_path(s)
|
|
692
|
-
return false if fn.nil?
|
|
693
|
-
|
|
694
|
-
path = File.join(@xml_root, fn)
|
|
695
|
-
File.exist? path
|
|
696
|
-
end
|
|
697
|
-
|
|
698
|
-
def open_xml(fn)
|
|
699
|
-
s = File.read(fn)
|
|
700
|
-
|
|
701
|
-
if fn.include? 'T16n0657'
|
|
702
|
-
# 這個地方 雙行夾註 跨兩行偈頌
|
|
703
|
-
# 把 lb 移到 note 結束之前
|
|
704
|
-
# 讓 lg-row 先結束,再結束雙行夾註
|
|
705
|
-
s.sub!(/(<\/note>)(\n<lb n="0206b29" ed="T"\/>)/, '\2\1')
|
|
706
|
-
end
|
|
707
|
-
|
|
708
|
-
# <milestone unit="juan"> 前面的 lb 屬於新的這一卷
|
|
709
|
-
s.gsub!(%r{((?:<pb [^>]+>\n?)?(?:<lb [^>]+>\n?)+)(<milestone [^>]*unit="juan"[^/>]*/>)}, '\2\1')
|
|
710
|
-
|
|
711
|
-
begin
|
|
712
|
-
doc = Nokogiri::XML(s) { |config| config.strict }
|
|
713
|
-
rescue Nokogiri::XML::SyntaxError => e
|
|
714
|
-
puts "XML parse error, file: #{fn}"
|
|
715
|
-
puts e
|
|
716
|
-
abort
|
|
717
|
-
end
|
|
718
|
-
doc.remove_namespaces!()
|
|
719
|
-
doc
|
|
720
|
-
end
|
|
721
|
-
|
|
722
|
-
def read_mod_notes(doc)
|
|
723
|
-
doc.xpath("//note[@type='mod']").each { |e|
|
|
724
|
-
n = e['n']
|
|
725
|
-
@mod_notes << n
|
|
726
|
-
|
|
727
|
-
# 例 T01n0026_p0506b07, 原註標為 7, CBETA 修訂為 7a, 7b
|
|
728
|
-
n.match(/[a-z]$/) {
|
|
729
|
-
@mod_notes << n[0..-2]
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
end
|
|
733
|
-
|
|
734
|
-
def parse_xml(xml_fn)
|
|
735
|
-
@pass = [false]
|
|
736
|
-
|
|
737
|
-
doc = open_xml(xml_fn)
|
|
738
|
-
|
|
739
|
-
e = doc.xpath("//titleStmt/title")[0]
|
|
740
|
-
@title = traverse(e, 'txt')
|
|
741
|
-
@title = @title.split()[-1]
|
|
742
|
-
|
|
743
|
-
e = doc.at_xpath("//editionStmt/edition/date")
|
|
744
|
-
abort "找不到版本日期" if e.nil?
|
|
745
|
-
@edition_date = e.text.sub(/\$Date: (.*?) \$$/, '\1')
|
|
746
|
-
|
|
747
|
-
e = doc.at_xpath("//projectDesc/p[@lang='zh']")
|
|
748
|
-
abort "找不到貢獻者" if e.nil?
|
|
749
|
-
@contributors = e.text
|
|
750
|
-
|
|
751
|
-
read_mod_notes(doc)
|
|
752
|
-
|
|
753
|
-
root = doc.root()
|
|
754
|
-
body = root.xpath("text/body")[0]
|
|
755
|
-
@pass = [true]
|
|
756
|
-
|
|
757
|
-
text = traverse(body)
|
|
758
|
-
text
|
|
759
|
-
end
|
|
760
|
-
|
|
761
|
-
def traverse(e, mode='html')
|
|
762
|
-
r = ''
|
|
763
|
-
e.children.each { |c|
|
|
764
|
-
s = handle_node(c, mode)
|
|
765
|
-
r += s
|
|
766
|
-
}
|
|
767
|
-
r
|
|
768
|
-
end
|
|
769
|
-
|
|
770
|
-
def write_juan(juan_no, body)
|
|
771
|
-
#if @sutra_no.match(/^(T05|T06|T07)n0220/)
|
|
772
|
-
# fn = "#{$1}n0220_%03d.htm" % juan_no
|
|
773
|
-
#else
|
|
774
|
-
# fn = "#{@sutra_no}_%03d.htm" % juan_no
|
|
775
|
-
#end
|
|
776
|
-
fn = "#{@sutra_no}_%03d.htm" % juan_no
|
|
777
|
-
|
|
778
|
-
html = <<eos
|
|
779
|
-
<html>
|
|
780
|
-
<head>
|
|
781
|
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
782
|
-
<meta name="filename" content="#{fn}" />
|
|
783
|
-
<title>#{@title}</title>
|
|
784
|
-
</head>
|
|
785
|
-
<body>
|
|
786
|
-
<!--
|
|
787
|
-
來源 XML CBETA P5a: https://github.com/cbeta-org/xml-p5a.git
|
|
788
|
-
轉檔程式: https://rubygems.org/gems/cbeta #{Date.today}
|
|
789
|
-
說明文件: http://wiki.ddbc.edu.tw/pages/CBETA_XML_P5a_轉_HTML
|
|
790
|
-
-->
|
|
791
|
-
<div id='body'>
|
|
792
|
-
eos
|
|
793
|
-
html += body + "\n</div><!-- end of div[@id='body'] -->\n"
|
|
794
|
-
html += "<div id='back'>\n" + @back[juan_no] + "</div>\n"
|
|
795
|
-
html += "<div id='cbeta-copyright'><p>\n"
|
|
796
|
-
|
|
797
|
-
orig = @cbeta.get_canon_nickname(@series)
|
|
798
|
-
v = @vol.sub(/^[A-Z]0*([^0].*)$/, '\1')
|
|
799
|
-
n = @sutra_no.sub(/^[A-Z]\d{2,3}n0*([^0].*)$/, '\1')
|
|
800
|
-
html += "【經文資訊】#{orig}第 #{v} 冊 No. #{n} #{@title}<br/>\n"
|
|
801
|
-
html += "【版本記錄】CBETA 電子佛典 版本日期:#{@edition_date}<br/>\n"
|
|
802
|
-
html += "【編輯說明】本資料庫由中華電子佛典協會(CBETA)依#{orig}所編輯<br/>\n"
|
|
803
|
-
|
|
804
|
-
html += "【原始資料】#{@contributors}<br/>\n"
|
|
805
|
-
html += "【其他事項】本資料庫可自由免費流通,詳細內容請參閱【中華電子佛典協會資料庫版權宣告】\n"
|
|
806
|
-
html += "</p></div><!-- end of cbeta-copyright -->\n"
|
|
807
|
-
html += '</body></html>'
|
|
808
|
-
|
|
809
|
-
output_path = File.join(@out_folder, fn)
|
|
810
|
-
File.write(output_path, html)
|
|
811
|
-
end
|
|
812
|
-
|
|
813
|
-
end
|