class Juli::Visitor::Html
This visits Absyn tree and generates HTML
Text files under juli-repository must have '.txt' extention.
OPTIONS¶ ↑
- -f
-
force update
- -t template
-
specify template
Attributes
Public Class Methods
Html
sepecific initialization does:
-
create output_top.
-
copy *.js, *.css files to output_top/
NOTE: this is executed every juli(1) run with -g html option (usually 99% is so), so be careful to avoid multiple initialization.
Juli::Absyn::Visitor::new
# File lib/juli/visitor/html.rb, line 110 def initialize(opts={}) super # files here will not be deleted even if corresponding *.txt file # doesn't exist. @exception = { 'sitemap' + conf['ext'] => 1, 'recent_update' + conf['ext'] => 1, } register_helper register_macro @html_line_visitor = HtmlLine.new(self) if !File.directory?(conf['output_top']) FileUtils.mkdir_p(conf['output_top']) end copy_to_output_top('prototype.js') copy_to_output_top('juli.js') copy_to_output_top('juli.css') end
Private Class Methods
Similar to Rails underscore() method.
Example: 'A::B::HelperMethod' -> 'helper_method'
# File lib/juli/visitor/html.rb, line 252 def self.to_method(helper_class) Juli::Util::underscore(helper_class.to_s) end
Public Instance Methods
run in bulk-mode. In Html
visitor, it sync juli-repository and OUTPUT_TOP.
# File lib/juli/visitor/html.rb, line 134 def run_bulk sync end
visit root to generate:
- 1st
-
HTML body
- 2nd
-
whole HTML by ERB.
# File lib/juli/visitor/html.rb, line 142 def run_file(in_file, root) @header_sequence = HeaderSequence.new IdAssigner.new.run(in_file, root) for key, helper in @_helpers do helper.on_root(in_file, root, self) end for macro_symbol, macro in @macros do macro.on_root(in_file, root, self) end # store to instance var for 'contents' helper @root = root title = File.basename(in_file.gsub(/\.[^.]*$/, '')) prototype = relative_from(in_file, 'prototype.js') javascript = relative_from(in_file, 'juli.js') stylesheet = relative_from(in_file, 'juli.css') sitemap = relative_from(in_file, 'sitemap' + conf['ext']) @wikiname_visited = {} body = root.accept(self) for macro_symbol, macro in @macros do macro.after_root(in_file, root) end erb = ERB.new(File.read(template)) out_path = out_filename(in_file, @opts[:o]) mkdir(out_path) File.open(out_path, 'w') do |f| f.write(erb.result(binding)) end printf("generated: %s\n", out_path) end
# File lib/juli/visitor/html.rb, line 244 def template=(name) @template = name end
# File lib/juli/visitor/html.rb, line 195 def visit_array(n) n.array.inject(''){|result, child| result += child.accept(self) } end
# File lib/juli/visitor/html.rb, line 201 def visit_chapter(n) header_link(n) + content_tag(:div, :id=>n.dom_id) do n.blocks.accept(self) end + "\n" end
# File lib/juli/visitor/html.rb, line 216 def visit_compact_dictionary_list(n) content_tag(:table, :class=>'juli_compact_dictionary') do n.array.inject('') do |result, child| result += child.accept(self) end end end
# File lib/juli/visitor/html.rb, line 224 def visit_compact_dictionary_list_item(n) content_tag(:tr) do content_tag(:td, str2html(n.term) + ':', :nowrap=>true) + content_tag(:td, str2html(n.str)) end end
# File lib/juli/visitor/html.rb, line 231 def visit_dictionary_list(n) content_tag(:dl, :class=>'juli_dictionary') do n.array.inject('') do |result, child| result += child.accept(self) end end end
# File lib/juli/visitor/html.rb, line 239 def visit_dictionary_list_item(n) content_tag(:dt, str2html(n.term), dt_css) + content_tag(:dd, str2html(n.str), dd_css) end
# File lib/juli/visitor/html.rb, line 208 def visit_ordered_list(n) visit_list(:ol, n) end
if str is in list, don't enclose by <p>
# File lib/juli/visitor/html.rb, line 177 def visit_str(n) if n.parent && n.parent.parent && n.parent.parent.is_a?(Juli::Absyn::List) str2html(n.str) else content_tag(:p, paragraph_css) do str2html(n.str) end end end
# File lib/juli/visitor/html.rb, line 212 def visit_unordered_list(n) visit_list(:ul, n) end
# File lib/juli/visitor/html.rb, line 188 def visit_verbatim(n) # quote; trim last white spaces at generating phase content_tag(:blockquote, content_tag(:pre, n.str.gsub(/\s+\z/m, '')), blockquote_css) end
Private Instance Methods
# File lib/juli/visitor/html.rb, line 411 def blockquote_css {} end
# File lib/juli/visitor/html.rb, line 256 def copy_to_output_top(file) src = File.join(Juli::TEMPLATE_PATH, file) dest = File.join(conf['output_top'], file) return if File.exist?(dest) && File.stat(dest).mtime >= File.stat(src).mtime FileUtils.cp(src, dest, :preserve=>true) end
default dictionary list item description part CSS
# File lib/juli/visitor/html.rb, line 425 def dd_css {} end
default dictionary list item term part CSS
# File lib/juli/visitor/html.rb, line 420 def dt_css {} end
draw <hi>… link, where i=2..7
When conf is true(=default), toggle-button to show/hide indent is drown.
NOTE: <h1> is reserved for title. <h2>, <h3>, … are used for Juli
formatting '=', '==', …
# File lib/juli/visitor/html.rb, line 374 def header_link(n) id = n.dom_id content_tag("h#{n.level + 1}", :id=>header_id(n)) do content_tag(:span, :class=>'juli_toggle', :onclick=>"Juli.toggle('#{id}');") do if conf['show_indent_toggle_button'] content_tag(:span, '[+] ', :id=>"#{id}_p", :class=>'juli_toggle_node', :style=>'display:none;') + content_tag(:span, '[-] ', :id=>"#{id}_m", :class=>'juli_toggle_node') else '' end + @header_sequence.gen(n.level) + '. ' + n.str end end + "\n" end
# File lib/juli/visitor/html.rb, line 415 def list_item_css {} end
# File lib/juli/visitor/html.rb, line 407 def paragraph_css {:class=>'default'} end
register each XHelper instance in @_helpers hash.
# File lib/juli/visitor/html.rb, line 265 def register_helper @_helpers = {} for helper_symbol in Juli::Visitor::Html::Helper.constants do next if helper_symbol == :AbstractHelper helper_class = Juli::Visitor::Html.module_eval(helper_symbol.to_s) helper = helper_class.new helper.set_conf_default(conf) @_helpers[helper_symbol.to_sym] = helper end end
create Macro object and register it in @macros hash.
call set_conf_default() to set conf default value for each macro
# File lib/juli/visitor/html.rb, line 291 def register_macro @macros = {} for macro_symbol in Juli::Macro.constants do next if macro_symbol == :Base macro_class = Juli::Macro.module_eval(macro_symbol.to_s) macro = macro_class.new macro.set_conf_default(conf) @macros[macro_symbol] = macro end end
-
parse str and build
Juli::LineAbsyn
tree -
visit the tree by
HtmlLine
and generate HTML
# File lib/juli/visitor/html.rb, line 401 def str2html(str) Juli::LineParser.new.parse( str, Juli::Wiki.wikinames).accept(@html_line_visitor) end
synchronize repository and OUTPUT_TOP.
-
if text file, calls
sync_txt
() -
for others, do rsync(1)
# File lib/juli/visitor/html.rb, line 307 def sync sync_txt sync_others end
# File lib/juli/visitor/html.rb, line 312 def sync_others Dir.chdir(juli_repo){ system 'rsync', '-avuzb', '--exclude', '*.txt', '--exclude', 'html/', '--exclude', '*~', '--exclude', '.juli/', '--exclude', '.git*', '.', conf['output_top'] } end
synchronize text file between juli-repo and OUTPUT_TOP:
-
new file exists, generate it.
-
repo's file timestamp is newer than the one under OUTPUT_TOP, regenerate it.
-
correspondent file of OUTPUT_TOP/…/f doesn't exist in repo and not in @exception list above, delete it.
-
if -f option is specified, don't check timestamp and always generates.
# File lib/juli/visitor/html.rb, line 332 def sync_txt repo = {} Dir.chdir(juli_repo){ Dir.glob('**/*.txt'){|f| repo[f] = 1 } } # When new file exists, generate it. # When repo's file timestamp is newer than OUTPUT_TOP, regenerate it. for f,v in repo do out_file = out_filename(f, @opts[:o]) if !@opts[:f] && File.exist?(out_file) && File.stat(out_file).mtime >= File.stat(File.join(juli_repo,f)).mtime #printf("already updated: %s\n", out_file) else Juli::Parser.new.parse(f, self) end end # When correspondent file of OUTPUT_TOP/.../f doesn't exist in repo, # and not in @exception list above, delete it. Dir.chdir(conf['output_top']){ Dir.glob('**/*' + conf['ext']){|f| next if @exception[f] in_file = File.join(juli_repo, in_filename(f)) if !File.exist?(in_file) && !File.exist?(in_file + '.txt') FileUtils.rm(f) printf("%s is deleted since no correspondent source text.\n", f) end } } end
return specified template.
-
If 'template' macro is used, it is used rather than defined at conf file.
-
Then, find_template() algorithm is used.
Total template search logic is described in template(macro) document.
# File lib/juli/visitor/html.rb, line 436 def template find_template(@template || conf['template'], @opts[:t]) end
# File lib/juli/visitor/html.rb, line 389 def visit_list(tag, n, options={}) content_tag(tag, options) do n.array.inject('') do |result, child| result += content_tag(:li, list_item_css) do child.accept(self) end end end end