# Copyright (c) 2008-2022 Minero Aoki, Kenshi Muto, Masayoshi Takahashi, # KADO Masanori # # This program is free software. # You can distribute or modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # require 'review/book/index' require 'review/exception' require 'review/builder' require 'review/sec_counter' module ReVIEW class IndexBuilder < Builder attr_reader :list_index, :table_index, :equation_index, :footnote_index, :endnote_index, :numberless_image_index, :image_index, :icon_index, :indepimage_index, :headline_index, :column_index, :bibpaper_index def initialize(strict = false, *args) super end def check_id(id) if id if id =~ %r![#%\\{}\[\]~/$'"|*?&<>`\s]! warn "deprecated ID: `#{$&}` in `#{id}`", location: location elsif id.start_with?('.') warn "deprecated ID: `#{id}` begins from `.`", location: location end end end def pre_paragraph '' end def post_paragraph '' end def bind(compiler, chapter, location) @compiler = compiler @chapter = chapter @location = location @output = StringIO.new if @chapter.present? @book = @chapter.book end builder_init_file end def builder_init_file super @headline_stack = [] @crossref = { footnote: {}, endnote: {} } @list_index = ReVIEW::Book::ListIndex.new @table_index = ReVIEW::Book::TableIndex.new @equation_index = ReVIEW::Book::EquationIndex.new @footnote_index = ReVIEW::Book::FootnoteIndex.new @endnote_index = ReVIEW::Book::EndnoteIndex.new @headline_index = ReVIEW::Book::HeadlineIndex.new(@chapter) @column_index = ReVIEW::Book::ColumnIndex.new @chapter_index = ReVIEW::Book::ChapterIndex.new @bibpaper_index = ReVIEW::Book::BibpaperIndex.new if @book @image_index = ReVIEW::Book::ImageIndex.new(@chapter) @icon_index = ReVIEW::Book::IconIndex.new(@chapter) @numberless_image_index = ReVIEW::Book::NumberlessImageIndex.new(@chapter) @indepimage_index = ReVIEW::Book::IndepImageIndex.new(@chapter) end end private :builder_init_file def result %i[footnote endnote].each do |name| @crossref[name].each_pair do |k, v| if v == 0 warn "#{@chapter.basename}: #{name} ID #{k} is not referred." end end end nil end def target_name 'index' end def headline(level, label, caption) check_id(label) @sec_counter.inc(level) return if level < 2 cursor = level - 2 @headline_stack[cursor] = (label || caption) if @headline_stack.size > cursor + 1 @headline_stack = @headline_stack.take(cursor + 1) end item_id = @headline_stack.join('|') item = ReVIEW::Book::Index::Item.new(item_id, @sec_counter.number_list, caption) @headline_index.add_item(item) compile_inline(caption) end def nonum_begin(level, label, caption) check_id(label) return if level < 2 cursor = level - 2 @headline_stack[cursor] = (label || caption) if @headline_stack.size > cursor + 1 @headline_stack = @headline_stack.take(cursor + 1) end item_id = @headline_stack.join('|') item = ReVIEW::Book::Index::Item.new(item_id, nil, caption) @headline_index.add_item(item) end def nonum_end(_level) end def notoc_begin(level, label, caption) check_id(label) return if level < 2 cursor = level - 2 @headline_stack[cursor] = (label || caption) if @headline_stack.size > cursor + 1 @headline_stack = @headline_stack.take(cursor + 1) end item_id = @headline_stack.join('|') item = ReVIEW::Book::Index::Item.new(item_id, nil, caption) @headline_index.add_item(item) end def notoc_end(_level) end def nodisp_begin(level, label, caption) check_id(label) return if level < 2 cursor = level - 2 @headline_stack[cursor] = (label || caption) if @headline_stack.size > cursor + 1 @headline_stack = @headline_stack.take(cursor + 1) end item_id = @headline_stack.join('|') item = ReVIEW::Book::Index::Item.new(item_id, nil, caption) @headline_index.add_item(item) end def nodisp_end(_level) end def column_begin(_level, label, caption) check_id(label) item_id = label || caption item = ReVIEW::Book::Index::Item.new(item_id, @column_index.size + 1, caption) @column_index.add_item(item) end def column_end(_level) end def xcolumn_begin(_level, label, _caption) check_id(label) end def xcolumn_end(_level) end def sup_begin(_level, label, _caption) check_id(label) end def sup_end(_level) end def ul_begin end def ul_item_begin(lines) end def ul_item_end end def ul_end end def ol_begin end def ol_item(lines, _num) end def ol_end end def dl_begin end def dt(line) end def dd(lines) end def dl_end end def paragraph(lines) end def parasep '' end def nofunc_text(_str) '' end def read(_lines) end alias_method :lead, :read def list(lines, id, caption, _lang = nil) check_id(id) item = ReVIEW::Book::Index::Item.new(id, @list_index.size + 1) @list_index.add_item(item) compile_inline(caption) lines.each { |line| compile_inline(line) } end def source(lines, caption = nil, _lang = nil) compile_inline(caption) lines.each { |line| compile_inline(line) } end def listnum(lines, id, caption, _lang = nil) check_id(id) item = ReVIEW::Book::Index::Item.new(id, @list_index.size + 1) @list_index.add_item(item) compile_inline(caption) lines.each { |line| compile_inline(line) } end def emlist(lines, caption = nil, _lang = nil) compile_inline(caption) lines.each { |line| compile_inline(line) } end def emlistnum(lines, caption = nil, _lang = nil) compile_inline(caption) lines.each { |line| compile_inline(line) } end def cmd(lines, caption = nil) compile_inline(caption) lines.each { |line| compile_inline(line) } end def quote(lines) lines.each { |line| compile_inline(line) } end def image(_lines, id, caption, _metric = nil) check_id(id) item = ReVIEW::Book::Index::Item.new(id, @image_index.size + 1, caption) @image_index.add_item(item) compile_inline(caption) end def table(lines, id = nil, caption = nil) check_id(id) if id item = ReVIEW::Book::Index::Item.new(id, @table_index.size + 1, caption) @table_index.add_item(item) end compile_inline(caption) lines.each { |line| compile_inline(line) } end def emtable(_lines, caption = nil) # item = ReVIEW::Book::TableIndex::Item.new(id, @table_index.size + 1) # @table_index << item compile_inline(caption) end def comment(lines, comment = nil) end def imgtable(_lines, id, caption = nil, _metric = nil) check_id(id) item = ReVIEW::Book::Index::Item.new(id, @table_index.size + 1) @table_index.add_item(item) ## to find image path item = ReVIEW::Book::Index::Item.new(id, @indepimage_index.size + 1) @indepimage_index.add_item(item) compile_inline(caption) end def footnote(id, str) check_id(id) @crossref[:footnote][id] ||= 0 item = ReVIEW::Book::Index::Item.new(id, @footnote_index.size + 1, str) @footnote_index.add_item(item) compile_inline(str) end def endnote(id, str) check_id(id) @crossref[:endnote][id] ||= 0 item = ReVIEW::Book::Index::Item.new(id, @endnote_index.size + 1, str) @endnote_index.add_item(item) compile_inline(str) end def indepimage(_lines, id, caption = '', _metric = nil) check_id(id) item = ReVIEW::Book::Index::Item.new(id, @indepimage_index.size + 1) @indepimage_index.add_item(item) compile_inline(caption) end def numberlessimage(_lines, id, caption = '', _metric = nil) check_id(id) item = ReVIEW::Book::Index::Item.new(id, @indepimage_index.size + 1) @indepimage_index.add_item(item) compile_inline(caption) end def hr end def label(id) check_id(id) end def blankline end def flushright(lines) lines.each { |line| compile_inline(line) } end def centering(lines) lines.each { |line| compile_inline(line) } end def olnum(_num) end def pagebreak end def bpo(lines) lines.each { |line| compile_inline(line) } end def noindent end def printendnotes end def compile_inline(s) @compiler.text(s) end def inline_chapref(_id) '' end def inline_chap(_id) '' end def inline_title(_id) '' end def inline_list(_id) '' end def inline_img(_id) '' end def inline_imgref(_id) '' end def inline_table(_id) '' end def inline_eq(_id) '' end def inline_fn(id) @crossref[:footnote][id] = @crossref[:footnote][id] ? @crossref[:footnote][id] + 1 : 1 '' end def inline_endnote(id) @crossref[:endnote][id] = @crossref[:endnote][id] ? @crossref[:endnote][id] + 1 : 1 '' end def inline_i(_str) '' end def inline_b(_str) '' end def inline_ami(_str) '' end def inline_bou(str) str end def inline_tti(_str) '' end def inline_ttb(_str) '' end def inline_dtp(_str) '' end def inline_code(_str) '' end def inline_idx(_str) '' end def inline_hidx(_str) '' end def inline_br(_str) '' end def inline_m(_str) '' end def firstlinenum(_num) '' end def inline_ruby(_arg) '' end def inline_kw(_arg) '' end def inline_href(_arg) '' end def inline_hr(_arg) '' end def text(_str) '' end def bibpaper(lines, id, caption) check_id(id) item = ReVIEW::Book::Index::Item.new(id, @bibpaper_index.size + 1, caption) @bibpaper_index.add_item(item) compile_inline(caption) lines.each { |line| compile_inline(line) } end def inline_hd(_id) '' end def inline_secref(_id) '' end def inline_sec(_id) '' end def inline_sectitle(_id) '' end def inline_bib(_id) '' end def inline_column(_id) '' end def inline_column_chap(_chapter, _id) '' end def inline_pageref(_id) '' end def inline_tcy(_arg) '' end def inline_balloon(_arg) '' end def inline_w(_s) '' end def inline_wb(_s) '' end def inline_abbr(_str) '' end def inline_acronym(_str) '' end def inline_cite(_str) '' end def inline_dfn(_str) '' end def inline_em(_str) '' end def inline_kbd(_str) '' end def inline_samp(_str) '' end def inline_strong(_str) '' end def inline_var(_str) '' end def inline_big(_str) '' end def inline_small(_str) '' end def inline_sub(_str) '' end def inline_sup(_str) '' end def inline_tt(_str) '' end def inline_del(_str) '' end def inline_ins(_str) '' end def inline_u(_str) '' end def inline_recipe(_str) '' end def inline_icon(id) check_id(id) item = ReVIEW::Book::Index::Item.new(id, @icon_index.size + 1) @icon_index.add_item(item) '' end def inline_uchar(_str) '' end def raw(_str) '' end def embed(_lines, _arg = nil) '' end ## override def error(msg = nil) # ignore in indexing end def texequation(_lines, id = nil, caption = '') check_id(id) if id item = ReVIEW::Book::Index::Item.new(id, @equation_index.size + 1) @equation_index.add_item(item) end compile_inline(caption) end def get_chap(_chapter = nil) '' end def extract_chapter_id(_chap_ref) '' end def captionblock(_type, lines, caption, _specialstyle = nil) compile_inline(caption) lines.each { |line| compile_inline(line) } '' end def graph(lines, id, _command, caption = '') image(lines, id, caption) end def tsize(_str) '' end def inline_raw(_args) '' end def inline_embed(_args) '' end def highlight? false end def unknown_command(*_args) # ignore end end end # module ReVIEW