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.
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