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,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>