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.
- 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
data/bin/setup
ADDED
data/juli.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'juli/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "juli"
|
9
|
+
spec.version = Juli::VERSION
|
10
|
+
spec.authors = ["ido"]
|
11
|
+
spec.email = ["fuminori_ido@yahoo.co.jp"]
|
12
|
+
|
13
|
+
spec.summary = %q{Offline wiki, and idea processor}
|
14
|
+
spec.description = %q{Offline wiki, and idea processor}
|
15
|
+
spec.homepage = "https://github.com/fuminori-ido/juli"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_runtime_dependency 'racc'
|
24
|
+
spec.add_runtime_dependency 'simplecov'
|
25
|
+
spec.add_runtime_dependency 'RMagick'
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
end
|
data/lib/juli.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
require 'pathname'
|
3
|
+
require "juli/version"
|
4
|
+
|
5
|
+
# namespace for all of Juli library elements
|
6
|
+
module Juli
|
7
|
+
# sentinel to search juli-repo. Also it's a directory name to sotre config.
|
8
|
+
REPO = '.juli'
|
9
|
+
LIB = File.join(Pathname.new(File.dirname(__FILE__)).realpath, 'juli')
|
10
|
+
TEMPLATE_PATH = File.join(LIB, 'template')
|
11
|
+
|
12
|
+
class JuliError < StandardError; end
|
13
|
+
class NoConfig < JuliError; end
|
14
|
+
class NotImplemented < JuliError; end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def init
|
18
|
+
I18n.enforce_available_locales = false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/juli/absyn.rb
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'juli/wiki'
|
2
|
+
|
3
|
+
# Abstract tree nodes
|
4
|
+
module Juli::Absyn
|
5
|
+
class Node
|
6
|
+
attr_accessor :parent
|
7
|
+
|
8
|
+
def accept(visitor)
|
9
|
+
visitor.visit_node(self)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# StrNode adds 'concat' string manupilation method
|
14
|
+
#
|
15
|
+
# StrNode is also an element of ListItem
|
16
|
+
class StrNode < Node
|
17
|
+
attr_accessor :str, :level
|
18
|
+
|
19
|
+
def initialize(str = '', level = 0)
|
20
|
+
@str = str
|
21
|
+
@level = level
|
22
|
+
end
|
23
|
+
|
24
|
+
def concat(str)
|
25
|
+
@str += str
|
26
|
+
end
|
27
|
+
|
28
|
+
def accept(visitor)
|
29
|
+
visitor.visit_str(self)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Verbatim < Node
|
34
|
+
attr_accessor :str
|
35
|
+
|
36
|
+
def initialize(str)
|
37
|
+
@str = str
|
38
|
+
end
|
39
|
+
|
40
|
+
def accept(visitor)
|
41
|
+
visitor.visit_verbatim(self)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class ArrayNode < Node
|
46
|
+
attr_accessor :array
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
@array = Array.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def accept(visitor)
|
53
|
+
visitor.visit_array(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
def add(child)
|
57
|
+
@array << child
|
58
|
+
child.parent = self
|
59
|
+
self
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# NOTE: @dom_id will be used for only Html visitor and contents helper.
|
64
|
+
class Chapter < Node
|
65
|
+
attr_accessor :level, :str, :blocks, :dom_id
|
66
|
+
|
67
|
+
def initialize(level, str, blocks)
|
68
|
+
super()
|
69
|
+
@level = level
|
70
|
+
@str = str
|
71
|
+
@blocks = blocks
|
72
|
+
end
|
73
|
+
|
74
|
+
def accept(visitor)
|
75
|
+
visitor.visit_chapter(self)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# abstract List.
|
80
|
+
class List < ArrayNode
|
81
|
+
end
|
82
|
+
|
83
|
+
class OrderedList < List
|
84
|
+
def accept(visitor)
|
85
|
+
visitor.visit_ordered_list(self)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class UnorderedList < List
|
90
|
+
def accept(visitor)
|
91
|
+
visitor.visit_unordered_list(self)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# CompactDictionary list as follows:
|
96
|
+
# term1:: description1
|
97
|
+
# term2:: description2
|
98
|
+
# ...
|
99
|
+
#
|
100
|
+
# === SEE ALSO
|
101
|
+
# DictionaryList
|
102
|
+
class CompactDictionaryList < ArrayNode
|
103
|
+
def accept(visitor)
|
104
|
+
visitor.visit_compact_dictionary_list(self)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class CompactDictionaryListItem < Node
|
109
|
+
attr_accessor :term, :str
|
110
|
+
|
111
|
+
def initialize(term, str)
|
112
|
+
@term = term
|
113
|
+
@str = str
|
114
|
+
end
|
115
|
+
|
116
|
+
def accept(visitor)
|
117
|
+
visitor.visit_compact_dictionary_list_item(self)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Dictionary list as follows:
|
122
|
+
# term1::
|
123
|
+
# description1
|
124
|
+
# description1(cont'd)
|
125
|
+
# term2::
|
126
|
+
# description2
|
127
|
+
# ...
|
128
|
+
#
|
129
|
+
# Description can be in multilines.
|
130
|
+
#
|
131
|
+
# === SEE ALSO
|
132
|
+
# CompactDictionaryList
|
133
|
+
class DictionaryList < List
|
134
|
+
def accept(visitor)
|
135
|
+
visitor.visit_dictionary_list(self)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class DictionaryListItem < CompactDictionaryListItem
|
140
|
+
def accept(visitor)
|
141
|
+
visitor.visit_dictionary_list_item(self)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Abstract VISITOR-pattern around Absyn tree.
|
146
|
+
#
|
147
|
+
# === How to add new generator
|
148
|
+
# Document generator, which juli(1) command says, points to 'visitor'
|
149
|
+
# internally because it is VISITOR-pattern.
|
150
|
+
# After adding new visitor, for example PDF-generator,
|
151
|
+
# it can be used by 'juli -g pdf' (let me assume the file name is pdf.rb).
|
152
|
+
# Follow the steps below to add new visitor:
|
153
|
+
#
|
154
|
+
# 1. create LIB/juli/visitor/pdf.rb. Probably, it is easy to copy
|
155
|
+
# from another visitor file (e.g. html.rb) as the skelton.
|
156
|
+
# Where, LIB is 'lib/' directory in package environment, or
|
157
|
+
# one of $LOAD_PATH in installed environment.
|
158
|
+
# 1. implement the pdf.rb. It's the most important task, of course...
|
159
|
+
#
|
160
|
+
class Visitor
|
161
|
+
# Visitor object is initialized when juli(1) gen command is executed.
|
162
|
+
# In other words, it is *NOT* initialized for each input text file.
|
163
|
+
# Some global initialization can be done here.
|
164
|
+
#
|
165
|
+
# Take care that this is executed every juli(1) execution.
|
166
|
+
def initialize(opts = {})
|
167
|
+
@opts = opts.dup
|
168
|
+
end
|
169
|
+
|
170
|
+
# 'run' bulk-mode (when no files are specified at
|
171
|
+
# juli(1) command line). Derived class should implement this.
|
172
|
+
def run_bulk; end
|
173
|
+
|
174
|
+
# run for a file and its node-tree.
|
175
|
+
# Here is just sample implementation.
|
176
|
+
# Derived class can re-implement this.
|
177
|
+
#
|
178
|
+
# === INPUTS
|
179
|
+
# in_file:: input filename
|
180
|
+
# root:: Absyn tree root
|
181
|
+
def run_file(in_file, root)
|
182
|
+
root.accept(self)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Methods for each Absyn node. Derived class should implement
|
186
|
+
# these.
|
187
|
+
#
|
188
|
+
# === INPUTS
|
189
|
+
# n:: Absyn node
|
190
|
+
def visit_node(n); end
|
191
|
+
def visit_str(n); end
|
192
|
+
def visit_verbatim(n); end
|
193
|
+
def visit_array(n)
|
194
|
+
for node in n.array do
|
195
|
+
node.accept(self)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
def visit_chapter(n); end
|
199
|
+
def visit_ordered_list(n); end
|
200
|
+
def visit_unordered_list(n); end
|
201
|
+
def visit_compact_dictionary_list(n); end
|
202
|
+
def visit_compact_dictionary_list_item(n); end
|
203
|
+
def visit_dictionary_list(n); end
|
204
|
+
def visit_dictionary_list_item(n); end
|
205
|
+
end
|
206
|
+
end
|
data/lib/juli/command.rb
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'juli/util'
|
2
|
+
require 'juli/parser.tab'
|
3
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'command/*.rb')){|sub_command_file|
|
4
|
+
require sub_command_file
|
5
|
+
}
|
6
|
+
|
7
|
+
module Juli
|
8
|
+
# This is a top level module for juli(1) command execution.
|
9
|
+
# Each juli(1) command corresponds to each method here.
|
10
|
+
module Command
|
11
|
+
class Error < Exception; end
|
12
|
+
|
13
|
+
# top level command execution. command_str will be checked and
|
14
|
+
# dispatched to each method.
|
15
|
+
def run(command_str, opts = {})
|
16
|
+
if command_str == 'init'
|
17
|
+
init(opts)
|
18
|
+
else
|
19
|
+
Juli::Util::JuliI18n.new(conf, juli_repo)
|
20
|
+
case command_str
|
21
|
+
when 'gen'; gen(opts)
|
22
|
+
when 'sitemap'; Juli::Command::Sitemap.new.run(opts)
|
23
|
+
when 'recent_update'; Juli::Command::RecentUpdate.new.run(opts)
|
24
|
+
when 'tag'; Juli::Command::Tag.new.run(opts)
|
25
|
+
else
|
26
|
+
STDERR.print "Unknown juli command: '#{command_str}'\n\n", usage, "\n"
|
27
|
+
raise Error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
OUTPUT_TOP_COMMENT = <<EOM
|
33
|
+
# Juli-repo config file.
|
34
|
+
#
|
35
|
+
# This is YAML format.
|
36
|
+
#
|
37
|
+
# Starting '#' at each line means just comment.
|
38
|
+
# You can delete these comments.
|
39
|
+
#
|
40
|
+
# The commented-out settings shown in this file represent the default values.
|
41
|
+
|
42
|
+
|
43
|
+
# Locale(default = en)
|
44
|
+
#
|
45
|
+
#locale: en
|
46
|
+
|
47
|
+
# show_indent_toggle_button (default = true) to show/hide the toggle button
|
48
|
+
# for indented scope of the text. NOTE: toggle action still works even
|
49
|
+
# though button is hidden.
|
50
|
+
#
|
51
|
+
#show_indent_toggle_button: true
|
52
|
+
|
53
|
+
|
54
|
+
# Specify output top directory (default = ../html).
|
55
|
+
|
56
|
+
EOM
|
57
|
+
TEMPLATE_COMMENT = <<EOM
|
58
|
+
|
59
|
+
# Specify html template when generating (default = 'default.html', which
|
60
|
+
# means that RUBY_LIB/juli/template/default.html is used).
|
61
|
+
#
|
62
|
+
# Current available templates are under RUBY_LIB/juli/template/, where
|
63
|
+
# RUBY_LIB is the directory which juli library is installed
|
64
|
+
# (e.g. /usr/local/lib/ruby/site_ruby/1.9/).
|
65
|
+
#
|
66
|
+
# You can put your customized template under JULI_REPO/.juli/
|
67
|
+
# rather than ruby standard library directory. For example,
|
68
|
+
# if you want to use your customized template 'blue_ocean.html',
|
69
|
+
# create it under JULI_REPO/ and specify it at config as follows:
|
70
|
+
#
|
71
|
+
# $ cp RUBY_LIB/juli/template/default.html JULI_REPO/.juli/blue_ocean.html
|
72
|
+
# (edit JULI_REPO/.juli/blue_ocean.html as you like)
|
73
|
+
# (edit JULI_REPO/.juli/config as follows:
|
74
|
+
#
|
75
|
+
# template: blue_ocean.html
|
76
|
+
#
|
77
|
+
# File extention (e.g. .html) is required in this config.
|
78
|
+
# -t option at 'juli gen' command line execution can be also supported.
|
79
|
+
#
|
80
|
+
|
81
|
+
EOM
|
82
|
+
EXT_COMMENT = <<EOM
|
83
|
+
|
84
|
+
# Generated file's extention (default = .shtml).
|
85
|
+
# The reason why '.shtml' is because to use SSI (server side include)
|
86
|
+
# for recent_update. Of course, it depends on web-server configuration and
|
87
|
+
# you may not use SSI. In such a case, you can change to '.html'.
|
88
|
+
|
89
|
+
EOM
|
90
|
+
# init does:
|
91
|
+
#
|
92
|
+
# 1. create juli-repository at the current directory, if not yet.
|
93
|
+
# 1. create config file under the juli-repo, if not yet.
|
94
|
+
# This stores juli-repo dependent information.
|
95
|
+
# 1. if parameters are specified, store it in config file under juli-repo.
|
96
|
+
#
|
97
|
+
# === OPTIONS
|
98
|
+
# -o output_top
|
99
|
+
# -t template
|
100
|
+
# -e ext
|
101
|
+
def init(opts)
|
102
|
+
if !File.directory?(Juli::REPO)
|
103
|
+
FileUtils.mkdir(Juli::REPO)
|
104
|
+
else
|
105
|
+
STDERR.print "WARN: juli-repo is already created\n"
|
106
|
+
end
|
107
|
+
|
108
|
+
config_file = File.join(Juli::REPO, 'config')
|
109
|
+
if !File.exist?(config_file)
|
110
|
+
File.open(config_file, 'w') do |f|
|
111
|
+
f.print OUTPUT_TOP_COMMENT
|
112
|
+
write_config(f, 'output_top', opts[:o])
|
113
|
+
f.print TEMPLATE_COMMENT
|
114
|
+
write_config(f, 'template', opts[:t])
|
115
|
+
f.print EXT_COMMENT
|
116
|
+
write_config(f, 'ext', opts[:e])
|
117
|
+
write_macro_conf(f)
|
118
|
+
write_helper_conf(f)
|
119
|
+
end
|
120
|
+
else
|
121
|
+
STDERR.print "WARN: config file is already created\n"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# generate command
|
126
|
+
#
|
127
|
+
# === OPTIONS
|
128
|
+
# -g generator:: specify generator
|
129
|
+
# -f:: force update
|
130
|
+
# -t template:: specify template
|
131
|
+
# -o output_path:: specify output file path (only non-bulk-mode)
|
132
|
+
def gen(opts)
|
133
|
+
o = opts.dup
|
134
|
+
o.delete(:g)
|
135
|
+
# executes each generator's init here:
|
136
|
+
v = visitor(opts[:g]).new(o)
|
137
|
+
|
138
|
+
if ARGV.empty?
|
139
|
+
print "bulk mode\n"
|
140
|
+
if opts[:o]
|
141
|
+
STDERR.print "ERROR: -o #{opts[:o]} is specified in bulk-mode\n"
|
142
|
+
else
|
143
|
+
v.run_bulk
|
144
|
+
end
|
145
|
+
else
|
146
|
+
for file in ARGV do
|
147
|
+
Juli::Parser.new.parse(file, v)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
def write_config(f, key, value)
|
154
|
+
if value
|
155
|
+
f.printf("%s: %s\n", key, value)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# write each macro conf sample to initial .juli/conf file
|
160
|
+
# by calling 'conf_template' method on each macro.
|
161
|
+
def write_macro_conf(f)
|
162
|
+
for macro_symbol in Juli::Macro.constants do
|
163
|
+
next if macro_symbol == :Base
|
164
|
+
macro_class = Juli::Macro.module_eval(macro_symbol.to_s)
|
165
|
+
f.print "\n", macro_class.conf_template
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# write each helper conf sample to initial .juli/conf file
|
170
|
+
# by calling 'conf_template' method on each macro.
|
171
|
+
def write_helper_conf(f)
|
172
|
+
for helper_symbol in Juli::Visitor::Html::Helper.constants do
|
173
|
+
next if helper_symbol == :AbstractHelper
|
174
|
+
helper_class = Juli::Visitor::Html::Helper.module_eval(helper_symbol.to_s)
|
175
|
+
f.print "\n", helper_class.conf_template
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|