review-peg 0.1.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 +7 -0
- data/.gitignore +36 -0
- data/.rubocop.yml +47 -0
- data/.rubocop_todo.yml +605 -0
- data/.travis.yml +18 -0
- data/COPYING +515 -0
- data/ChangeLog +2449 -0
- data/Dockerfile +22 -0
- data/Gemfile +6 -0
- data/README.rdoc +81 -0
- data/Rakefile +51 -0
- data/bin/review-catalog-converter-peg +129 -0
- data/bin/review-check-peg +169 -0
- data/bin/review-checkdep-peg +63 -0
- data/bin/review-compile-peg +202 -0
- data/bin/review-epubmaker-legacy-peg +1024 -0
- data/bin/review-epubmaker-peg +44 -0
- data/bin/review-index-peg +110 -0
- data/bin/review-init-peg +151 -0
- data/bin/review-pdfmaker-peg +18 -0
- data/bin/review-preproc-peg +131 -0
- data/bin/review-validate-peg +51 -0
- data/bin/review-vol-peg +100 -0
- data/debian/README.Debian +12 -0
- data/debian/README.source +5 -0
- data/debian/changelog +5 -0
- data/debian/compat +1 -0
- data/debian/control +22 -0
- data/debian/copyright +62 -0
- data/debian/docs +6 -0
- data/debian/manpage.1.ex +59 -0
- data/debian/patches/path.diff +91 -0
- data/debian/patches/series +1 -0
- data/debian/review.install +13 -0
- data/debian/review.links +4 -0
- data/debian/rules +13 -0
- data/debian/source/format +1 -0
- data/doc/NEWS.ja.md +350 -0
- data/doc/NEWS.md +354 -0
- data/doc/catalog.ja.md +53 -0
- data/doc/catalog.md +52 -0
- data/doc/format.ja.md +734 -0
- data/doc/format.md +746 -0
- data/doc/format_idg.ja.md +203 -0
- data/doc/quickstart.ja.md +222 -0
- data/doc/quickstart.md +252 -0
- data/doc/ruby-uuid/README +11 -0
- data/doc/ruby-uuid/README.ja +34 -0
- data/doc/sample.css +108 -0
- data/doc/sample.yml +238 -0
- data/lib/epubmaker.rb +24 -0
- data/lib/epubmaker/content.rb +93 -0
- data/lib/epubmaker/epubcommon.rb +424 -0
- data/lib/epubmaker/epubv2.rb +139 -0
- data/lib/epubmaker/epubv3.rb +222 -0
- data/lib/epubmaker/producer.rb +330 -0
- data/lib/lineinput.rb +107 -0
- data/lib/review.rb +3 -0
- data/lib/review/book.rb +43 -0
- data/lib/review/book/base.rb +401 -0
- data/lib/review/book/chapter.rb +100 -0
- data/lib/review/book/compilable.rb +184 -0
- data/lib/review/book/image_finder.rb +71 -0
- data/lib/review/book/index.rb +413 -0
- data/lib/review/book/page_metric.rb +47 -0
- data/lib/review/book/part.rb +54 -0
- data/lib/review/book/volume.rb +67 -0
- data/lib/review/builder.rb +452 -0
- data/lib/review/catalog.rb +52 -0
- data/lib/review/compiler.rb +5183 -0
- data/lib/review/compiler/literals_1_9.kpeg +22 -0
- data/lib/review/compiler/literals_1_9.rb +435 -0
- data/lib/review/configure.rb +64 -0
- data/lib/review/epubbuilder.rb +18 -0
- data/lib/review/epubmaker.rb +480 -0
- data/lib/review/ewbbuilder.rb +381 -0
- data/lib/review/exception.rb +21 -0
- data/lib/review/extentions.rb +4 -0
- data/lib/review/extentions/array.rb +25 -0
- data/lib/review/extentions/object.rb +9 -0
- data/lib/review/extentions/string.rb +33 -0
- data/lib/review/htmlbuilder.rb +1166 -0
- data/lib/review/htmllayout.rb +41 -0
- data/lib/review/htmltoc.rb +45 -0
- data/lib/review/htmlutils.rb +90 -0
- data/lib/review/i18n.rb +96 -0
- data/lib/review/i18n.yml +169 -0
- data/lib/review/idgxmlbuilder.rb +1233 -0
- data/lib/review/inaobuilder.rb +357 -0
- data/lib/review/latexbuilder.rb +941 -0
- data/lib/review/latexindex.rb +35 -0
- data/lib/review/latexutils.rb +95 -0
- data/lib/review/layout.tex.erb +340 -0
- data/lib/review/lineinput.rb +17 -0
- data/lib/review/location.rb +24 -0
- data/lib/review/makerhelper.rb +67 -0
- data/lib/review/markdownbuilder.rb +339 -0
- data/lib/review/node.rb +288 -0
- data/lib/review/pdfmaker.rb +332 -0
- data/lib/review/preprocessor.rb +530 -0
- data/lib/review/review.kpeg +745 -0
- data/lib/review/sec_counter.rb +69 -0
- data/lib/review/template.rb +21 -0
- data/lib/review/textbuilder.rb +17 -0
- data/lib/review/textutils.rb +16 -0
- data/lib/review/tocparser.rb +348 -0
- data/lib/review/tocprinter.rb +205 -0
- data/lib/review/topbuilder.rb +796 -0
- data/lib/review/unfold.rb +138 -0
- data/lib/review/version.rb +3 -0
- data/lib/uuid.rb +312 -0
- data/review.gemspec +32 -0
- data/templates/html/layout-html5.html.erb +17 -0
- data/templates/html/layout-xhtml1.html.erb +20 -0
- data/templates/ncx/epubv2.ncx.erb +11 -0
- data/templates/opf/epubv2.opf.erb +21 -0
- data/templates/opf/epubv3.opf.erb +18 -0
- data/templates/xml/container.xml.erb +6 -0
- data/test/CHAPS +2 -0
- data/test/assets/test.xml.erb +3 -0
- data/test/assets/test_template.tex +255 -0
- data/test/assets/test_template_backmatter.tex +32 -0
- data/test/bib.re +13 -0
- data/test/book_test_helper.rb +35 -0
- data/test/sample-book/README.md +7 -0
- data/test/sample-book/src/Rakefile +58 -0
- data/test/sample-book/src/_cover.html +3 -0
- data/test/sample-book/src/catalog.yml +10 -0
- data/test/sample-book/src/ch01.re +71 -0
- data/test/sample-book/src/ch02.re +3 -0
- data/test/sample-book/src/config.yml +186 -0
- data/test/sample-book/src/images/ch01-imgsample.jpg +0 -0
- data/test/sample-book/src/images/cover.jpg +0 -0
- data/test/sample-book/src/preface.re +15 -0
- data/test/sample-book/src/sty/jumoline.sty +310 -0
- data/test/sample-book/src/sty/reviewmacro.sty +39 -0
- data/test/sample-book/src/style.css +251 -0
- data/test/sample-book/src/vendor/jumoline/README +29 -0
- data/test/sample-book/src/vendor/jumoline/jumoline.dtx +2988 -0
- data/test/sample-book/src/vendor/jumoline/jumoline.ins +6 -0
- data/test/test.re +43 -0
- data/test/test_book.rb +556 -0
- data/test/test_book_chapter.rb +280 -0
- data/test/test_book_part.rb +54 -0
- data/test/test_builder.rb +80 -0
- data/test/test_catalog.rb +119 -0
- data/test/test_catalog_converter_cmd.rb +73 -0
- data/test/test_compiler.rb +92 -0
- data/test/test_configure.rb +50 -0
- data/test/test_epub3maker.rb +529 -0
- data/test/test_epubmaker.rb +569 -0
- data/test/test_epubmaker_cmd.rb +40 -0
- data/test/test_helper.rb +92 -0
- data/test/test_htmlbuilder.rb +1114 -0
- data/test/test_htmltoc.rb +32 -0
- data/test/test_htmlutils.rb +50 -0
- data/test/test_i18n.rb +180 -0
- data/test/test_idgxmlbuilder.rb +608 -0
- data/test/test_image_finder.rb +82 -0
- data/test/test_inaobuilder.rb +245 -0
- data/test/test_index.rb +174 -0
- data/test/test_latexbuilder.rb +732 -0
- data/test/test_lineinput.rb +182 -0
- data/test/test_makerhelper.rb +66 -0
- data/test/test_markdownbuilder.rb +125 -0
- data/test/test_pdfmaker.rb +171 -0
- data/test/test_pdfmaker_cmd.rb +40 -0
- data/test/test_preprocessor.rb +23 -0
- data/test/test_review_ext.rb +31 -0
- data/test/test_template.rb +26 -0
- data/test/test_textutils.rb +32 -0
- data/test/test_topbuilder.rb +291 -0
- data/test/test_uuid.rb +157 -0
- metadata +357 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#
|
|
2
|
+
# $Id: book.rb 4315 2009-09-02 04:15:24Z kmuto $
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2002-2008 Minero Aoki
|
|
5
|
+
# 2009 Minero Aoki, Kenshi Muto
|
|
6
|
+
#
|
|
7
|
+
# This program is free software.
|
|
8
|
+
# You can distribute or modify this program under the terms of
|
|
9
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
|
10
|
+
# For details of the GNU LGPL, see the file "COPYING".
|
|
11
|
+
#
|
|
12
|
+
require 'review/book/compilable'
|
|
13
|
+
module ReVIEW
|
|
14
|
+
module Book
|
|
15
|
+
ROMAN = %w[0 I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII XIX XX XXI XXII XXIII XXIV XXV XXVI XXVII]
|
|
16
|
+
ALPHA = %w[0 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
|
|
17
|
+
|
|
18
|
+
class Chapter
|
|
19
|
+
include Compilable
|
|
20
|
+
|
|
21
|
+
attr_reader :number, :book
|
|
22
|
+
|
|
23
|
+
def initialize(book, number, name, path, io = nil)
|
|
24
|
+
@book = book
|
|
25
|
+
@number = number
|
|
26
|
+
@name = name
|
|
27
|
+
@path = path
|
|
28
|
+
@io = io
|
|
29
|
+
@title = nil
|
|
30
|
+
@content = nil
|
|
31
|
+
@list_index = nil
|
|
32
|
+
@table_index = nil
|
|
33
|
+
@footnote_index = nil
|
|
34
|
+
@image_index = nil
|
|
35
|
+
@icon_index = nil
|
|
36
|
+
@numberless_image_index = nil
|
|
37
|
+
@indepimage_index = nil
|
|
38
|
+
@headline_index = nil
|
|
39
|
+
@column_index = nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def inspect
|
|
43
|
+
"\#<#{self.class} #{@number} #{@path}>"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def format_number(heading = true)
|
|
47
|
+
if on_PREDEF?
|
|
48
|
+
return "#{@number}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if on_APPENDIX?
|
|
52
|
+
return "#{@number}" if @number < 1 || @number > 27
|
|
53
|
+
|
|
54
|
+
type = @book.config["appendix_format"].blank? ? "arabic" : @book.config["appendix_format"].downcase.strip
|
|
55
|
+
appendix = case type
|
|
56
|
+
when "roman"
|
|
57
|
+
ROMAN[@number]
|
|
58
|
+
when "alphabet", "alpha"
|
|
59
|
+
ALPHA[@number]
|
|
60
|
+
else
|
|
61
|
+
# nil, "arabic", etc...
|
|
62
|
+
"#{@number}"
|
|
63
|
+
end
|
|
64
|
+
if heading
|
|
65
|
+
return "#{I18n.t("appendix", appendix)}"
|
|
66
|
+
else
|
|
67
|
+
return "#{appendix}"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
if heading
|
|
72
|
+
"#{I18n.t("chapter", @number)}"
|
|
73
|
+
else
|
|
74
|
+
"#{@number}"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def on_CHAPS?
|
|
79
|
+
on_FILE?(@book.read_CHAPS)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def on_PREDEF?
|
|
83
|
+
on_FILE?(@book.read_PREDEF)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def on_APPENDIX?
|
|
87
|
+
on_FILE?(@book.read_APPENDIX)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def on_POSTDEF?
|
|
91
|
+
on_FILE?(@book.read_POSTDEF)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
def on_FILE?(contents)
|
|
96
|
+
contents.lines.map(&:strip).include?("#{id()}#{@book.ext()}")
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#
|
|
2
|
+
# $Id: book.rb 4315 2009-09-02 04:15:24Z kmuto $
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2002-2008 Minero Aoki
|
|
5
|
+
# 2009 Minero Aoki, Kenshi Muto
|
|
6
|
+
#
|
|
7
|
+
# This program is free software.
|
|
8
|
+
# You can distribute or modify this program under the terms of
|
|
9
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
|
10
|
+
# For details of the GNU LGPL, see the file "COPYING".
|
|
11
|
+
#
|
|
12
|
+
require 'review/textutils'
|
|
13
|
+
module ReVIEW
|
|
14
|
+
module Book
|
|
15
|
+
module Compilable
|
|
16
|
+
include TextUtils
|
|
17
|
+
attr_reader :book
|
|
18
|
+
attr_reader :path
|
|
19
|
+
|
|
20
|
+
def env
|
|
21
|
+
@book
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def dirname
|
|
25
|
+
return nil unless @path
|
|
26
|
+
File.dirname(@path)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def basename
|
|
30
|
+
return nil unless @path
|
|
31
|
+
File.basename(@path)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def name
|
|
35
|
+
return nil unless @name
|
|
36
|
+
File.basename(@name, '.*')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
alias_method :id, :name
|
|
40
|
+
|
|
41
|
+
def title
|
|
42
|
+
return @title if @title
|
|
43
|
+
|
|
44
|
+
@title = ''
|
|
45
|
+
open {|f|
|
|
46
|
+
f.each_line {|l|
|
|
47
|
+
if l =~ /\A=+/
|
|
48
|
+
@title = l.sub(/\A=+(\[.+?\])?(\{.+?\})?/, '').strip
|
|
49
|
+
break
|
|
50
|
+
end
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
@title
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def size
|
|
57
|
+
File.size(path())
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def volume
|
|
61
|
+
if !@volume
|
|
62
|
+
@volume = Volume.count_file(path())
|
|
63
|
+
@volume.page_per_kbyte = @book.page_metric.page_per_kbyte
|
|
64
|
+
end
|
|
65
|
+
@volume
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def open(&block)
|
|
69
|
+
return (block_given?() ? yield(@io) : @io) if @io
|
|
70
|
+
File.open(path(), &block)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
attr_writer :content
|
|
74
|
+
|
|
75
|
+
def content
|
|
76
|
+
@content = File.read(path())
|
|
77
|
+
rescue
|
|
78
|
+
@content
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def lines
|
|
82
|
+
# FIXME: we cannot duplicate Enumerator on ruby 1.9 HEAD
|
|
83
|
+
(@lines ||= content().lines.to_a).dup
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def list(id)
|
|
87
|
+
list_index()[id]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def list_index
|
|
91
|
+
@list_index ||= ListIndex.parse(lines())
|
|
92
|
+
@list_index
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def table(id)
|
|
96
|
+
table_index()[id]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def table_index
|
|
100
|
+
@table_index ||= TableIndex.parse(lines())
|
|
101
|
+
@table_index
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def footnote(id)
|
|
105
|
+
footnote_index()[id]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def footnote_index
|
|
109
|
+
@footnote_index ||= FootnoteIndex.parse(lines())
|
|
110
|
+
@footnote_index
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def image(id)
|
|
114
|
+
return image_index()[id] if image_index().has_key?(id)
|
|
115
|
+
return icon_index()[id] if icon_index().has_key?(id)
|
|
116
|
+
return numberless_image_index()[id] if numberless_image_index().has_key?(id)
|
|
117
|
+
indepimage_index()[id]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def numberless_image_index
|
|
121
|
+
@numberless_image_index ||=
|
|
122
|
+
NumberlessImageIndex.parse(lines(), id(),
|
|
123
|
+
"#{book.basedir}/#{@book.image_dir}",
|
|
124
|
+
@book.image_types, @book.config['builder'])
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def image_index
|
|
128
|
+
@image_index ||= ImageIndex.parse(lines(), id(),
|
|
129
|
+
"#{book.basedir}/#{@book.image_dir}",
|
|
130
|
+
@book.image_types, @book.config['builder'])
|
|
131
|
+
@image_index
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def icon_index
|
|
135
|
+
@icon_index ||= IconIndex.parse(lines(), id(),
|
|
136
|
+
"#{book.basedir}/#{@book.image_dir}",
|
|
137
|
+
@book.image_types, @book.config['builder'])
|
|
138
|
+
@icon_index
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def indepimage_index
|
|
142
|
+
@indepimage_index ||=
|
|
143
|
+
IndepImageIndex.parse(lines(), id(),
|
|
144
|
+
"#{book.basedir}/#{@book.image_dir}",
|
|
145
|
+
@book.image_types, @book.config['builder'])
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def bibpaper(id)
|
|
149
|
+
bibpaper_index()[id]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def bibpaper_index
|
|
153
|
+
raise FileNotFound, "no such bib file: #{@book.bib_file}" unless @book.bib_exist?
|
|
154
|
+
@bibpaper_index ||= BibpaperIndex.parse(@book.read_bib.lines.to_a)
|
|
155
|
+
@bibpaper_index
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def headline(caption)
|
|
159
|
+
headline_index()[caption]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def headline_index
|
|
163
|
+
@headline_index ||= HeadlineIndex.parse(lines(), self)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def column(id)
|
|
167
|
+
column_index()[id]
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def column_index
|
|
171
|
+
@column_index ||= ColumnIndex.parse(lines())
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def next_chapter
|
|
175
|
+
book.next_chapter(self)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def prev_chapter
|
|
179
|
+
book.prev_chapter(self)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2014 Minero Aoki, Kenshi Muto, Masayoshi Takahashi
|
|
3
|
+
#
|
|
4
|
+
# This program is free software.
|
|
5
|
+
# You can distribute or modify this program under the terms of
|
|
6
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
|
7
|
+
# For details of LGPL, see the file "COPYING".
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
require 'review/extentions'
|
|
11
|
+
require 'review/exception'
|
|
12
|
+
|
|
13
|
+
module ReVIEW
|
|
14
|
+
module Book
|
|
15
|
+
class ImageFinder
|
|
16
|
+
def initialize(basedir, chapid, builder, exts)
|
|
17
|
+
@basedir = basedir
|
|
18
|
+
@chapid = chapid
|
|
19
|
+
@builder = builder
|
|
20
|
+
@exts = exts
|
|
21
|
+
@entries = get_entries()
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def get_entries
|
|
25
|
+
Dir.glob(File.join(@basedir, "**/*.*"))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def add_entry(path)
|
|
29
|
+
unless @entries.include?(path)
|
|
30
|
+
@entries << path
|
|
31
|
+
end
|
|
32
|
+
@entries
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def find_path(id)
|
|
36
|
+
targets = target_list(id)
|
|
37
|
+
targets.each do |target|
|
|
38
|
+
@exts.each do |ext|
|
|
39
|
+
if @entries.include?("#{target}#{ext}")
|
|
40
|
+
return "#{target}#{ext}"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def target_list(id)
|
|
48
|
+
[
|
|
49
|
+
# 1. <basedir>/<builder>/<chapid>/<id>.<ext>
|
|
50
|
+
"#{@basedir}/#{@builder}/#{@chapid}/#{id}",
|
|
51
|
+
|
|
52
|
+
# 2. <basedir>/<builder>/<chapid>-<id>.<ext>
|
|
53
|
+
"#{@basedir}/#{@builder}/#{@chapid}-#{id}",
|
|
54
|
+
|
|
55
|
+
# 3. <basedir>/<builder>/<id>.<ext>
|
|
56
|
+
"#{@basedir}/#{@builder}/#{id}",
|
|
57
|
+
|
|
58
|
+
# 4. <basedir>/<chapid>/<id>.<ext>
|
|
59
|
+
"#{@basedir}/#{@chapid}/#{id}",
|
|
60
|
+
|
|
61
|
+
# 5. <basedir>/<chapid>-<id>.<ext>
|
|
62
|
+
"#{@basedir}/#{@chapid}-#{id}",
|
|
63
|
+
|
|
64
|
+
# 6. <basedir>/<id>.<ext>
|
|
65
|
+
"#{@basedir}/#{id}"
|
|
66
|
+
]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2002-2007 Minero Aoki
|
|
4
|
+
# 2008-2009 Minero Aoki, Kenshi Muto
|
|
5
|
+
#
|
|
6
|
+
# This program is free software.
|
|
7
|
+
# You can distribute or modify this program under the terms of
|
|
8
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
|
9
|
+
# For details of LGPL, see the file "COPYING".
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
require 'review/extentions'
|
|
13
|
+
require 'review/exception'
|
|
14
|
+
require 'review/book/image_finder'
|
|
15
|
+
require 'review/i18n'
|
|
16
|
+
|
|
17
|
+
module ReVIEW
|
|
18
|
+
module Book
|
|
19
|
+
class Index
|
|
20
|
+
def Index.parse(src, *args)
|
|
21
|
+
items = []
|
|
22
|
+
seq = 1
|
|
23
|
+
src.grep(%r<^//#{item_type()}>) do |line|
|
|
24
|
+
if id = line.slice(/\[(.*?)\]/, 1)
|
|
25
|
+
items.push item_class().new(id, seq)
|
|
26
|
+
seq += 1
|
|
27
|
+
if id == ""
|
|
28
|
+
warn "warning: no ID of #{item_type()} in #{line}"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
new(items, *args)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Item = Struct.new(:id, :number)
|
|
36
|
+
|
|
37
|
+
def Index.item_class
|
|
38
|
+
self::Item
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
include Enumerable
|
|
42
|
+
|
|
43
|
+
def item_type
|
|
44
|
+
self.class.item_type
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def initialize(items)
|
|
48
|
+
@items = items
|
|
49
|
+
@index = {}
|
|
50
|
+
items.each do |i|
|
|
51
|
+
warn "warning: duplicate ID: #{i.id} (#{i})" unless @index[i.id].nil?
|
|
52
|
+
@index[i.id] = i
|
|
53
|
+
end
|
|
54
|
+
@image_finder = nil
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def [](id)
|
|
58
|
+
@index.fetch(id)
|
|
59
|
+
rescue
|
|
60
|
+
if @index.keys.map{|i| i.split(/\|/).last }.flatten. # unfold all ids
|
|
61
|
+
reduce(Hash.new(0)){|h, i| h[i] += 1; h}. # number of occurrences
|
|
62
|
+
select{|k, v| k == id && v > 1 }.present? # detect duplicated
|
|
63
|
+
raise KeyError, "key '#{id}' is ambiguous for #{self.class}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
@items.each do |i|
|
|
67
|
+
if i.id.split(/\|/).include?(id)
|
|
68
|
+
return i
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
raise KeyError, "not found key '#{id}' for #{self.class}"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def number(id)
|
|
75
|
+
self[id].number.to_s
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def each(&block)
|
|
79
|
+
@items.each(&block)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def has_key?(id)
|
|
83
|
+
return @index.has_key?(id)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class ChapterIndex < Index
|
|
89
|
+
def item_type
|
|
90
|
+
'chapter'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def number(id)
|
|
94
|
+
chapter = @index.fetch(id, nil)
|
|
95
|
+
if chapter
|
|
96
|
+
return chapter.format_number
|
|
97
|
+
else
|
|
98
|
+
return "#{I18n.t("part", chapter.number)}"
|
|
99
|
+
end
|
|
100
|
+
rescue # part
|
|
101
|
+
raise "invalid number error: id:#{id}, capter:#{chapter}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def title(id)
|
|
105
|
+
@index.fetch(id).title
|
|
106
|
+
rescue # non-file part
|
|
107
|
+
@index.fetch(id).name
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def display_string(id)
|
|
111
|
+
"#{number(id)}#{I18n.t("chapter_quote", title(id))}"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ListIndex < Index
|
|
117
|
+
def ListIndex.item_type
|
|
118
|
+
'(list|listnum)'
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class TableIndex < Index
|
|
124
|
+
def TableIndex.item_type
|
|
125
|
+
'table'
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class FootnoteIndex < Index
|
|
131
|
+
Item = Struct.new(:id, :number, :content)
|
|
132
|
+
|
|
133
|
+
def FootnoteIndex.parse(src)
|
|
134
|
+
items = []
|
|
135
|
+
seq = 1
|
|
136
|
+
src.grep(%r<^//footnote>) do |line|
|
|
137
|
+
if m = /\[(.*?)\]\[(.*)\]/.match(line)
|
|
138
|
+
m1 = m[1].gsub(/\\(\])/){$1}
|
|
139
|
+
m2 = m[2].gsub(/\\(\])/){$1}
|
|
140
|
+
items.push Item.new(m1, seq, m2)
|
|
141
|
+
end
|
|
142
|
+
seq += 1
|
|
143
|
+
end
|
|
144
|
+
new(items)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class ImageIndex < Index
|
|
150
|
+
def self.parse(src, *args)
|
|
151
|
+
items = []
|
|
152
|
+
seq = 1
|
|
153
|
+
src.grep(%r<^//#{item_type()}>) do |line|
|
|
154
|
+
# ex. ["//image", "id", "", "caption"]
|
|
155
|
+
elements = line.split(/\[(.*?)\]/)
|
|
156
|
+
if elements[1].present?
|
|
157
|
+
items.push item_class().new(elements[1], seq, elements[3])
|
|
158
|
+
seq += 1
|
|
159
|
+
if elements[1] == ""
|
|
160
|
+
warn "warning: no ID of #{item_type()} in #{line}"
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
new(items, *args)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
class Item
|
|
168
|
+
|
|
169
|
+
def initialize(id, number, caption = nil)
|
|
170
|
+
@id = id
|
|
171
|
+
@number = number
|
|
172
|
+
@caption = caption
|
|
173
|
+
@path = nil
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
attr_reader :id
|
|
177
|
+
attr_reader :number
|
|
178
|
+
attr_reader :caption
|
|
179
|
+
attr_writer :index # internal use only
|
|
180
|
+
|
|
181
|
+
def bound?
|
|
182
|
+
path
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def path
|
|
186
|
+
@path ||= @index.find_path(id)
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def ImageIndex.item_type
|
|
191
|
+
'(image|graph)'
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
attr_reader :image_finder
|
|
195
|
+
|
|
196
|
+
def initialize(items, chapid, basedir, types, builder)
|
|
197
|
+
super items
|
|
198
|
+
items.each do |i|
|
|
199
|
+
i.index = self
|
|
200
|
+
end
|
|
201
|
+
@chapid = chapid
|
|
202
|
+
@basedir = basedir
|
|
203
|
+
@types = types
|
|
204
|
+
|
|
205
|
+
@image_finder = ReVIEW::Book::ImageFinder.new(basedir, chapid,
|
|
206
|
+
builder, types)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def find_path(id)
|
|
210
|
+
@image_finder.find_path(id)
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
class IconIndex < ImageIndex
|
|
215
|
+
def initialize(items, chapid, basedir, types, builder)
|
|
216
|
+
@items = items
|
|
217
|
+
@index = {}
|
|
218
|
+
items.each do |i|
|
|
219
|
+
## warn "warning: duplicate ID: #{i.id} (#{i})" unless @index[i.id].nil?
|
|
220
|
+
@index[i.id] = i
|
|
221
|
+
end
|
|
222
|
+
items.each do |i|
|
|
223
|
+
i.index = self
|
|
224
|
+
end
|
|
225
|
+
@chapid = chapid
|
|
226
|
+
@basedir = basedir
|
|
227
|
+
@types = types
|
|
228
|
+
|
|
229
|
+
@image_finder = ImageFinder.new(basedir, chapid, builder, types)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def IconIndex.parse(src, *args)
|
|
233
|
+
items = []
|
|
234
|
+
seq = 1
|
|
235
|
+
src.grep(%r!@<icon>!) do |line|
|
|
236
|
+
line.gsub(/@<icon>\{(.+?)\}/) do |m|
|
|
237
|
+
items.push item_class().new($1, seq)
|
|
238
|
+
seq += 1
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
new(items, *args)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
class FormatRef
|
|
246
|
+
def initialize(locale, index)
|
|
247
|
+
@locale = locale
|
|
248
|
+
@index = index
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def title(id)
|
|
252
|
+
sprintf(@locale["#{@index.item_type}_caption_format".to_sym],
|
|
253
|
+
@index.title(id))
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def number(id)
|
|
257
|
+
sprintf(@locale["#{@index.item_type}_number_format".to_sym],
|
|
258
|
+
@index.number(id))
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def method_missing(mid, *args, &block)
|
|
262
|
+
super unless @index.respond_to?(mid)
|
|
263
|
+
@index.__send__(mid, *args, &block)
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
class BibpaperIndex < Index
|
|
268
|
+
Item = Struct.new(:id, :number, :caption)
|
|
269
|
+
|
|
270
|
+
def BibpaperIndex.parse(src)
|
|
271
|
+
items = []
|
|
272
|
+
seq = 1
|
|
273
|
+
src.grep(%r<^//bibpaper>) do |line|
|
|
274
|
+
if m = /\[(.*?)\]\[(.*)\]/.match(line)
|
|
275
|
+
m1 = m[1].gsub(/\\(.)/){$1}
|
|
276
|
+
m2 = m[2].gsub(/\\(.)/){$1}
|
|
277
|
+
items.push Item.new(m1, seq, m2)
|
|
278
|
+
end
|
|
279
|
+
seq += 1
|
|
280
|
+
end
|
|
281
|
+
new(items)
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
class NumberlessImageIndex < ImageIndex
|
|
286
|
+
class Item < ImageIndex::Item
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def NumberlessImageIndex.item_type
|
|
290
|
+
'numberlessimage'
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def number(id)
|
|
294
|
+
""
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
class IndepImageIndex < ImageIndex
|
|
299
|
+
class Item < ImageIndex::Item
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def IndepImageIndex.item_type
|
|
303
|
+
'indepimage'
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def number(id)
|
|
307
|
+
""
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
class HeadlineIndex < Index
|
|
312
|
+
HEADLINE_PATTERN = /\A(=+)(?:\[(.+?)\])?(?:\{(.+?)\})?(.*)/
|
|
313
|
+
Item = Struct.new(:id, :number, :caption)
|
|
314
|
+
attr_reader :items
|
|
315
|
+
|
|
316
|
+
def HeadlineIndex.parse(src, chap)
|
|
317
|
+
items = []
|
|
318
|
+
indexs = []
|
|
319
|
+
headlines = []
|
|
320
|
+
inside_column = false
|
|
321
|
+
src.each do |line|
|
|
322
|
+
if m = HEADLINE_PATTERN.match(line)
|
|
323
|
+
next if m[1].size > 10 # Ignore too deep index
|
|
324
|
+
index = m[1].size - 2
|
|
325
|
+
|
|
326
|
+
# column
|
|
327
|
+
if m[2] == 'column'
|
|
328
|
+
inside_column = true
|
|
329
|
+
next
|
|
330
|
+
end
|
|
331
|
+
if m[2] == '/column'
|
|
332
|
+
inside_column = false
|
|
333
|
+
next
|
|
334
|
+
end
|
|
335
|
+
if indexs.blank? || index <= indexs[-1]
|
|
336
|
+
inside_column = false
|
|
337
|
+
end
|
|
338
|
+
if inside_column
|
|
339
|
+
next
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
if index >= 0
|
|
343
|
+
if indexs.size > (index + 1)
|
|
344
|
+
indexs = indexs.take(index + 1)
|
|
345
|
+
headlines = headlines.take(index + 1)
|
|
346
|
+
end
|
|
347
|
+
if indexs[index].nil?
|
|
348
|
+
(0..index).each{|i| indexs[i] = 0 if indexs[i].nil?}
|
|
349
|
+
end
|
|
350
|
+
indexs[index] += 1
|
|
351
|
+
headlines[index] = m[3].present? ? m[3].strip : m[4].strip
|
|
352
|
+
items.push Item.new(headlines.join("|"), indexs.dup, m[4].strip)
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
new(items, chap)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def initialize(items, chap)
|
|
360
|
+
@items = items
|
|
361
|
+
@chap = chap
|
|
362
|
+
@index = {}
|
|
363
|
+
items.each do |i|
|
|
364
|
+
warn "warning: duplicate ID: #{i.id}" unless @index[i.id].nil?
|
|
365
|
+
@index[i.id] = i
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def number(id)
|
|
370
|
+
n = @chap.number
|
|
371
|
+
if @chap.on_APPENDIX? && @chap.number > 0 && @chap.number < 28
|
|
372
|
+
type = @chap.book.config["appendix_format"].blank? ? "arabic" : @chap.book.config["appendix_format"].downcase.strip
|
|
373
|
+
n = case type
|
|
374
|
+
when "roman"
|
|
375
|
+
ROMAN[@chap.number]
|
|
376
|
+
when "alphabet", "alpha"
|
|
377
|
+
ALPHA[@chap.number]
|
|
378
|
+
else
|
|
379
|
+
# nil, "arabic", etc...
|
|
380
|
+
"#{@chap.number}"
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
return ([n] + self[id].number).join(".")
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
class ColumnIndex < Index
|
|
388
|
+
COLUMN_PATTERN = /\A(=+)\[column\](?:\{(.+?)\})?(.*)/
|
|
389
|
+
Item = Struct.new(:id, :number, :caption)
|
|
390
|
+
|
|
391
|
+
def ColumnIndex.parse(src, *args)
|
|
392
|
+
items = []
|
|
393
|
+
seq = 1
|
|
394
|
+
src.each do |line|
|
|
395
|
+
if m = COLUMN_PATTERN.match(line)
|
|
396
|
+
level = m[1] ## not use it yet
|
|
397
|
+
id = m[2]
|
|
398
|
+
caption = m[3].strip
|
|
399
|
+
if !id || id == ""
|
|
400
|
+
id = caption
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
items.push item_class().new(id, seq, caption)
|
|
404
|
+
seq += 1
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
new(items)
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
end
|
|
413
|
+
end
|