juli 2.0.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 (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +26 -0
  3. data/CODE_OF_CONDUCT.md +13 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.rdoc +39 -0
  7. data/Rakefile +89 -0
  8. data/bin/console +14 -0
  9. data/bin/je +73 -0
  10. data/bin/juli +82 -0
  11. data/bin/juli_tb.rb +76 -0
  12. data/bin/setup +7 -0
  13. data/juli.gemspec +29 -0
  14. data/lib/juli.rb +21 -0
  15. data/lib/juli/absyn.rb +206 -0
  16. data/lib/juli/command.rb +180 -0
  17. data/lib/juli/command/file_entry.rb +12 -0
  18. data/lib/juli/command/recent_update.rb +52 -0
  19. data/lib/juli/command/sitemap.rb +55 -0
  20. data/lib/juli/command/tag.rb +81 -0
  21. data/lib/juli/line_parser.y +212 -0
  22. data/lib/juli/macro.rb +39 -0
  23. data/lib/juli/macro/amazon.rb +33 -0
  24. data/lib/juli/macro/jmap.rb +38 -0
  25. data/lib/juli/macro/photo.rb +161 -0
  26. data/lib/juli/macro/tag.rb +136 -0
  27. data/lib/juli/macro/template.rb +37 -0
  28. data/lib/juli/macro/template_base.rb +44 -0
  29. data/lib/juli/macro/wikipedia.rb +19 -0
  30. data/lib/juli/parser.y +360 -0
  31. data/lib/juli/template/default.html +64 -0
  32. data/lib/juli/template/facebook.html +82 -0
  33. data/lib/juli/template/je-bash-complete +42 -0
  34. data/lib/juli/template/juli.css +173 -0
  35. data/lib/juli/template/juli.js +87 -0
  36. data/lib/juli/template/locale/en.yml +10 -0
  37. data/lib/juli/template/locale/ja.yml +10 -0
  38. data/lib/juli/template/prototype.js +4320 -0
  39. data/lib/juli/template/simple.html +45 -0
  40. data/lib/juli/template/sitemap.html +78 -0
  41. data/lib/juli/template/sitemap_order_by_mtime_DESC.html +78 -0
  42. data/lib/juli/template/slidy.html +126 -0
  43. data/lib/juli/template/sourceforge.html +71 -0
  44. data/lib/juli/template/takahashi_method.html +116 -0
  45. data/lib/juli/util.rb +255 -0
  46. data/lib/juli/util/juli_i18n.rb +32 -0
  47. data/lib/juli/version.rb +3 -0
  48. data/lib/juli/visitor.rb +12 -0
  49. data/lib/juli/visitor/html.rb +462 -0
  50. data/lib/juli/visitor/html/helper.rb +97 -0
  51. data/lib/juli/visitor/html/helper/contents.rb +76 -0
  52. data/lib/juli/visitor/html/helper/fb_comments.rb +68 -0
  53. data/lib/juli/visitor/html/helper/fb_like.rb +37 -0
  54. data/lib/juli/visitor/html/tag_helper.rb +40 -0
  55. data/lib/juli/visitor/slidy.rb +39 -0
  56. data/lib/juli/visitor/takahashi_method.rb +41 -0
  57. data/lib/juli/visitor/tree.rb +135 -0
  58. data/lib/juli/wiki.rb +52 -0
  59. data/sample/protected_photo/2012-04-22/DCIM/101_PANA/P1010441.JPG +0 -0
  60. data/sample/update_public_juli.rb +71 -0
  61. data/setup.rb +1585 -0
  62. metadata +211 -0
@@ -0,0 +1,12 @@
1
+ module Juli
2
+ module Command
3
+ # used in both Juli::Command::Sitemap Juli::Command::RecentUpdate
4
+ class FileEntry
5
+ attr_accessor :path, :mtime
6
+ def initialize(path, mtime)
7
+ @path = path
8
+ @mtime = mtime
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,52 @@
1
+ module Juli::Command
2
+ # generate recent_updates.shtml which lists recent updated entries.
3
+ # The file is for server-side-include(SSI).
4
+ class RecentUpdate
5
+ include Juli::Util
6
+ include Juli::Visitor::Html::TagHelper
7
+
8
+ # define maximum file limit in order to reduce process time.
9
+ FILE_LIMIT = 20
10
+
11
+ # cache recent_update
12
+ def initialize
13
+ @file = []
14
+ Dir.chdir(juli_repo){
15
+ Dir.glob('**/*.txt'){|f|
16
+ @file << FileEntry.new(f, File.stat(f).mtime)
17
+ }
18
+ @file.sort!{|a,b| b.mtime <=> a.mtime}
19
+ }
20
+ end
21
+
22
+ def run(opts)
23
+ File.open(File.join(conf['output_top'], 'recent_update.shtml'), 'w') do |f|
24
+ f.write(gen(opts))
25
+ end
26
+ end
27
+
28
+ private
29
+ def gen(opts)
30
+ title = I18n.t('recent_updates')
31
+ content_tag(:table, :class=>'juli_recent_update') do
32
+ content_tag(:tr, content_tag(:th, title, :colspan=>2)) +
33
+ begin
34
+ result = ''
35
+ for i in 0..FILE_LIMIT-1 do
36
+ f = @file[i]
37
+ break if !f
38
+ result +=
39
+ content_tag(:tr) do
40
+ content_tag(:td) do
41
+ content_tag(:a, f.path.gsub(/.txt$/, ''),
42
+ :href=>f.path.gsub(/.txt$/, conf['ext'])) + "\n<br/>"
43
+ end +
44
+ content_tag(:td, f.mtime.strftime('%Y/%m/%d'))
45
+ end
46
+ end
47
+ result
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,55 @@
1
+ module Juli::Command
2
+ # generate sitemap.html and sitemap_order_by_mtime_DESC.html
3
+ # under $JULI_REPO
4
+ class Sitemap
5
+ include Juli::Util
6
+ include Juli::Visitor::Html::TagHelper
7
+
8
+ # cache File info
9
+ def initialize
10
+ @file = []
11
+ Dir.chdir(juli_repo){
12
+ Dir.glob('**/*.txt'){|f|
13
+ @file << FileEntry.new(f, File.stat(f).mtime)
14
+ }
15
+ }
16
+ end
17
+
18
+ def run(opts)
19
+ sitemap_sub('sitemap.html'){|files| files.sort}
20
+ sitemap_sub('sitemap_order_by_mtime_DESC.html'){|files|
21
+ files.sort{|a,b| File.stat(a).mtime <=> File.stat(b).mtime}.reverse
22
+ }
23
+ end
24
+
25
+ private
26
+ # === INPUTS
27
+ # name:: basename without extention for sitemap
28
+ # block:: sort condition
29
+ def sitemap_sub(name, &block)
30
+ Dir.chdir(juli_repo) {
31
+ outdir = File.join(conf['output_top'])
32
+ FileUtils.mkdir(outdir) if !File.directory?(outdir)
33
+ body = ''
34
+ count = 0
35
+ for textfile in yield(Dir.glob('**/*.txt')) do
36
+ count += 1
37
+ body += sprintf("<tr><td class='num'>%d</td><td><a href='%s'>%s</a></td><td>%s</td></tr>\n",
38
+ count,
39
+ textfile.gsub(/.txt$/, conf['ext']), # url
40
+ textfile.gsub(/.txt$/, ''), # label
41
+ File.stat(textfile).mtime.strftime("%Y/%m/%d %H:%M:%S"))
42
+ end
43
+
44
+ title = I18n.t('sitemap')
45
+ prototype = 'prototype.js'
46
+ javascript = 'juli.js'
47
+ stylesheet = 'juli.css'
48
+ erb = ERB.new(File.read(find_template(name)))
49
+ File.open(out_filename(name), 'w') do |f|
50
+ f.write(erb.result(binding))
51
+ end
52
+ }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,81 @@
1
+ # coding: UTF-8
2
+
3
+ module Juli::Command
4
+ # generate _tag.shtml which shows tag-search-result HTML page.
5
+ class Tag
6
+ include Juli::Util
7
+ include Juli::Visitor::Html::TagHelper
8
+
9
+ def initialize
10
+ @tag_macro = Juli::Macro::Tag.new
11
+ end
12
+
13
+ def run(opts)
14
+ # tag list
15
+ body = content_tag(:a, '', :name=>'top').force_encoding('UTF-8') +
16
+ "<h2>#{I18n.t('tag_list')}</h2>\n".force_encoding('UTF-8')
17
+ for tag, val in @tag_macro.tag_db do
18
+ body += gen_tag_list(tag)
19
+ end
20
+ body += gen_tag_list(
21
+ Juli::Macro::Tag::NO_TAG,
22
+ I18n.t(Juli::Macro::Tag::NO_TAG))
23
+ body += "\n\n" + '<br/>'*50
24
+
25
+ # tag detail
26
+ for tag, val in @tag_macro.tag_db do
27
+ body += gen_tag_detail(tag)
28
+ end
29
+ body += gen_tag_detail(
30
+ Juli::Macro::Tag::NO_TAG,
31
+ I18n.t(Juli::Macro::Tag::NO_TAG))
32
+
33
+ title = I18n.t('tag_list')
34
+ contents = ''
35
+ prototype = 'prototype.js'
36
+ javascript = 'juli.js'
37
+ stylesheet = 'juli.css'
38
+ erb = ERB.new(File.read(find_template('simple.html')))
39
+ File.open(File.join(conf['output_top'], '_tag.shtml'), 'w') do |f|
40
+ f.write(erb.result(binding))
41
+ end
42
+ end
43
+
44
+ private
45
+ def gen_tag_list(tag, tag_label=tag)
46
+ (content_tag(:a, tag_label,
47
+ :class => sprintf("juli_tag_%02d", @tag_macro.tag_weight_ratio(tag)),
48
+ :href => "##{tag}") + ' ').force_encoding('UTF-8')
49
+ end
50
+
51
+ def gen_tag_detail(tag, tag_label=tag)
52
+ content_tag(:a, '', :name=>tag).force_encoding('UTF-8') +
53
+ content_tag(:h2, tag_label).force_encoding('UTF-8') +
54
+ '<table>' +
55
+ begin
56
+ s = ''
57
+ for page in @tag_macro.pages(@tag_macro.to_utf8(tag)) do
58
+ file = page + '.txt'
59
+ if !File.exist?(file)
60
+ # Non-exist file may occur by manual delete/rename so that
61
+ # delete the entry from tag-DB and don't produce tag entry
62
+ # from the tag-list page.
63
+ @tag_macro.delete_page(file)
64
+ next
65
+ end
66
+
67
+ page_utf8 = @tag_macro.to_utf8(page)
68
+ s += sprintf("<tr><td><a href='%s'>%s</a></td><td>%s</td></tr>\n",
69
+ page_utf8 + @tag_macro.to_utf8(conf['ext']),
70
+ page_utf8,
71
+ File.stat(file).mtime.strftime("%Y/%m/%d %H:%M"))
72
+ end
73
+ s
74
+ end +
75
+ '</table>' +
76
+ '<br/>' +
77
+ '<a href="#top">' + I18n.t('back_to_top') + '</a>' +
78
+ '<br/>'*30
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,212 @@
1
+ # Text *line* parser for Juli format.
2
+ class Juli::LineParser
3
+ options no_result_var
4
+
5
+ rule
6
+ line
7
+ : elements { @root = val[0] }
8
+
9
+ elements
10
+ : /* none */ { LineAbsyn::ArrayNode.new }
11
+ | elements element { val[0].add(val[1]) }
12
+
13
+ element
14
+ : STRING { LineAbsyn::StringNode.new(val[0]) }
15
+ | WIKINAME { LineAbsyn::WikiName.new(val[0]) }
16
+ | TAG { LineAbsyn::StringNode.new(val[0]) }
17
+ | URL { LineAbsyn::Url.new(val[0]) }
18
+ | MACRO { LineAbsyn::Macro.new(val[0][0], val[0][1]) }
19
+ end
20
+ ---- header
21
+ module Juli::LineAbsyn
22
+ class Node
23
+ def accept(visitor)
24
+ visitor.visit_node(self)
25
+ end
26
+ end
27
+
28
+ class StringNode < Node
29
+ attr_accessor :str
30
+
31
+ def initialize(str)
32
+ @str = str
33
+ end
34
+
35
+ def accept(visitor)
36
+ visitor.visit_string(self)
37
+ end
38
+ end
39
+
40
+ class WikiName < StringNode
41
+ def accept(visitor)
42
+ visitor.visit_wikiname(self)
43
+ end
44
+ end
45
+
46
+ class Url < StringNode
47
+ def accept(visitor)
48
+ visitor.visit_url(self)
49
+ end
50
+ end
51
+
52
+ class Macro < Node
53
+ attr_accessor :name, :rest
54
+
55
+ def initialize(name, rest)
56
+ @name = name
57
+ @rest = rest
58
+ end
59
+
60
+ def accept(visitor)
61
+ visitor.visit_macro(self)
62
+ end
63
+ end
64
+
65
+ class ArrayNode < Node
66
+ attr_accessor :array
67
+
68
+ def initialize
69
+ @array = Array.new
70
+ end
71
+
72
+ def add(child)
73
+ @array << child
74
+ self
75
+ end
76
+
77
+ def accept(visitor)
78
+ visitor.visit_array(self)
79
+ end
80
+ end
81
+
82
+ # define Visitor default actions
83
+ class Visitor
84
+ def visit_node(n); end
85
+
86
+ def visit_array(n)
87
+ for n in n.array do
88
+ n.accept(self)
89
+ end
90
+ end
91
+
92
+ def visit_string(n); end
93
+ def visit_wikiname(n); end
94
+ def visit_url(n); end
95
+ def visit_macro(n); end
96
+ end
97
+
98
+ # visitor for debug
99
+ class DebugVisitor < Visitor
100
+ attr_reader :array
101
+
102
+ def initialize
103
+ @array = []
104
+ end
105
+
106
+ def visit_string(n)
107
+ @array << n.str
108
+ end
109
+
110
+ def visit_wikiname(n)
111
+ @array << sprintf("W:%s", n.str)
112
+ end
113
+
114
+ def visit_url(n)
115
+ @array << sprintf("U:%s", n.str)
116
+ end
117
+
118
+ def visit_macro(n)
119
+ @array << sprintf("M:%s:%s", n.name, n.rest)
120
+ end
121
+ end
122
+ end
123
+
124
+ ---- inner
125
+ # parse one line and return absyn tree for the line
126
+ def parse(line, wikinames)
127
+ @remain = line
128
+ @wikinames = wikinames
129
+ yyparse self, :scan
130
+ @root
131
+ end
132
+
133
+ private
134
+ # Wikiname scanning algorithm is as follows:
135
+ #
136
+ # 1. input: [..............................................................]
137
+ # 2. scan longest wikiname in wikiname-dictionary:
138
+ # [<---heading_remain---->LONGEST_WIKINAME<---trailing_remain--->]
139
+ # 3. for remaining in head & trail, do 2. above recursively
140
+ def scan(&block)
141
+ scan_r(@remain, &block)
142
+ yield [false, nil]
143
+ end
144
+
145
+ URL = '(https?|mailto|ftp):[\w\.\?&/@%^=~#-]+'
146
+
147
+ # recursive scan
148
+ def scan_r(str, &block)
149
+ for w in @wikinames do
150
+ case str
151
+ # to escape wikiname string in <a>...</a>, it is prior to wikiname
152
+ #
153
+ # If word in <a ...>word</a> tag is a wikiname, it would be produced to
154
+ # <a ...><a ...>word</a></a> because it is a wikiname. In order to
155
+ # avoid this, two ways can be considered:
156
+ #
157
+ # 1. introduce escape notation. e.g. rdoc \word
158
+ # 2. introduce special inline escape logic just for <a>...</a>
159
+ #
160
+ # I choose latter for simple usage.
161
+ when /\A([^<]*)(<a[^>]*>[^<]*<\/a>)(.*)\z/m
162
+ scan_r($1, &block)
163
+ yield [:STRING, $2] # <a>...</a> is just string even wikiname be there
164
+ scan_r($3, &block)
165
+ return
166
+
167
+ # to escape wikiname string in HTML tag, it is prior to wikiname
168
+ when /\A([^<]*)(<[^>]*>)(.*)\z/m
169
+ scan_r($1, &block)
170
+ yield [:STRING, $2] # <a>...</a> is just string even wikiname be there
171
+ scan_r($3, &block)
172
+ return
173
+
174
+ # escape of escape: \\{ -> \{
175
+ when /\A([^\\]*)\\\\\{(.*)\z/m
176
+ scan_r($1, &block)
177
+ yield [:STRING, '\\{']
178
+ scan_r($2, &block)
179
+ return
180
+
181
+ # explicit escape by \{!...}
182
+ when /\A([^\\]*)\\\{!([^}]+)\}(.*)\z/m
183
+ scan_r($1, &block)
184
+ yield [:STRING, $2]
185
+ scan_r($3, &block)
186
+ return
187
+
188
+ # macro \{command rest}
189
+ when /\A([^\\]*)\\\{(\w+)\s*([^}]*)\}(.*)\z/m
190
+ scan_r($1, &block)
191
+ yield [:MACRO, [$2, $3]]
192
+ scan_r($4, &block)
193
+ return
194
+
195
+ # URL is piror to wikiname
196
+ when /\A(|.*[^\w])(#{URL})(.*)\z/m
197
+ scan_r($1, &block)
198
+ yield [:URL, $2]
199
+ scan_r($4, &block) # not $3 since URL itself has (...)
200
+ return
201
+
202
+ when /\A(.*)#{w}(.*)\z/m
203
+ scan_r($1, &block)
204
+ yield [:WIKINAME, w]
205
+ scan_r($2, &block)
206
+ return
207
+ end
208
+ end
209
+ yield [:STRING, str]
210
+ end
211
+
212
+ ---- footer
data/lib/juli/macro.rb ADDED
@@ -0,0 +1,39 @@
1
+ module Juli
2
+ module Macro
3
+ class Base
4
+ include Juli::Util
5
+
6
+ # called on 'juli init' to generate config sample template.
7
+ def self.conf_template
8
+ ''
9
+ end
10
+
11
+ # called when juli(1) starts.
12
+ def initialize
13
+ end
14
+
15
+ # called on setting up conf to set default key=val
16
+ def set_conf_default(conf)
17
+ end
18
+
19
+ # called on each parsed document
20
+ def on_root(file, root, visitor = nil)
21
+ end
22
+
23
+ # called on each macro as "\{macro_name args...}" in text.
24
+ # String should be returned.
25
+ def run(*args)
26
+ ''
27
+ end
28
+
29
+ # called at final on each parsed document
30
+ def after_root(file, root)
31
+ end
32
+
33
+ end
34
+
35
+ Dir.glob(File.join(File.dirname(__FILE__), 'macro/*.rb')){|m|
36
+ require File.join('juli/macro', File.basename(m))
37
+ }
38
+ end
39
+ end