juli 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,19 @@
1
+ require 'juli/macro/template_base'
2
+
3
+ module Juli
4
+ module Macro
5
+ # Interwiki for Wikipedia
6
+ class Wikipedia < TemplateBase
7
+ DEFAULT_TEMPLATE = '<a href="http://en.wikipedia.org/wiki/%{wikipedia}">%{wikipedia}</a>'
8
+
9
+ def self.conf_template
10
+ <<EOM
11
+ # HTML template for wikipedia.
12
+ # '%{wikipedia}' in the template will be replaced by actual Wikipedia word:
13
+ #
14
+ #wikipedia: #{DEFAULT_TEMPLATE}
15
+ EOM
16
+ end
17
+ end
18
+ end
19
+ end
data/lib/juli/parser.y ADDED
@@ -0,0 +1,360 @@
1
+ # Text parser for Juli format.
2
+ class Juli::Parser
3
+ options no_result_var
4
+
5
+ rule
6
+ # Racc action returns absyn node to build absyn-tree
7
+ text
8
+ : blocks { @root = val[0] }
9
+
10
+ blocks
11
+ : /* none */ { Absyn::ArrayNode.new }
12
+ | blocks block { val[0].add(val[1]) if val[1]; val[0] }
13
+
14
+ block
15
+ : textblock { Absyn::StrNode.new(val[0]) }
16
+ | '(' textblock ')' { Absyn::Verbatim.new(val[1]) }
17
+ | '{' chapters '}' { val[1] }
18
+ | '(' ulist ')' { val[1] }
19
+ | '(' olist ')' { val[1] }
20
+ | cdlist
21
+ | dlist
22
+ | WHITELINE { nil }
23
+
24
+ textblock
25
+ : STRING
26
+ | textblock STRING { val[0] + val[1] }
27
+
28
+ # chapters are list of chapter at the same level,
29
+ # and chapter is header + blocks.
30
+ #
31
+ # Where, chapter here refers both chapter and/or section in
32
+ # usual meanings since (again) it contains header + blocks.
33
+ #
34
+ # '{' ... '}' at chapters syntax is to let
35
+ # racc parse headlines with *level* correctly.
36
+ # It's the same as 'if ... elsif ... elsif ... end' in Ada, Eiffel, and Ruby.
37
+ chapters
38
+ : chapter { h = Absyn::ArrayNode.new; h.add(val[0]) }
39
+ | chapters chapter { val[0].add(val[1]) }
40
+ chapter
41
+ : H STRING blocks { Absyn::Chapter.new(val[0], val[1], val[2]) }
42
+
43
+ # unordered list
44
+ ulist
45
+ : ulist_item { l = Absyn::UnorderedList.new; l.add(val[0]) }
46
+ | ulist ulist_item { val[0].add(val[1]) }
47
+ ulist_item
48
+ : '*' blocks { val[1] }
49
+
50
+ # ordered list
51
+ olist
52
+ : olist_item { l = Absyn::OrderedList.new; l.add(val[0]) }
53
+ | olist olist_item { val[0].add(val[1]) }
54
+ olist_item
55
+ : '#' blocks { val[1] }
56
+
57
+ # compact dictionary list
58
+ cdlist
59
+ : cdlist_item { l = Absyn::CompactDictionaryList.new; l.add(val[0])}
60
+ | cdlist cdlist_item { val[0].add(val[1]) }
61
+ cdlist_item
62
+ : CDT STRING { Absyn::CompactDictionaryListItem.new(val[0],val[1])}
63
+
64
+ # dictionary list
65
+ dlist
66
+ : dlist_item { l = Absyn::DictionaryList.new; l.add(val[0]) }
67
+ | dlist dlist_item { val[0].add(val[1]) }
68
+ dlist_item
69
+ : DT '(' textblock ')'{ Absyn::DictionaryListItem.new(val[0], val[2]) }
70
+ end
71
+
72
+ ---- header
73
+ require 'juli/wiki'
74
+
75
+ ---- inner
76
+ require 'erb'
77
+ require 'juli/visitor'
78
+
79
+ # keep nest level; will be used to yield ')'
80
+ #
81
+ # This is used for both headline level and list nesting.
82
+ class NestStack
83
+ class InvalidOrder < StandardError; end
84
+
85
+ def initialize
86
+ @stack = []
87
+ @baseline = 0
88
+ end
89
+
90
+ # action on '('
91
+ def push(length)
92
+ if @stack.last && @stack.last >= length
93
+ raise InvalidOrder, "top(#{@stack.last}) >= length(#{length})"
94
+ end
95
+ @stack << length
96
+ @baseline = length
97
+ end
98
+
99
+ # current baseline
100
+ def baseline
101
+ @baseline
102
+ end
103
+
104
+ # action on ')'
105
+ #
106
+ # go up nest until length meets. Block (mainly for ')') is called
107
+ # on each pop
108
+ # If length==nil, pop just 1 level up
109
+ def pop(length = nil, &block)
110
+ if length
111
+ if @stack.last && @stack.last > length
112
+ @stack.pop
113
+ yield if block_given?
114
+ self.pop(length, &block)
115
+ else
116
+ @baseline = @stack.last ? length : 0
117
+ end
118
+ else
119
+ if @stack.last
120
+ @stack.pop
121
+ yield if block_given?
122
+ @baseline = @stack.last || 0
123
+ end
124
+ end
125
+ end
126
+
127
+ def flush(&block)
128
+ while @stack.last do
129
+ yield if block_given?
130
+ @stack.pop
131
+ end
132
+ @baseline = 0
133
+ end
134
+
135
+ # for debug
136
+ def status
137
+ @stack.inspect
138
+ end
139
+ end
140
+
141
+ # parse one file, build Absyn tree, then generate HTML
142
+ def parse(in_file, visitor)
143
+ @yydebug = true if ENV['YYDEBUG']
144
+ @indent_stack = NestStack.new
145
+ @header_stack = NestStack.new
146
+
147
+ @in_verbatim = false
148
+ @in_file = in_file
149
+ File.open(in_file) do |io|
150
+ @in_io = io
151
+ yyparse self, :scan
152
+ end
153
+ visitor.run_file(in_file, @root)
154
+ end
155
+
156
+ # return absyn tree
157
+ def tree
158
+ @root
159
+ end
160
+
161
+ private
162
+ class ScanError < Exception; end
163
+
164
+ def scan(&block)
165
+ @src_line = 0
166
+ while line = @in_io.gets do
167
+ debug("@in_verbatim = #{@in_verbatim.inspect}")
168
+ @src_line += 1
169
+ case line
170
+ when /^\s*$/
171
+ if @in_verbatim
172
+ yield [:STRING, "\n"]
173
+ else
174
+ indent_or_dedent(0, &block)
175
+ yield [:WHITELINE, nil]
176
+ end
177
+ when /^(={1,6})\s+(.*)$/
178
+ header_nest($1.length, &block)
179
+ yield [:H, $1.length]
180
+ yield [:STRING, $2]
181
+ when /^(\s*)(\d+\.\s+)(.*)$/
182
+ on_list_item(line, '#', $1.length, $2.length, $3, &block)
183
+ when /^(\s*)(\*\s+)(.*)$/
184
+ on_list_item(line, '*', $1.length, $2.length, $3, &block)
185
+ when /^(\s*)(\S.*)::\s*$/
186
+ if !on_item($1.length, $2 + "::\n", &block)
187
+ yield [:DT, $2]
188
+ end
189
+ when /^(\s*)((\S.*)::\s+(.*))$/
190
+ if !on_item($1.length, $2 + "\n", &block)
191
+ yield [:CDT, $3]
192
+ yield [:STRING, $4]
193
+ end
194
+ when /^(\s*)(.*)$/
195
+ length = $1.length
196
+ if indent_or_dedent(length, &block)
197
+ @in_verbatim = true
198
+ end
199
+ yield [:STRING,
200
+ (@in_verbatim ?
201
+ ' ' * (length - @indent_stack.baseline) :
202
+ '') + $2 + "\n"]
203
+ else
204
+ raise ScanError
205
+ end
206
+ end
207
+ @indent_stack.flush{ yield [')', nil] }
208
+ @header_stack.flush{ yield ['}', nil] }
209
+ yield [false, nil]
210
+ end
211
+
212
+ class NoSrcLine < ParseError; end
213
+
214
+ def on_error(et, ev, values)
215
+ print_line('Juli syntax error')
216
+ raise ParseError
217
+ rescue NoSrcLine
218
+ raise ParseError, sprintf("Juli syntax error at line %d\n", @src_line)
219
+ end
220
+
221
+ def on_list_item(line, token, length1, length2, str, &block)
222
+ length = length1 + length2
223
+ debug_indent("list item('#{token}')", length)
224
+ if @in_verbatim
225
+ if @indent_stack.baseline <= length1
226
+ yield [:STRING, line]
227
+ else
228
+ # after verbatim, dedent just 1-level because there is no
229
+ # deeper nest in verbatim
230
+ dedent(&block)
231
+ @in_verbatim = false
232
+ indent_or_dedent_on_non_verbatim(length, &block)
233
+ yield [token, nil]
234
+ yield [:STRING, str + "\n"]
235
+ end
236
+ else
237
+ base_line_before = @indent_stack.baseline
238
+ indent_or_dedent(length, &block)
239
+ if base_line_before > 0 && @indent_stack.baseline == 0
240
+ warn('Incorrect nest here, but reset it and continue to process.')
241
+ indent(length, &block)
242
+ end
243
+ yield [token, nil]
244
+ yield [:STRING, str + "\n"]
245
+ end
246
+ end
247
+
248
+ # action on dictionary list and compact dictionary list
249
+ #
250
+ # 1st, check indent, dedent, or continue.
251
+ # 2nd, if in verbatime, yield string.
252
+ # otherwise, return in_verbatim to tell caller to do the 'NON verbatim'
253
+ # case.
254
+ #
255
+ # === RETURN
256
+ # in verbatim
257
+ def on_item(length, str, &block)
258
+ if indent_or_dedent(length, &block)
259
+ @in_verbatim = true
260
+ end
261
+ if @in_verbatim
262
+ yield [:STRING, str]
263
+ end
264
+ @in_verbatim
265
+ end
266
+
267
+ # calculate indent level and yield '(' or ')' correctly
268
+ #
269
+ # === RETURN
270
+ # true:: not @in_verbatim and @indent_stack.baseline < length
271
+ # false:: other case
272
+ def indent_or_dedent(length, &block)
273
+ if @in_verbatim
274
+ debug_indent('in_verbatim', length)
275
+ if @indent_stack.baseline > length # end of verbatim
276
+ dedent(length, &block)
277
+ @in_verbatim = false
278
+ end
279
+ false
280
+ else
281
+ indent_or_dedent_on_non_verbatim(length, &block)
282
+ end
283
+ end
284
+
285
+ def indent_or_dedent_on_non_verbatim(length, &block)
286
+ debug_indent('NOTverbatim', length)
287
+ if @indent_stack.baseline < length # begin verbatim
288
+ indent(length, &block)
289
+ true
290
+ elsif @indent_stack.baseline > length
291
+ dedent(length, &block)
292
+ false
293
+ end
294
+ end
295
+
296
+ def indent(length, &block)
297
+ @indent_stack.push(length)
298
+ yield ['(', nil]
299
+ end
300
+
301
+ def dedent(length=nil, &block)
302
+ @indent_stack.pop(length) do
303
+ yield [')', nil]
304
+ end
305
+ end
306
+
307
+ # calculate header level and yield '(' or ')' correctly
308
+ def header_nest(length, &block)
309
+ # at header level change, flush indent_stack
310
+ @indent_stack.flush{ yield [')', nil] }
311
+ @in_verbatim = false
312
+
313
+ if @header_stack.baseline < length
314
+ @header_stack.push(length)
315
+ yield ['{', nil]
316
+ elsif @header_stack.baseline > length
317
+ @header_stack.pop(length) do
318
+ yield ['}', nil]
319
+ end
320
+ end
321
+ end
322
+
323
+ # print indent info on debug
324
+ def debug_indent(key, length)
325
+ debug(sprintf(
326
+ "indent(%s): @indent_stack(%s,%d), length=%d",
327
+ key,
328
+ @indent_stack.status,
329
+ @indent_stack.baseline,
330
+ length))
331
+ end
332
+
333
+ # print str with source text line info to $stderr.
334
+ # If @src_line is not found, NoSrcLine error is raised.
335
+ def print_line(str)
336
+ File.open(@in_file) do |io|
337
+ line = 0
338
+ while line_str = io.gets do
339
+ line += 1
340
+ if @src_line == line
341
+ return $stderr.printf("%s: %s\n%04d: %s\n",
342
+ @in_file,
343
+ str,
344
+ @src_line,
345
+ line_str)
346
+ end
347
+ end
348
+ end
349
+ raise NoSrcError
350
+ end
351
+
352
+ def warn(str)
353
+ print_line('WARN: ' + str)
354
+ end
355
+
356
+ # general debug method
357
+ def debug(str)
358
+ @racc_debug_out.print(str, "\n") if @yydebug
359
+ end
360
+ ---- footer
@@ -0,0 +1,64 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html>
3
+ <!--
4
+
5
+ DO NOT MODIFY THIS FILE DIRECTORY!
6
+
7
+ This file is automatically generated from a text file by juli(1).
8
+
9
+ Thanks!
10
+ -->
11
+ <%#
12
+ = Required methods
13
+
14
+ juli(1) template must have following methods:
15
+
16
+ title:: title string
17
+ prototype:: prototype url
18
+ javascript:: javascript url
19
+ stylesheet:: stylesheet url
20
+ body:: generate html
21
+
22
+ = Optional methods
23
+
24
+ Following helper methods are optional:
25
+
26
+ contents:: draw contents of page
27
+ %>
28
+ <head>
29
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
30
+ <title><%= title %></title>
31
+ <script src="<%= prototype %>" type="text/javascript"></script>
32
+ <script src="<%= javascript %>" type="text/javascript"></script>
33
+ <link href="<%= stylesheet %>" rel="stylesheet" type="text/css" />
34
+ </head>
35
+ <body>
36
+ <h1>
37
+ <%= title %>
38
+ </h1>
39
+ <br/><br/>
40
+
41
+ <table width='100%'>
42
+ <tr>
43
+ <td>
44
+ <%= contents %>
45
+ </td>
46
+ <td align=right valign=top>
47
+ <table>
48
+ <tr><td align=left valign=top>
49
+ <div class=sitemap>
50
+ <a href="<%= sitemap %>">Sitemap</a>
51
+ </div>
52
+ <br/>
53
+ <!--#include virtual="recent_update.shtml" -->
54
+ </td></tr>
55
+ </table>
56
+ </td>
57
+ </tr>
58
+ </table>
59
+ <br/><br/>
60
+ <%= body %>
61
+ <hr/>
62
+ Generated by <a href='http://jjjuli.sourceforge.net/'>juli <%= Juli::VERSION %></a>
63
+ </body>
64
+ </html>
@@ -0,0 +1,82 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
+ <html xmlns:fb="http://ogp.me/ns/fb#">
3
+ <!--
4
+
5
+ DO NOT MODIFY THIS FILE DIRECTORY!
6
+
7
+ This file is automatically generated from a text file by juli(1).
8
+
9
+ Thanks!
10
+ -->
11
+ <%#
12
+ = Required methods
13
+
14
+ juli(1) template must have following methods:
15
+
16
+ title:: title string
17
+ prototype:: prototype url
18
+ javascript:: javascript url
19
+ stylesheet:: stylesheet url
20
+ body:: generate html
21
+
22
+ = Optional methods
23
+
24
+ Following helper methods are optional:
25
+
26
+ contents:: draw contents of page
27
+ %>
28
+ <head>
29
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
30
+ <title><%= title %></title>
31
+ <script src="<%= prototype %>" type="text/javascript"></script>
32
+ <script src="<%= javascript %>" type="text/javascript"></script>
33
+ <link href="<%= stylesheet %>" rel="stylesheet" type="text/css" />
34
+ </head>
35
+ <body>
36
+ <div id="fb-root"></div>
37
+ <!--
38
+ YOUR_APPID below is a uniq ID for your site.
39
+ This *SHOULD* be replaced with your actual digits taken from
40
+ Facebook developer site application registration page fo
41
+ -->
42
+ <script>(function(d, s, id) {
43
+ var js, fjs = d.getElementsByTagName(s)[0];
44
+ if (d.getElementById(id)) return;
45
+ js = d.createElement(s); js.id = id;
46
+ js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=YOUR_APPID";
47
+ fjs.parentNode.insertBefore(js, fjs);
48
+ }(document, 'script', 'facebook-jssdk'));
49
+ </script>
50
+
51
+ <h1>
52
+ <%= title %>
53
+ </h1>
54
+ <br/><br/>
55
+
56
+ <table width='100%'>
57
+ <tr>
58
+ <td>
59
+ <%= contents %>
60
+ </td>
61
+ <td align=right valign=top>
62
+ <table>
63
+ <tr><td align=left valign=top>
64
+ <div class=sitemap>
65
+ <a href="<%= sitemap %>">Sitemap</a>
66
+ </div>
67
+ <br/>
68
+ <!--#include virtual="recent_update.shtml" -->
69
+ </td></tr>
70
+ </table>
71
+ </td>
72
+ </tr>
73
+ </table>
74
+ <br/><br/>
75
+ <%= body %>
76
+ <br/><br/>
77
+ <%= fb_like %>
78
+ <%= fb_comments %>
79
+ <hr/>
80
+ Generated by <a href='http://jjjuli.sourceforge.net/'>juli <%= Juli::VERSION %></a>
81
+ </body>
82
+ </html>