review-peg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/.rubocop.yml +47 -0
  4. data/.rubocop_todo.yml +605 -0
  5. data/.travis.yml +18 -0
  6. data/COPYING +515 -0
  7. data/ChangeLog +2449 -0
  8. data/Dockerfile +22 -0
  9. data/Gemfile +6 -0
  10. data/README.rdoc +81 -0
  11. data/Rakefile +51 -0
  12. data/bin/review-catalog-converter-peg +129 -0
  13. data/bin/review-check-peg +169 -0
  14. data/bin/review-checkdep-peg +63 -0
  15. data/bin/review-compile-peg +202 -0
  16. data/bin/review-epubmaker-legacy-peg +1024 -0
  17. data/bin/review-epubmaker-peg +44 -0
  18. data/bin/review-index-peg +110 -0
  19. data/bin/review-init-peg +151 -0
  20. data/bin/review-pdfmaker-peg +18 -0
  21. data/bin/review-preproc-peg +131 -0
  22. data/bin/review-validate-peg +51 -0
  23. data/bin/review-vol-peg +100 -0
  24. data/debian/README.Debian +12 -0
  25. data/debian/README.source +5 -0
  26. data/debian/changelog +5 -0
  27. data/debian/compat +1 -0
  28. data/debian/control +22 -0
  29. data/debian/copyright +62 -0
  30. data/debian/docs +6 -0
  31. data/debian/manpage.1.ex +59 -0
  32. data/debian/patches/path.diff +91 -0
  33. data/debian/patches/series +1 -0
  34. data/debian/review.install +13 -0
  35. data/debian/review.links +4 -0
  36. data/debian/rules +13 -0
  37. data/debian/source/format +1 -0
  38. data/doc/NEWS.ja.md +350 -0
  39. data/doc/NEWS.md +354 -0
  40. data/doc/catalog.ja.md +53 -0
  41. data/doc/catalog.md +52 -0
  42. data/doc/format.ja.md +734 -0
  43. data/doc/format.md +746 -0
  44. data/doc/format_idg.ja.md +203 -0
  45. data/doc/quickstart.ja.md +222 -0
  46. data/doc/quickstart.md +252 -0
  47. data/doc/ruby-uuid/README +11 -0
  48. data/doc/ruby-uuid/README.ja +34 -0
  49. data/doc/sample.css +108 -0
  50. data/doc/sample.yml +238 -0
  51. data/lib/epubmaker.rb +24 -0
  52. data/lib/epubmaker/content.rb +93 -0
  53. data/lib/epubmaker/epubcommon.rb +424 -0
  54. data/lib/epubmaker/epubv2.rb +139 -0
  55. data/lib/epubmaker/epubv3.rb +222 -0
  56. data/lib/epubmaker/producer.rb +330 -0
  57. data/lib/lineinput.rb +107 -0
  58. data/lib/review.rb +3 -0
  59. data/lib/review/book.rb +43 -0
  60. data/lib/review/book/base.rb +401 -0
  61. data/lib/review/book/chapter.rb +100 -0
  62. data/lib/review/book/compilable.rb +184 -0
  63. data/lib/review/book/image_finder.rb +71 -0
  64. data/lib/review/book/index.rb +413 -0
  65. data/lib/review/book/page_metric.rb +47 -0
  66. data/lib/review/book/part.rb +54 -0
  67. data/lib/review/book/volume.rb +67 -0
  68. data/lib/review/builder.rb +452 -0
  69. data/lib/review/catalog.rb +52 -0
  70. data/lib/review/compiler.rb +5183 -0
  71. data/lib/review/compiler/literals_1_9.kpeg +22 -0
  72. data/lib/review/compiler/literals_1_9.rb +435 -0
  73. data/lib/review/configure.rb +64 -0
  74. data/lib/review/epubbuilder.rb +18 -0
  75. data/lib/review/epubmaker.rb +480 -0
  76. data/lib/review/ewbbuilder.rb +381 -0
  77. data/lib/review/exception.rb +21 -0
  78. data/lib/review/extentions.rb +4 -0
  79. data/lib/review/extentions/array.rb +25 -0
  80. data/lib/review/extentions/object.rb +9 -0
  81. data/lib/review/extentions/string.rb +33 -0
  82. data/lib/review/htmlbuilder.rb +1166 -0
  83. data/lib/review/htmllayout.rb +41 -0
  84. data/lib/review/htmltoc.rb +45 -0
  85. data/lib/review/htmlutils.rb +90 -0
  86. data/lib/review/i18n.rb +96 -0
  87. data/lib/review/i18n.yml +169 -0
  88. data/lib/review/idgxmlbuilder.rb +1233 -0
  89. data/lib/review/inaobuilder.rb +357 -0
  90. data/lib/review/latexbuilder.rb +941 -0
  91. data/lib/review/latexindex.rb +35 -0
  92. data/lib/review/latexutils.rb +95 -0
  93. data/lib/review/layout.tex.erb +340 -0
  94. data/lib/review/lineinput.rb +17 -0
  95. data/lib/review/location.rb +24 -0
  96. data/lib/review/makerhelper.rb +67 -0
  97. data/lib/review/markdownbuilder.rb +339 -0
  98. data/lib/review/node.rb +288 -0
  99. data/lib/review/pdfmaker.rb +332 -0
  100. data/lib/review/preprocessor.rb +530 -0
  101. data/lib/review/review.kpeg +745 -0
  102. data/lib/review/sec_counter.rb +69 -0
  103. data/lib/review/template.rb +21 -0
  104. data/lib/review/textbuilder.rb +17 -0
  105. data/lib/review/textutils.rb +16 -0
  106. data/lib/review/tocparser.rb +348 -0
  107. data/lib/review/tocprinter.rb +205 -0
  108. data/lib/review/topbuilder.rb +796 -0
  109. data/lib/review/unfold.rb +138 -0
  110. data/lib/review/version.rb +3 -0
  111. data/lib/uuid.rb +312 -0
  112. data/review.gemspec +32 -0
  113. data/templates/html/layout-html5.html.erb +17 -0
  114. data/templates/html/layout-xhtml1.html.erb +20 -0
  115. data/templates/ncx/epubv2.ncx.erb +11 -0
  116. data/templates/opf/epubv2.opf.erb +21 -0
  117. data/templates/opf/epubv3.opf.erb +18 -0
  118. data/templates/xml/container.xml.erb +6 -0
  119. data/test/CHAPS +2 -0
  120. data/test/assets/test.xml.erb +3 -0
  121. data/test/assets/test_template.tex +255 -0
  122. data/test/assets/test_template_backmatter.tex +32 -0
  123. data/test/bib.re +13 -0
  124. data/test/book_test_helper.rb +35 -0
  125. data/test/sample-book/README.md +7 -0
  126. data/test/sample-book/src/Rakefile +58 -0
  127. data/test/sample-book/src/_cover.html +3 -0
  128. data/test/sample-book/src/catalog.yml +10 -0
  129. data/test/sample-book/src/ch01.re +71 -0
  130. data/test/sample-book/src/ch02.re +3 -0
  131. data/test/sample-book/src/config.yml +186 -0
  132. data/test/sample-book/src/images/ch01-imgsample.jpg +0 -0
  133. data/test/sample-book/src/images/cover.jpg +0 -0
  134. data/test/sample-book/src/preface.re +15 -0
  135. data/test/sample-book/src/sty/jumoline.sty +310 -0
  136. data/test/sample-book/src/sty/reviewmacro.sty +39 -0
  137. data/test/sample-book/src/style.css +251 -0
  138. data/test/sample-book/src/vendor/jumoline/README +29 -0
  139. data/test/sample-book/src/vendor/jumoline/jumoline.dtx +2988 -0
  140. data/test/sample-book/src/vendor/jumoline/jumoline.ins +6 -0
  141. data/test/test.re +43 -0
  142. data/test/test_book.rb +556 -0
  143. data/test/test_book_chapter.rb +280 -0
  144. data/test/test_book_part.rb +54 -0
  145. data/test/test_builder.rb +80 -0
  146. data/test/test_catalog.rb +119 -0
  147. data/test/test_catalog_converter_cmd.rb +73 -0
  148. data/test/test_compiler.rb +92 -0
  149. data/test/test_configure.rb +50 -0
  150. data/test/test_epub3maker.rb +529 -0
  151. data/test/test_epubmaker.rb +569 -0
  152. data/test/test_epubmaker_cmd.rb +40 -0
  153. data/test/test_helper.rb +92 -0
  154. data/test/test_htmlbuilder.rb +1114 -0
  155. data/test/test_htmltoc.rb +32 -0
  156. data/test/test_htmlutils.rb +50 -0
  157. data/test/test_i18n.rb +180 -0
  158. data/test/test_idgxmlbuilder.rb +608 -0
  159. data/test/test_image_finder.rb +82 -0
  160. data/test/test_inaobuilder.rb +245 -0
  161. data/test/test_index.rb +174 -0
  162. data/test/test_latexbuilder.rb +732 -0
  163. data/test/test_lineinput.rb +182 -0
  164. data/test/test_makerhelper.rb +66 -0
  165. data/test/test_markdownbuilder.rb +125 -0
  166. data/test/test_pdfmaker.rb +171 -0
  167. data/test/test_pdfmaker_cmd.rb +40 -0
  168. data/test/test_preprocessor.rb +23 -0
  169. data/test/test_review_ext.rb +31 -0
  170. data/test/test_template.rb +26 -0
  171. data/test/test_textutils.rb +32 -0
  172. data/test/test_topbuilder.rb +291 -0
  173. data/test/test_uuid.rb +157 -0
  174. 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