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,33 @@
1
+ require 'juli/macro/template_base'
2
+
3
+ module Juli
4
+ module Macro
5
+ # generate Amazon link
6
+ #
7
+ # Amazon link template can be defined at 'amazon' entry in
8
+ # JULI_REPO/.juli/config.
9
+ #
10
+ # if it is not defined, then default template here is used.
11
+ class Amazon < TemplateBase
12
+ DEFAULT_TEMPLATE = <<-EOS
13
+ <iframe src="http://rcm-jp.amazon.co.jp/e/cm?t=wells00-22&o=9&p=8&l=as1&asins=%{asins}&ref=tf_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr"
14
+ style="float:right; width:120px;height:240px;"
15
+ scrolling="no" marginwidth="0" marginheight="0" frameborder="0"
16
+ ></iframe>
17
+ EOS
18
+
19
+ def self.conf_template
20
+ <<EOM
21
+ # Amazon association link with any ASIN can be rendered
22
+ # at any location in juli text. Its template is as follows.
23
+ # This HTML is just an example so that you can change as you like.
24
+ # '%{asins}' in the template will be replaced by actual ASIN:
25
+ #
26
+ #amazon: '<iframe src="http://rcm-jp.amazon.co.jp/e/cm?o=9&p=8&l=as1&asins=%{asins}&ref=tf_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="float:right; width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>'
27
+ EOM
28
+ end
29
+
30
+ def place_holder; 'asins'; end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,38 @@
1
+ # coding: UTF-8
2
+ require 'juli/macro/template_base'
3
+
4
+ module Juli
5
+ module Macro
6
+ # generate Map HTML.
7
+ #
8
+ # The purpose of this macro is to provide I/F for map.
9
+ # When map-site(like google) service is discontinued, or
10
+ # URL is changed, it is enough to change:
11
+ #
12
+ # 1. .juli/config jmap entry or
13
+ # 1. this macro implementation.
14
+ #
15
+ # There is no need to modify all of wiki pages which use 'jmap' macro.
16
+ #
17
+ # 'J' of jmap stands for Juli. it is because 'map' in ruby is quite common
18
+ # method so that necessary to avoid name confusion.
19
+ #
20
+ # Currently, Google map is used.
21
+ class Jmap < TemplateBase
22
+ # Thank you, http://mapki.com/wiki/Google_Map_Parameters !!
23
+ DEFAULT_TEMPLATE = '<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps?q=loc:%{coord}&amp;num=1&amp;ie=UTF8&amp;t=m&amp;z=14&amp;output=embed"></iframe><br /><small><a href="http://maps.google.com/maps?q=loc:%{coord}&amp;num=1&amp;ie=UTF8&amp;t=m&amp;z=14&amp;source=embed" style="color:#0000FF;text-align:left">View Larger Map</a></small>'
24
+
25
+ def self.conf_template
26
+ <<EOM
27
+ # HTML template to draw map. If not set, default defined at
28
+ # Juli::Macro::Jmap::DEFAULT_TEMPLATE is used.
29
+ # %{coord} in the template wiil be replaced to the actual 1st parameter.
30
+ #
31
+ #jmap: '#{DEFAULT_TEMPLATE}'
32
+ EOM
33
+ end
34
+
35
+ def place_holder; 'coord'; end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,161 @@
1
+ require 'fileutils'
2
+ require 'digest/sha1'
3
+ require 'RMagick'
4
+ require 'pp'
5
+
6
+ module Juli
7
+ module Macro
8
+ # embed photo(image) in juli wiki text with minimum maintenance cost
9
+ #
10
+ # See 'doc/photo(macro).txt' for the detail.
11
+ class Photo < Base
12
+ include Juli::Visitor::Html::TagHelper
13
+
14
+ PUBLIC_PHOTO_DIR_DEFAULT = 'public_photo'
15
+ SEED_DEFAULT = '-- Juli seed default!! --'
16
+ CONF_DEFAULT = {
17
+ 'mount' => '/home/YOUR_NAME/Photos',
18
+ 'small' => {
19
+ 'width' => 512, # default small width in pixel
20
+ 'style' => 'float: right'
21
+ },
22
+ 'large' => {
23
+ 'width' => 1024 # default large width in pixel
24
+ }
25
+ }
26
+
27
+ class DirNameConflict < Juli::JuliError; end
28
+ class ConfigNoMount < Juli::JuliError; end
29
+
30
+ def self.conf_template
31
+ <<EOM
32
+ # Photo macro setup sample is as follows.
33
+ #
34
+ #photo:
35
+ # mount: '#{CONF_DEFAULT['mount']}'
36
+ # small:
37
+ # width: #{CONF_DEFAULT['small']['width']}
38
+ # style: '#{CONF_DEFAULT['small']['style']}'
39
+ # large:
40
+ # width: #{CONF_DEFAULT['large']['width']}
41
+ EOM
42
+ end
43
+
44
+ def set_conf_default(conf)
45
+ set_conf_default_sub(conf, 'photo', CONF_DEFAULT)
46
+ end
47
+
48
+ # rotate image to fit orientation
49
+ def rotate(img)
50
+ exif = img.get_exif_by_entry(:Orientation)
51
+ return img if !(exif && exif[0] && exif[0][0] == :Orientation)
52
+ case exif[0][1]
53
+ when '1' # Normal
54
+ img
55
+ when '6' # 90 degree
56
+ img.rotate(90) # 90[deg] to clock direction
57
+ when '8' # 270 degree
58
+ img.rotate(-90) # 90[deg] to reversed-clock direction
59
+ else
60
+ img
61
+ end
62
+ end
63
+
64
+ # public photo directory is used to:
65
+ #
66
+ # * store converted photo from original one
67
+ # * protect private photo in 'mount' directory from public web access
68
+ # by copying (with conversion) to it on demand.
69
+ #
70
+ # === INPUTS
71
+ # url:: when true, return url, else, return physical file-system path
72
+ def public_photo_dir(url = true)
73
+ dir = File.join(conf['output_top'], PUBLIC_PHOTO_DIR_DEFAULT)
74
+ raise DirNameConflict if File.file?(dir)
75
+
76
+ if !File.directory?(dir)
77
+ FileUtils.mkdir(dir)
78
+ end
79
+ url ? PUBLIC_PHOTO_DIR_DEFAULT : dir
80
+ end
81
+
82
+ # simplify path to the non-directory name with size.
83
+ #
84
+ # === Example
85
+ # path:: a/b/c.jpg
86
+ # photo_name:: a_b_c_#{size}.jpg
87
+ def photo_name(path, size)
88
+ flat = path.gsub(/\//, '_')
89
+ sprintf("%s_%s%s",
90
+ File.basename(flat, '.*'), size, File.extname(flat))
91
+ end
92
+
93
+ # cached photo path
94
+ #
95
+ # === INPUTS
96
+ # path:: photo-macro path argument
97
+ # size:: :small, or :large
98
+ # url:: when true, return url, else, return physical file-system path
99
+ def photo_path(path, size, url = true)
100
+ File.join(public_photo_dir(url), photo_name(path, size))
101
+ end
102
+
103
+ # create resized, rotated, and 'exif' eliminated cache when:
104
+ # 1. not already created, or
105
+ # 1. cache is obsolete
106
+ #
107
+ # and return the path.
108
+ #
109
+ # === INPUTS
110
+ # path:: photo-macro path argument
111
+ # size:: :small, or :large
112
+ # url:: when true, return url, else, return physical file-system path
113
+ def intern(path, size = :small, url = true)
114
+ protected_path = File.join(conf_photo['mount'], path)
115
+ public_phys_path = photo_path(path, size, false)
116
+ if !File.exist?(public_phys_path) ||
117
+ File::Stat.new(public_phys_path).mtime < File::Stat.new(protected_path).mtime
118
+
119
+ img = Magick::ImageList.new(protected_path)
120
+ width = (s = conf_photo[size.to_s]) && s['width']
121
+ img.resize_to_fit!(width, img.rows * width / img.columns)
122
+ self.rotate(img).
123
+ strip!.
124
+ write(public_phys_path).destroy!
125
+ end
126
+ photo_path(path, size, url)
127
+ end
128
+
129
+ # return <img...> HTML tag for the photo with this macro features.
130
+ def run(*args)
131
+ path = args[0].gsub(/\.\./, '') # sanitize '..'
132
+ style = conf_photo['small']['style']
133
+ small_url = intern(path)
134
+ large_url = intern(path, :large)
135
+ content_tag(:a, :href=>large_url) do
136
+ tag(:img,
137
+ :src => intern(path),
138
+ :class => 'juli_photo_small',
139
+ :style => style)
140
+ end
141
+ end
142
+
143
+ def conf_photo
144
+ @conf_photo ||= conf['photo']
145
+ end
146
+
147
+ private
148
+ def set_conf_default_sub(hash, key, val)
149
+ case val
150
+ when Hash
151
+ hash[key] = {} if !hash[key]
152
+ for k, v in val do
153
+ set_conf_default_sub(hash[key], k, v)
154
+ end
155
+ else
156
+ hash[key] = val if !hash[key]
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,136 @@
1
+ # coding: UTF-8
2
+
3
+ require 'sdbm'
4
+
5
+ module Juli
6
+ module Macro
7
+ # Register tags of this document for tag-search.
8
+ #
9
+ # See 'doc/tag(macro).txt' for the detail how to use it.
10
+ # Here is the implementation document.
11
+ #
12
+ # === Tag-DB ER-chart
13
+ # tag <--->> tag_page <<---> page
14
+ #
15
+ # * tag DB value counts number of wikipages
16
+ #
17
+ # === FILES
18
+ # JURI_REPO/.juli/tag.sdbm:: tag DB
19
+ # JURI_REPO/.juli/page.sdbm:: page DB
20
+ # JURI_REPO/.juli/tag_page.sdbm:: tag-page intersection DB
21
+ class Tag < Base
22
+ SEPARATOR = '_, _'
23
+ NO_TAG = '_no_tag_'
24
+
25
+ attr_accessor :tag_db, :page_db, :tag_page_db
26
+
27
+ def initialize
28
+ super
29
+
30
+ repo_dir = File.join(juli_repo, Juli::REPO)
31
+ @tag_db = SDBM.open(File.join(repo_dir, 'tag.sdbm'))
32
+ @page_db = SDBM.open(File.join(repo_dir, 'page.sdbm'))
33
+ @tag_page_db = SDBM.open(File.join(repo_dir, 'tag_page.sdbm'))
34
+ end
35
+
36
+ # register page
37
+ def on_root(file, root, visitor = nil)
38
+ @wikiname = Juli::Util::to_wikiname(file)
39
+ @page_db[@wikiname] = '1'
40
+ @tag_exists = false
41
+ end
42
+
43
+ def run(*args)
44
+ for tag in args do
45
+ @tag_exists = true
46
+
47
+ # +1 on tag
48
+ @tag_db[tag] = ((@tag_db[tag] || '0').to_i + 1).to_s
49
+ if @wikiname
50
+ @tag_page_db[tag_page_key(tag, @wikiname)] = '1'
51
+ end
52
+ end
53
+ ''
54
+ end
55
+
56
+ # follow-up process to register 'no-tag' if there is no tag in the
57
+ # file.
58
+ def after_root(file, root)
59
+ key = sprintf("%s%s%s", @wikiname, SEPARATOR, NO_TAG)
60
+ if @tag_exists
61
+ @tag_page_db.delete(key)
62
+ else
63
+ @tag_page_db[key] = '1'
64
+ end
65
+ end
66
+
67
+ # value in sdbm in ruby 1.9 looks not to support encoding
68
+ # (in other words, always set to ASCII-8BIT) so that
69
+ # enforce to set it to UTF-8.
70
+ def to_utf8(v)
71
+ v.force_encoding(Encoding::UTF_8)
72
+ end
73
+
74
+ # return pages associated with key
75
+ def pages(key)
76
+ result = []
77
+ for tag_page, val in @tag_page_db do
78
+ if to_utf8(tag_page) =~ /^(.*)#{SEPARATOR}#{key}$/
79
+ result << $1
80
+ end
81
+ end
82
+ result
83
+ end
84
+
85
+ def max_tag_weight
86
+ @tag_db.values.map{|v| v.to_i}.max || 1
87
+ end
88
+
89
+ # return 0..10 in tag weight v.s. max-weight
90
+ def tag_weight_ratio(key)
91
+ v = (@tag_db[key] || '0').to_i
92
+ (v * 10 / max_tag_weight).to_i
93
+ end
94
+
95
+ # delete entry from DB
96
+ def delete_page(file)
97
+ wikiname = Juli::Util::to_wikiname(file)
98
+ @page_db.delete(wikiname)
99
+
100
+ tag_on_the_file = {}
101
+ for tag, val in @tag_db.keys do
102
+ if @tag_page_db[tag_page_key(tag, wikiname)]
103
+ tag_on_the_file[tag] = 1
104
+ end
105
+ end
106
+
107
+ # -1 on tag
108
+ for tag in tag_on_the_file.keys do
109
+ @tag_db[tag] = ((@tag_db[tag] || '1').to_i - 1).to_s
110
+ end
111
+ end
112
+
113
+ # print DB info; debugging purpose. How to use:
114
+ #
115
+ # $ test/console
116
+ # > Dir.chdir('../test/repo')
117
+ # > include Juli::Util
118
+ # > t = Juli::Macro::Tag.new
119
+ # > t.dump
120
+ def dump
121
+ for db in %w(tag_db page_db tag_page_db) do
122
+ printf("%s\n", db)
123
+ for key, val in instance_variable_get('@' + db) do
124
+ printf(" %s\t%s\n", key, val)
125
+ end
126
+ print "\n"
127
+ end
128
+ end
129
+
130
+ private
131
+ def tag_page_key(tag, wikiname)
132
+ sprintf("%s%s%s", wikiname, SEPARATOR, tag)
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,37 @@
1
+ # coding: UTF-8
2
+
3
+ require 'sdbm'
4
+
5
+ module Juli
6
+ module Macro
7
+ # set ERB template.
8
+ #
9
+ # ERB template, which is used on generating HTML from juli-formatted text,
10
+ # can be specified by:
11
+ #
12
+ # 1. juli(1) command line -t option.
13
+ # 1. this macro
14
+ # 1. .juli/config template directive.
15
+ # 1. lib/juli/template
16
+ #
17
+ # See 'doc/template(macro).txt' for the detail how to use it.
18
+ # Here is the implementation document.
19
+ #
20
+ # NOTE: Template class is <b>totally different</b> from TemplateBase.
21
+ # Template is to specify ERB template, while TemplateBase is the
22
+ # base class to provide HTML flagment replacement in a juli document.
23
+ class Template < Base
24
+ # save visitor for later use at run()
25
+ def on_root(file, root, visitor = nil)
26
+ @visitor = visitor
27
+ end
28
+
29
+ def run(*args)
30
+ if @visitor.respond_to?('template=')
31
+ @visitor.template = args[0]
32
+ end
33
+ ''
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,44 @@
1
+ module Juli
2
+ module Macro
3
+ # Base class for HTML template related macros.
4
+ #
5
+ # Derived class can provide HTML template replacement with minimum
6
+ # implementation. Please see Wikipedia case as an example.
7
+ class TemplateBase < Base
8
+ DEFAULT_TEMPLATE = ''
9
+
10
+ def self.conf_template
11
+ ''
12
+ end
13
+
14
+ # return key string used for conf-key
15
+ #
16
+ # Please overwrite this method if it is not just underscore-ed.
17
+ def conf_key
18
+ Juli::Util::underscore(self.class.to_s)
19
+ end
20
+
21
+ # set default value in conf if no .juli/conf defined.
22
+ #
23
+ # Please overwrite this method when this implementation is not your
24
+ # case.
25
+ def set_conf_default(conf)
26
+ if !conf[conf_key]
27
+ conf[conf_key] = self.class::DEFAULT_TEMPLATE
28
+ end
29
+ end
30
+
31
+ # return string used to be replaced with %{...} in conf[conf_key] string.
32
+ #
33
+ # Please overwrite this method if it is not just underscore-ed.
34
+ def place_holder
35
+ conf_key
36
+ end
37
+
38
+ def run(*args)
39
+ template = conf[conf_key]
40
+ template.gsub("%{#{place_holder}}", args[0])
41
+ end
42
+ end
43
+ end
44
+ end