juli 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.rdoc +39 -0
- data/Rakefile +89 -0
- data/bin/console +14 -0
- data/bin/je +73 -0
- data/bin/juli +82 -0
- data/bin/juli_tb.rb +76 -0
- data/bin/setup +7 -0
- data/juli.gemspec +29 -0
- data/lib/juli.rb +21 -0
- data/lib/juli/absyn.rb +206 -0
- data/lib/juli/command.rb +180 -0
- data/lib/juli/command/file_entry.rb +12 -0
- data/lib/juli/command/recent_update.rb +52 -0
- data/lib/juli/command/sitemap.rb +55 -0
- data/lib/juli/command/tag.rb +81 -0
- data/lib/juli/line_parser.y +212 -0
- data/lib/juli/macro.rb +39 -0
- data/lib/juli/macro/amazon.rb +33 -0
- data/lib/juli/macro/jmap.rb +38 -0
- data/lib/juli/macro/photo.rb +161 -0
- data/lib/juli/macro/tag.rb +136 -0
- data/lib/juli/macro/template.rb +37 -0
- data/lib/juli/macro/template_base.rb +44 -0
- data/lib/juli/macro/wikipedia.rb +19 -0
- data/lib/juli/parser.y +360 -0
- data/lib/juli/template/default.html +64 -0
- data/lib/juli/template/facebook.html +82 -0
- data/lib/juli/template/je-bash-complete +42 -0
- data/lib/juli/template/juli.css +173 -0
- data/lib/juli/template/juli.js +87 -0
- data/lib/juli/template/locale/en.yml +10 -0
- data/lib/juli/template/locale/ja.yml +10 -0
- data/lib/juli/template/prototype.js +4320 -0
- data/lib/juli/template/simple.html +45 -0
- data/lib/juli/template/sitemap.html +78 -0
- data/lib/juli/template/sitemap_order_by_mtime_DESC.html +78 -0
- data/lib/juli/template/slidy.html +126 -0
- data/lib/juli/template/sourceforge.html +71 -0
- data/lib/juli/template/takahashi_method.html +116 -0
- data/lib/juli/util.rb +255 -0
- data/lib/juli/util/juli_i18n.rb +32 -0
- data/lib/juli/version.rb +3 -0
- data/lib/juli/visitor.rb +12 -0
- data/lib/juli/visitor/html.rb +462 -0
- data/lib/juli/visitor/html/helper.rb +97 -0
- data/lib/juli/visitor/html/helper/contents.rb +76 -0
- data/lib/juli/visitor/html/helper/fb_comments.rb +68 -0
- data/lib/juli/visitor/html/helper/fb_like.rb +37 -0
- data/lib/juli/visitor/html/tag_helper.rb +40 -0
- data/lib/juli/visitor/slidy.rb +39 -0
- data/lib/juli/visitor/takahashi_method.rb +41 -0
- data/lib/juli/visitor/tree.rb +135 -0
- data/lib/juli/wiki.rb +52 -0
- data/sample/protected_photo/2012-04-22/DCIM/101_PANA/P1010441.JPG +0 -0
- data/sample/update_public_juli.rb +71 -0
- data/setup.rb +1585 -0
- metadata +211 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
|
3
|
+
class Juli::Visitor::Html
|
4
|
+
# This provides methods used in HTML Erb; called 'helper'.
|
5
|
+
#
|
6
|
+
# Any method here can be used at ERB template under LIB/juli/template/.
|
7
|
+
# Where, LIB is 'lib/' directory in package environment, or
|
8
|
+
# one of $LOAD_PATH in installed environment.
|
9
|
+
#
|
10
|
+
# === How to add new helper(1)
|
11
|
+
# If new method is added in this module, it can be used as helper at
|
12
|
+
# template ERB file. This is the simplest case.
|
13
|
+
#
|
14
|
+
# === How to add new helper(2)
|
15
|
+
# If some preparation is required before calling helper, above way is not
|
16
|
+
# enough. For example, recent_update() helper requires file list
|
17
|
+
# which is sorted by descendant order of mtime timestamp.
|
18
|
+
# It is time-consuming task to prepare such a file list on every
|
19
|
+
# recent_update() calling. It is enough to do that only once when juli(1)
|
20
|
+
# is executed.
|
21
|
+
#
|
22
|
+
# Another example: if the same helper is called more than once in one
|
23
|
+
# template, it could be effective to reduce the CPU resource to
|
24
|
+
# prepare some data and store it in the helper class instance then
|
25
|
+
# each helper uses it just to print the result.
|
26
|
+
#
|
27
|
+
# Juli supports such a case. Let me assume here to write
|
28
|
+
# 'weather_forecast' helper, which draws some local area's
|
29
|
+
# one week weather forecast (juli(1) is offline wiki so that
|
30
|
+
# this kind of realtime information is not a good example though...).
|
31
|
+
# Follow the steps below:
|
32
|
+
# 1. Write WeatherForecast helper class file as
|
33
|
+
# LIB/juli/visitor/html/helper/weather_forecast.rb.
|
34
|
+
# (recent_update.rb could be a reference for this.)
|
35
|
+
# 1. WeatherForecast should inherit
|
36
|
+
# Juli::Visitor::Html::Helper::AbstractHelper.
|
37
|
+
# 1. implement each method: initialize, on_root, run.
|
38
|
+
#
|
39
|
+
# Then, weather_forecast method can be used in ERB template.
|
40
|
+
# This method is dynamically defined at Html visitor and equivalent
|
41
|
+
# to WeatherForecast#run.
|
42
|
+
#
|
43
|
+
module Helper
|
44
|
+
class AbstractHelper
|
45
|
+
include Juli::Util
|
46
|
+
|
47
|
+
# called on 'juli init' to generate config sample template.
|
48
|
+
def self.conf_template
|
49
|
+
''
|
50
|
+
end
|
51
|
+
|
52
|
+
# called when juli(1) starts.
|
53
|
+
def initialize
|
54
|
+
end
|
55
|
+
|
56
|
+
# called on setting up conf to set default key=val
|
57
|
+
def set_conf_default(conf)
|
58
|
+
end
|
59
|
+
|
60
|
+
# called on each parsed document
|
61
|
+
def on_root(in_file, root, visitor)
|
62
|
+
end
|
63
|
+
|
64
|
+
# This will be a helper like 'abstract_helper(args)'
|
65
|
+
def run(*args)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# TRICKY PART: header_id is used for 'contents' helper link.
|
70
|
+
# Absyn::HeaderNode.dom_id cannot be used directory for
|
71
|
+
# this purpose since when clicking a header of 'contents',
|
72
|
+
# document jumps to its contents rather than header so that
|
73
|
+
# header is hidden on browser. To resolve this, header_id
|
74
|
+
# is required for 'contents' helper and it is set at Html visitor.
|
75
|
+
def header_id(n)
|
76
|
+
"#{n.dom_id}_header"
|
77
|
+
end
|
78
|
+
|
79
|
+
# dest's relative path from src
|
80
|
+
#
|
81
|
+
# === EXAMPLE
|
82
|
+
# relative_from('a.txt', 'juli.js'):: → './juli.js'
|
83
|
+
# relative_from('a/b.txt', 'juli.js'):: → '../juli.js'
|
84
|
+
def relative_from(src, dest)
|
85
|
+
result = []
|
86
|
+
Pathname.new(File.dirname(src)).descend{|dir|
|
87
|
+
result << (dir.to_s == '.' ? '.' : '..')
|
88
|
+
}
|
89
|
+
File.join(result, dest)
|
90
|
+
end
|
91
|
+
|
92
|
+
# import all of helper/*.rb files
|
93
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'helper/*.rb')){|v|
|
94
|
+
require File.join('juli/visitor/html/helper', File.basename(v))
|
95
|
+
}
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Juli::Visitor::Html::Helper
|
2
|
+
# Helper-class for 'contents' helper
|
3
|
+
class Contents < AbstractHelper
|
4
|
+
# Check if chapter exists or not
|
5
|
+
class ChapterChecker < Juli::Absyn::Visitor
|
6
|
+
attr_accessor :chapter_exists
|
7
|
+
|
8
|
+
def initialize(opts = {})
|
9
|
+
@chapter_exists = false
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def visit_chapter(n)
|
14
|
+
@chapter_exists = true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ContentsDrawer < Juli::Absyn::Visitor
|
19
|
+
include Juli::Visitor::Html::TagHelper
|
20
|
+
include Juli::Visitor::Html::Helper
|
21
|
+
|
22
|
+
def visit_node(n); ''; end
|
23
|
+
def visit_str(n); ''; end
|
24
|
+
def visit_verbatim(n); ''; end
|
25
|
+
def visit_ordered_list(n); ''; end
|
26
|
+
def visit_unordered_list(n); ''; end
|
27
|
+
def visit_compact_dictionary_list(n); ''; end
|
28
|
+
def visit_compact_dictionary_list_item(n); ''; end
|
29
|
+
def visit_dictionary_list(n); ''; end
|
30
|
+
def visit_dictionary_list_item(n); ''; end
|
31
|
+
|
32
|
+
def visit_array(n)
|
33
|
+
n.array.inject(''){|result, child|
|
34
|
+
result += child.accept(self)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def visit_chapter(n)
|
39
|
+
content_tag(:li) do
|
40
|
+
content_tag(:a, :href=>'#' + header_id(n)) do
|
41
|
+
n.str
|
42
|
+
end +
|
43
|
+
content_tag(:ol) do
|
44
|
+
n.blocks.accept(self)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# called on each parsed document
|
51
|
+
def on_root(in_file, root, visitor = nil)
|
52
|
+
@root = root
|
53
|
+
end
|
54
|
+
|
55
|
+
# implementation of:
|
56
|
+
# contents
|
57
|
+
#
|
58
|
+
# which draws contents(a.k.a. outline) of this document.
|
59
|
+
#
|
60
|
+
# This visits document tree by ContentsDrawer visitor and
|
61
|
+
# generate HTML contents list.
|
62
|
+
def run(*args)
|
63
|
+
contents_drawer = ContentsDrawer.new
|
64
|
+
chapter_checker = ChapterChecker.new
|
65
|
+
@root.accept(chapter_checker)
|
66
|
+
if chapter_checker.chapter_exists
|
67
|
+
contents_drawer.content_tag(:b, I18n.t('contents')) +
|
68
|
+
contents_drawer.content_tag(:ol) do
|
69
|
+
@root.accept(contents_drawer)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
''
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Juli::Visitor::Html::Helper
|
2
|
+
# Helper-class for 'fb_like' helper
|
3
|
+
class FbComments < AbstractHelper
|
4
|
+
# default HTML template for facebook 'like' button.
|
5
|
+
# You can customize it in .juli/config facebook.like.template entry.
|
6
|
+
#
|
7
|
+
# %{href} in the template will be replaced to the actual URL of
|
8
|
+
# current wiki page.
|
9
|
+
DEFAULT_TEMPLATE =
|
10
|
+
'<fb:comments href="%{href}" num_posts="2" width="470">' +
|
11
|
+
'</fb:comments>'
|
12
|
+
|
13
|
+
# called on 'juli init' to generate config sample template.
|
14
|
+
def self.conf_template
|
15
|
+
<<EOM
|
16
|
+
# Facebook related setup is here.
|
17
|
+
#
|
18
|
+
#url_prefix: 'http://YOUR_HOST/juli'
|
19
|
+
#facebook:
|
20
|
+
# like:
|
21
|
+
# template: '#{Juli::Visitor::Html::Helper::FbLike::DEFAULT_TEMPLATE}'
|
22
|
+
# comments:
|
23
|
+
# template: '#{DEFAULT_TEMPLATE}'
|
24
|
+
EOM
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@fb_conf = conf['facebook']
|
29
|
+
end
|
30
|
+
|
31
|
+
# set default value in conf if no .juli/conf defined.
|
32
|
+
#
|
33
|
+
# Please overwrite this method when this implementation is not your
|
34
|
+
# case.
|
35
|
+
def set_conf_default(conf)
|
36
|
+
conf['url_prefix'] = 'http://YOUR_HOST/juli' if !conf['url_prefix']
|
37
|
+
conf['facebook'] = {} if !conf['facebook']
|
38
|
+
if !conf['facebook']['comments']
|
39
|
+
conf['facebook']['comments'] = {
|
40
|
+
'template' => self.class::DEFAULT_TEMPLATE
|
41
|
+
}
|
42
|
+
end
|
43
|
+
if !conf['facebook']['like']
|
44
|
+
conf['facebook']['like'] = {
|
45
|
+
'template' => Juli::Visitor::Html::Helper::FbLike::DEFAULT_TEMPLATE
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# called on each parsed document
|
51
|
+
def on_root(in_file, root, visitor = nil)
|
52
|
+
@in_file = in_file
|
53
|
+
end
|
54
|
+
|
55
|
+
def run(*args)
|
56
|
+
raise Juli::NoConfig if !conf['url_prefix']
|
57
|
+
raise Juli::NoConfig if !@in_file
|
58
|
+
|
59
|
+
template.gsub('%{href}',
|
60
|
+
conf['url_prefix'] + '/' + to_wikiname(@in_file) + conf['ext'])
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def template
|
65
|
+
@fb_conf['comments']['template']
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Juli::Visitor::Html::Helper
|
2
|
+
# Helper-class for 'fb_like' helper
|
3
|
+
class FbLike < AbstractHelper
|
4
|
+
# default HTML template for facebook 'like' button.
|
5
|
+
# You can customize it in .juli/config facebook.like.template entry.
|
6
|
+
#
|
7
|
+
# %{href} in the template will be replaced to the actual URL of
|
8
|
+
# current wiki page.
|
9
|
+
DEFAULT_TEMPLATE =
|
10
|
+
'<fb:like href="%{href}" ' +
|
11
|
+
'send="false" layout="button_count" width="450" ' +
|
12
|
+
'show_faces="false">' +
|
13
|
+
'</fb:like>'
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@fb_conf = conf['facebook']
|
17
|
+
end
|
18
|
+
|
19
|
+
# called on each parsed document
|
20
|
+
def on_root(in_file, root, visitor = nil)
|
21
|
+
@in_file = in_file
|
22
|
+
end
|
23
|
+
|
24
|
+
def run(*args)
|
25
|
+
raise Juli::NoConfig if !conf['url_prefix']
|
26
|
+
raise Juli::NoConfig if !@in_file
|
27
|
+
|
28
|
+
template.gsub('%{href}',
|
29
|
+
conf['url_prefix'] + '/' + to_wikiname(@in_file) + conf['ext'])
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def template
|
34
|
+
@fb_conf['like']['template']
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Juli::Visitor::Html
|
2
|
+
# copied from Rails
|
3
|
+
module TagHelper
|
4
|
+
def tag(name, options = nil, open = false)
|
5
|
+
"<#{name}#{tag_options(options) if options}#{open ? ">" : " />"}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def content_tag(name, content_or_options_with_block = nil, options = nil, &block)
|
9
|
+
if block_given?
|
10
|
+
options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
|
11
|
+
content_tag_string(name, block.call, options)
|
12
|
+
else
|
13
|
+
content_tag_string(name, content_or_options_with_block, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked)
|
19
|
+
BOOLEAN_ATTRIBUTES << BOOLEAN_ATTRIBUTES.map{|s| s.to_sym}
|
20
|
+
|
21
|
+
def content_tag_string(name, content, options)
|
22
|
+
tag_options = tag_options(options) if options
|
23
|
+
"<#{name}#{tag_options}>#{content}</#{name}>"
|
24
|
+
end
|
25
|
+
|
26
|
+
def tag_options(options)
|
27
|
+
if options != {}
|
28
|
+
attrs = []
|
29
|
+
options.each_pair do |key, value|
|
30
|
+
if BOOLEAN_ATTRIBUTES.include?(key)
|
31
|
+
attrs << key if value
|
32
|
+
else
|
33
|
+
attrs << %(#{key}="#{value}") if !value.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
" #{attrs.sort * ' '}" unless attrs.empty?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Juli::Visitor
|
2
|
+
# This visits Absyn tree and generates HTML for Slideshow.
|
3
|
+
#
|
4
|
+
# Text files under juli-repository must have '.txt' extention.
|
5
|
+
#
|
6
|
+
# Almost all are the same as Html VISITOR.
|
7
|
+
#
|
8
|
+
# === OPTIONS
|
9
|
+
# -t template:: specify template
|
10
|
+
class Slidy < Html
|
11
|
+
# bulk-mode for slideshow generation doesn't make sense so that
|
12
|
+
# it just warns and return quickly.
|
13
|
+
def run_bulk
|
14
|
+
STDERR.printf("bulk-mode in Slidy is not supported.\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
# overwrite to:
|
18
|
+
# * add 'slide' stylesheet-class at level==1
|
19
|
+
# * include all contents in 'slide' stylesheet-class even title
|
20
|
+
def visit_chapter(n)
|
21
|
+
attr = {:id=>n.dom_id}
|
22
|
+
if n.level==1
|
23
|
+
attr.merge!(:class=>'slide')
|
24
|
+
end
|
25
|
+
content_tag(:div, attr) do
|
26
|
+
header_link(n) +
|
27
|
+
n.blocks.accept(self)
|
28
|
+
end + "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
# overwrite to generate simple <h#>...</h#>
|
33
|
+
def header_link(n)
|
34
|
+
content_tag("h#{n.level + 1}") do
|
35
|
+
@header_sequence.gen(n.level) + '. ' + n.str
|
36
|
+
end + "\n"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Juli::Visitor
|
2
|
+
# This visits Absyn tree and generates HTML for
|
3
|
+
# 'Takahashi method' slideshow.
|
4
|
+
#
|
5
|
+
# Text files under juli-repository must have '.txt' extention.
|
6
|
+
#
|
7
|
+
# Almost all are the same as Html VISITOR.
|
8
|
+
#
|
9
|
+
# === OPTIONS
|
10
|
+
# -t template:: specify template
|
11
|
+
class TakahashiMethod < Html
|
12
|
+
# bulk-mode in TakahashiMethod doesn't make sense so that
|
13
|
+
# it just warns and return quickly.
|
14
|
+
def run_bulk
|
15
|
+
STDERR.printf("bulk-mode in TakahashiMethod is not supported.\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
# overwrite to generate simple <h# class=slide>...</h#>
|
20
|
+
def header_link(n)
|
21
|
+
content_tag("h#{n.level + 1}", :class=>'slide') do
|
22
|
+
@header_sequence.gen(n.level) + '. ' + n.str
|
23
|
+
end + "\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
# specify paragraph css
|
27
|
+
def paragraph_css
|
28
|
+
{:class=>'default slide'}
|
29
|
+
end
|
30
|
+
|
31
|
+
# specify blockquote css
|
32
|
+
def blockquote_css
|
33
|
+
{:class=>'slide'}
|
34
|
+
end
|
35
|
+
|
36
|
+
# specify list item css
|
37
|
+
def list_item_css
|
38
|
+
{:class=>'slide'}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'juli/absyn'
|
2
|
+
require 'juli/util'
|
3
|
+
require 'juli/line_parser.tab'
|
4
|
+
|
5
|
+
module Juli::Visitor
|
6
|
+
class LineTree < Juli::LineAbsyn::Visitor
|
7
|
+
include Juli::Util
|
8
|
+
|
9
|
+
def initialize(depth)
|
10
|
+
@depth = depth
|
11
|
+
end
|
12
|
+
|
13
|
+
def print_depth
|
14
|
+
print '| ' * @depth
|
15
|
+
end
|
16
|
+
|
17
|
+
def visit_string(n)
|
18
|
+
print_depth
|
19
|
+
printf "str: %s\n", str_trim(n.str)
|
20
|
+
end
|
21
|
+
|
22
|
+
def visit_wikiname(n)
|
23
|
+
print_depth
|
24
|
+
printf "wiki: %s\n", str_trim(n.str)
|
25
|
+
end
|
26
|
+
|
27
|
+
def visit_url(n)
|
28
|
+
print_depth
|
29
|
+
printf "url: %s\n", str_trim(n.str)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Another VISITOR-pattern for Absyn tree to print tree
|
34
|
+
# structure around each node.
|
35
|
+
class Tree < Juli::Absyn::Visitor
|
36
|
+
include Juli::Util
|
37
|
+
|
38
|
+
# visit root to generate absyn-tree structure.
|
39
|
+
def run_file(in_file, root)
|
40
|
+
@depth = 0
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
def visit_str(n)
|
45
|
+
print_depth
|
46
|
+
printf("StrNode(%d)\n", -1)
|
47
|
+
@depth += 1
|
48
|
+
process_str(n.str)
|
49
|
+
@depth -= 1
|
50
|
+
end
|
51
|
+
|
52
|
+
def visit_verbatim(n)
|
53
|
+
print_depth
|
54
|
+
printf("verbatim: %s\n", str_trim(n.str))
|
55
|
+
end
|
56
|
+
|
57
|
+
def visit_array(n)
|
58
|
+
print_depth
|
59
|
+
printf("Array\n")
|
60
|
+
@depth += 1
|
61
|
+
for child in n.array do
|
62
|
+
child.accept(self)
|
63
|
+
end
|
64
|
+
@depth -= 1
|
65
|
+
end
|
66
|
+
|
67
|
+
def visit_chapter(n)
|
68
|
+
print_depth
|
69
|
+
printf("Chapter(%d %s)\n", n.level, n.str)
|
70
|
+
@depth += 1
|
71
|
+
n.blocks.accept(self)
|
72
|
+
@depth -= 1
|
73
|
+
end
|
74
|
+
|
75
|
+
def visit_ordered_list(n)
|
76
|
+
visit_list("OrderedList\n", n)
|
77
|
+
end
|
78
|
+
|
79
|
+
def visit_unordered_list(n)
|
80
|
+
visit_list("UnorderedList\n", n)
|
81
|
+
end
|
82
|
+
|
83
|
+
def visit_compact_dictionary_list(n)
|
84
|
+
visit_list("CompactDictionaryList\n", n)
|
85
|
+
end
|
86
|
+
|
87
|
+
def visit_compact_dictionary_list_item(n)
|
88
|
+
visit_x_dictionary_list_item(n, "CompactDictionaryListItem\n")
|
89
|
+
end
|
90
|
+
|
91
|
+
def visit_dictionary_list(n)
|
92
|
+
visit_list("DictionaryList\n", n)
|
93
|
+
end
|
94
|
+
|
95
|
+
def visit_dictionary_list_item(n)
|
96
|
+
visit_x_dictionary_list_item(n, "DictionaryListItem\n")
|
97
|
+
end
|
98
|
+
|
99
|
+
def visit_quote(n)
|
100
|
+
print_depth
|
101
|
+
printf("QuoteNode(%s)\n", str_trim(n.str))
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
def print_depth
|
106
|
+
print '| ' * @depth
|
107
|
+
end
|
108
|
+
|
109
|
+
def visit_list(class_str, n)
|
110
|
+
print_depth
|
111
|
+
printf(class_str)
|
112
|
+
@depth += 1
|
113
|
+
for child in n.array do
|
114
|
+
child.accept(self)
|
115
|
+
end
|
116
|
+
@depth -= 1
|
117
|
+
end
|
118
|
+
|
119
|
+
# common for both dictionary list item and compact dictionary list item
|
120
|
+
def visit_x_dictionary_list_item(n, node_name)
|
121
|
+
print_depth
|
122
|
+
printf(node_name)
|
123
|
+
@depth += 1
|
124
|
+
process_str(n.term)
|
125
|
+
process_str(n.str)
|
126
|
+
@depth -= 1
|
127
|
+
end
|
128
|
+
|
129
|
+
# str -> Juli::LineAbsyn -> print with depth
|
130
|
+
def process_str(str)
|
131
|
+
Juli::LineParser.new.parse(str, Juli::Wiki.wikinames).
|
132
|
+
accept(LineTree.new(@depth))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|