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