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

macros[RW]
wikiname_visited[RW]

Public Class Methods

new(opts={}) click to toggle source

Html sepecific initialization does:

  1. create output_top.

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

Calls superclass method 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

to_method(helper_class) click to toggle source

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_bulk() click to toggle source

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
run_file(in_file, root) click to toggle source

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
template=(name) click to toggle source
# File lib/juli/visitor/html.rb, line 244
def template=(name)
  @template = name
end
visit_array(n) click to toggle source
# File lib/juli/visitor/html.rb, line 195
def visit_array(n)
  n.array.inject(''){|result, child|
    result += child.accept(self)
  }
end
visit_chapter(n) click to toggle source
# 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
visit_compact_dictionary_list(n) click to toggle source
# 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
visit_compact_dictionary_list_item(n) click to toggle source
# 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
visit_dictionary_list(n) click to toggle source
# 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
visit_dictionary_list_item(n) click to toggle source
# 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
visit_ordered_list(n) click to toggle source
# File lib/juli/visitor/html.rb, line 208
def visit_ordered_list(n)
  visit_list(:ol, n)
end
visit_str(n) click to toggle source

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
visit_unordered_list(n) click to toggle source
# File lib/juli/visitor/html.rb, line 212
def visit_unordered_list(n)
  visit_list(:ul, n)
end
visit_verbatim(n) click to toggle source
# 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

blockquote_css() click to toggle source
# File lib/juli/visitor/html.rb, line 411
def blockquote_css
  {}
end
copy_to_output_top(file) click to toggle source
# 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
dd_css() click to toggle source

default dictionary list item description part CSS

# File lib/juli/visitor/html.rb, line 425
def dd_css
  {}
end
dt_css() click to toggle source

default dictionary list item term part CSS

# File lib/juli/visitor/html.rb, line 420
def dt_css
  {}
end
list_item_css() click to toggle source
# File lib/juli/visitor/html.rb, line 415
def list_item_css
  {}
end
paragraph_css() click to toggle source
# File lib/juli/visitor/html.rb, line 407
def paragraph_css
  {:class=>'default'}
end
register_helper() click to toggle source

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
register_macro() click to toggle source

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
str2html(str) click to toggle source
  1. parse str and build Juli::LineAbsyn tree

  2. 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
sync() click to toggle source

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
sync_others() click to toggle source
# 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
sync_txt() click to toggle source

synchronize text file between juli-repo and OUTPUT_TOP:

  1. new file exists, generate it.

  2. repo's file timestamp is newer than the one under OUTPUT_TOP, regenerate it.

  3. correspondent file of OUTPUT_TOP/…/f doesn't exist in repo and not in @exception list above, delete it.

  4. 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
template() click to toggle source

return specified template.

  1. If 'template' macro is used, it is used rather than defined at conf file.

  2. 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
visit_list(tag, n, options={}) click to toggle source
# 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