bluemark-smallcage 0.1.3

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 (79) hide show
  1. data/History.txt +48 -0
  2. data/License.txt +20 -0
  3. data/README.txt +1 -0
  4. data/Rakefile +140 -0
  5. data/bin/smc +16 -0
  6. data/lib/smallcage.rb +18 -0
  7. data/lib/smallcage/application.rb +164 -0
  8. data/lib/smallcage/commands/auto.rb +158 -0
  9. data/lib/smallcage/commands/base.rb +19 -0
  10. data/lib/smallcage/commands/clean.rb +32 -0
  11. data/lib/smallcage/commands/export.rb +41 -0
  12. data/lib/smallcage/commands/import.rb +217 -0
  13. data/lib/smallcage/commands/manifest.rb +39 -0
  14. data/lib/smallcage/commands/server.rb +15 -0
  15. data/lib/smallcage/commands/update.rb +121 -0
  16. data/lib/smallcage/document_path.rb +46 -0
  17. data/lib/smallcage/erb_base.rb +16 -0
  18. data/lib/smallcage/http_server.rb +66 -0
  19. data/lib/smallcage/loader.rb +278 -0
  20. data/lib/smallcage/misc.rb +13 -0
  21. data/lib/smallcage/renderer.rb +19 -0
  22. data/lib/smallcage/resources/Manifest.erb +19 -0
  23. data/lib/smallcage/resources/auto.html +119 -0
  24. data/lib/smallcage/runner.rb +51 -0
  25. data/lib/smallcage/version.rb +9 -0
  26. data/project/base/_smc/helpers/base_helper.rb +41 -0
  27. data/project/base/_smc/helpers/site_helper.rb +5 -0
  28. data/project/base/_smc/templates/default.rhtml +5 -0
  29. data/project/base/_smc/templates/footer.rhtml +0 -0
  30. data/project/base/_smc/templates/header.rhtml +0 -0
  31. data/project/bluecloth/_smc/helpers/blue_cloth_helper.rb +10 -0
  32. data/project/bluecloth/_smc/templates/markdown.rhtml +5 -0
  33. data/project/lang/_smc/helpers/lang_helper.rb +19 -0
  34. data/project/lang/_smc/templates/other_lang.rhtml +6 -0
  35. data/project/news/_smc/helpers/news_helper.rb +36 -0
  36. data/project/nkf/_smc/filters/filters.yml +3 -0
  37. data/project/nkf/_smc/filters/nkf_filter.rb +15 -0
  38. data/project/rake/_smc/Rakefile +68 -0
  39. data/project/redcloth/_smc/helpers/red_cloth_helper.rb +10 -0
  40. data/project/redcloth/_smc/templates/textile.rhtml +5 -0
  41. data/project/relpath/_smc/filters/filters.yml +2 -0
  42. data/project/relpath/_smc/filters/relpath_filter.rb +13 -0
  43. data/project/standard/_dir.smc +2 -0
  44. data/project/standard/_smc/helpers/base_helper.rb +34 -0
  45. data/project/standard/_smc/helpers/menu_helper.rb +23 -0
  46. data/project/standard/_smc/templates/default.rhtml +5 -0
  47. data/project/standard/_smc/templates/footer.rhtml +13 -0
  48. data/project/standard/_smc/templates/header.rhtml +37 -0
  49. data/project/standard/_smc/templates/menu.rhtml +6 -0
  50. data/project/standard/_smc/templates/redirect.rhtml +13 -0
  51. data/project/standard/_smc/templates/sidebar.rhtml +7 -0
  52. data/project/standard/_smc/templates/topic_path.rhtml +6 -0
  53. data/project/standard/common/css/default.css +145 -0
  54. data/project/standard/common/css/print.css +0 -0
  55. data/project/standard/index.html.smc +3 -0
  56. data/project/standard/sample/_dir.smc +1 -0
  57. data/project/standard/sample/index.html.smc +7 -0
  58. data/project/standard/sample/redirect.html.smc +2 -0
  59. data/project/standard/sample/sub/_dir.smc +1 -0
  60. data/project/standard/sample/sub/contents.html.smc +3 -0
  61. data/project/standard/sample/sub/index.html.smc +7 -0
  62. data/spec/data/htdocs1/_dir.smc +0 -0
  63. data/spec/data/htdocs1/a/b/c/index.html.smc +6 -0
  64. data/spec/data/htdocs2/_smc/templates/dummy.rhtml +0 -0
  65. data/spec/data/htdocs2/a/b/c/test.html +1 -0
  66. data/spec/data/htdocs2/a/b/test.html +1 -0
  67. data/spec/data/htdocs2/a/test.html.smc +2 -0
  68. data/spec/document_path_spec.rb +42 -0
  69. data/spec/export_spec.rb +45 -0
  70. data/spec/import_spec.rb +20 -0
  71. data/spec/loader_spec.rb +55 -0
  72. data/spec/manifest_spec.rb +39 -0
  73. data/spec/misc_spec.rb +25 -0
  74. data/spec/smallcage_spec.rb +40 -0
  75. data/spec/spec.opts +1 -0
  76. data/spec/spec_helper.rb +9 -0
  77. data/test/test_helper.rb +2 -0
  78. data/test/test_smallcage.rb +11 -0
  79. metadata +193 -0
@@ -0,0 +1,19 @@
1
+ module SmallCage::Commands
2
+ class Base
3
+ def self.execute(opts)
4
+ self.new(opts).execute
5
+ end
6
+
7
+ def initialize(opts)
8
+ @opts = opts
9
+ end
10
+
11
+ def execute
12
+ end
13
+
14
+ def quiet?
15
+ return @opts[:quiet]
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ module SmallCage::Commands
2
+ class Clean
3
+ def self.execute(opts)
4
+ self.new(opts).execute
5
+ end
6
+
7
+ def initialize(opts)
8
+ @opts = opts
9
+ end
10
+
11
+ def execute
12
+ target = Pathname.new(@opts[:path])
13
+ unless target.exist?
14
+ raise "target directory or file does not exist.: " + target.to_s
15
+ end
16
+
17
+ loader = SmallCage::Loader.new(target)
18
+ loader.each_smc_obj do |obj|
19
+ if obj["path"].exist?
20
+ obj["path"].delete
21
+ puts "D " + obj["uri"] unless @opts[:quiet]
22
+ end
23
+ end
24
+
25
+ tmpdir = loader.root + "./_smc/tmp"
26
+ if tmpdir.exist?
27
+ FileUtils.rm_r(tmpdir)
28
+ puts "D /_smc/tmp" unless @opts[:quiet]
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,41 @@
1
+ module SmallCage::Commands
2
+ class Export < SmallCage::Commands::Base
3
+ def execute
4
+ target = Pathname.new(@opts[:path])
5
+ unless target.exist?
6
+ raise target.to_s + " does not exist."
7
+ end
8
+
9
+ loader = SmallCage::Loader.new(target)
10
+ root = loader.root
11
+
12
+ if @opts[:out].nil?
13
+ out = root + ("./_smc/tmp/export/" + Time.now.strftime("%Y%m%d%H%M%S"))
14
+ else
15
+ out = Pathname.new(@opts[:out])
16
+ end
17
+ if out.exist?
18
+ raise out.to_s + " already exist."
19
+ end
20
+ FileUtils.makedirs(out)
21
+ out = out.realpath
22
+
23
+ # TODO create empty directories
24
+ loader.each_not_smc_file do |docpath|
25
+ dir = Pathname.new(docpath.uri).parent
26
+ outdir = out + ("." + dir.to_s)
27
+ FileUtils.makedirs(outdir)
28
+ FileUtils.cp(docpath.path, outdir)
29
+ puts "A " + docpath.uri unless quiet?
30
+ end
31
+
32
+ unless quiet?
33
+ puts ""
34
+ puts "All contents exported to:"
35
+ puts " #{out.to_s}"
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,217 @@
1
+ module SmallCage::Commands
2
+ class Import
3
+ def self.execute(opts)
4
+ self.new(opts).execute
5
+ end
6
+
7
+ def initialize(opts)
8
+ @opts = opts
9
+ if @opts[:from] == "default"
10
+ @opts[:from] = "base,standard"
11
+ end
12
+ @project_dir = Pathname.new(__FILE__) + "../../../../project"
13
+ end
14
+
15
+ def qp(str = "")
16
+ print str unless @opts[:quiet]
17
+ end
18
+
19
+ def qps(str = "")
20
+ puts str unless @opts[:quiet]
21
+ end
22
+
23
+ def execute
24
+ @dest = Pathname.new(@opts[:to])
25
+
26
+ Dir.mkdir(@dest) unless @dest.exist?
27
+ return unless @dest.directory?
28
+
29
+ from = @opts[:from].split(/,/)
30
+ from.each do |f|
31
+ qps
32
+ qps "Import: #{f}"
33
+ if f =~ %r{^https?://}
34
+ import_external(f)
35
+ elsif f =~ %r{^\w+$}
36
+ import(f)
37
+ else
38
+ end
39
+ end
40
+ end
41
+
42
+ def import(from)
43
+ d = @project_dir + from
44
+ return unless d.directory?
45
+ @entries = local_entries(d)
46
+ unless @opts[:quiet]
47
+ return unless confirm_entries
48
+ end
49
+ import_entries
50
+ end
51
+
52
+ def import_external
53
+ @entries = external_entries
54
+ unless @opts[:quiet]
55
+ return unless confirm_entries
56
+ end
57
+ import_entries
58
+ end
59
+
60
+ def import_entries
61
+ failed = []
62
+ @entries.each do |e|
63
+ if e.overwrite?
64
+ qps "M /" + e.path
65
+ elsif ! e.exist?
66
+ qps "A /" + e.path
67
+ elsif e.to.directory?
68
+ # nothing
69
+ else
70
+ qps "? /" + e.path
71
+ end
72
+
73
+ begin
74
+ e.import
75
+ rescue
76
+ failed << e
77
+ qps "F /" + e.path
78
+ end
79
+ end
80
+
81
+ unless failed.empty?
82
+ qps "FAILED:"
83
+ failed.each do |e|
84
+ qps " " + e.path
85
+ end
86
+ end
87
+ end
88
+ private :import_entries
89
+
90
+ def local_entries(d)
91
+ result = []
92
+ Dir.chdir(d) do
93
+ Dir.glob("**/*") do |f|
94
+ e = ImportEntry.new
95
+ e.path = f
96
+ e.from = d + f
97
+ e.to = @dest + f
98
+ result << e
99
+ end
100
+ end
101
+ return result
102
+ end
103
+ private :local_entries
104
+
105
+ def external_entries(uri)
106
+ if uri !~ %r{/$}
107
+ uri += "/"
108
+ end
109
+ mfuri = uri + "Manifest.html"
110
+
111
+ source = open(mfuri) {|io| io.read }
112
+ result = []
113
+
114
+ files = source.scan(%r{<li><a href="(./[^"]+)">(./[^<]+)</a></li>})
115
+ files.each do |f|
116
+ raise "illegal path:#{f[0]},#{f[1]}" if f[0] != f[1]
117
+ raise "illegal path:#{f[0]}" if f[0] =~ %r{/\.\.}
118
+ path = f[0]
119
+ e = ImportEntry.new
120
+ e.path = path
121
+ e.from = uri + path
122
+ e.to = @dest + path
123
+ result << e
124
+ end
125
+
126
+ return result
127
+ end
128
+ private :external_entries
129
+
130
+ def confirm_entries
131
+ overwrite = []
132
+
133
+ qps "Create:"
134
+ @entries.each do |e|
135
+ if e.overwrite?
136
+ overwrite << e
137
+ elsif ! e.exist?
138
+ qps " /" + e.path
139
+ end
140
+ end
141
+ qps
142
+
143
+ unless overwrite.empty?
144
+ qps "Overwrite:"
145
+ overwrite.each do |e|
146
+ qps " /" + e.path
147
+ end
148
+ qps
149
+ end
150
+
151
+ return y_or_n("Import these files?[yN]: ", false)
152
+ end
153
+ private :confirm_entries
154
+
155
+ def y_or_n(prompt, default)
156
+ loop do
157
+ print prompt
158
+ yn = STDIN.gets.strip
159
+ if yn =~ /^(y|yes)$/i
160
+ return true
161
+ elsif yn =~ /^(n|no)$/i
162
+ return false
163
+ elsif yn == ""
164
+ return default
165
+ end
166
+ end
167
+ end
168
+ private :y_or_n
169
+
170
+
171
+ class ImportEntry
172
+ attr_accessor :path, :from, :to
173
+
174
+ def import
175
+ if external?
176
+ copy_external
177
+ else
178
+ copy_local
179
+ end
180
+ end
181
+
182
+ def external?
183
+ from =~ %r{^https?://}
184
+ end
185
+
186
+ def exist?
187
+ to.exist?
188
+ end
189
+
190
+ def overwrite?
191
+ to.file?
192
+ end
193
+
194
+ def copy_local
195
+ if from.directory?
196
+ FileUtils.makedirs(to)
197
+ else
198
+ FileUtils.makedirs(to.parent)
199
+ FileUtils.copy(from, to)
200
+ end
201
+ end
202
+ private :copy_local
203
+
204
+ def copy_external
205
+ if from =~ %r{/$}
206
+ FileUtils.makedirs(to)
207
+ else
208
+ FileUtils.makedirs(to.parent)
209
+ s = open(from) {|io| io.read }
210
+ open(to, "w") {|io| io << s }
211
+ end
212
+ end
213
+ private :copy_external
214
+
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,39 @@
1
+ module SmallCage::Commands
2
+ class Manifest
3
+ def self.execute(opts)
4
+ self.new(opts).execute
5
+ end
6
+
7
+ def initialize(opts)
8
+ @opts = opts
9
+ end
10
+
11
+ def execute
12
+ entries = []
13
+ root = Pathname.new(@opts[:path])
14
+ Dir.chdir(root) do
15
+ Dir.glob("**/*") do |f|
16
+ entries << f
17
+ end
18
+ end
19
+
20
+ tmp = []
21
+ entries.each do |f|
22
+ path = root + f
23
+ f = "./" + f
24
+ if path.directory?
25
+ f = f + "/"
26
+ end
27
+ next if path.basename.to_s == "Manifest.html"
28
+ tmp << f
29
+ end
30
+ entries = tmp
31
+
32
+ template = File.dirname(__FILE__) + "/../resources/Manifest.erb"
33
+ source = ERB.new(File.read(template), nil, "-").result(binding)
34
+ open(root + "Manifest.html", "w") do |io|
35
+ io << source
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module SmallCage::Commands
2
+ class Server
3
+ def self.execute(opts)
4
+ document_root = opts[:path]
5
+ port = opts[:port]
6
+
7
+ server = SmallCage::HTTPServer.new(document_root, port)
8
+
9
+ sighandler = Proc.new {|signal| server.shutdown}
10
+ SmallCage::Application.add_signal_handler(["INT", "TERM"], sighandler)
11
+
12
+ server.start
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,121 @@
1
+ module SmallCage::Commands
2
+ class Update
3
+ def self.execute(opts)
4
+ self.new(opts).execute
5
+ end
6
+
7
+ def initialize(opts)
8
+ @opts = opts
9
+ end
10
+
11
+ def execute
12
+ target = Pathname.new(@opts[:path])
13
+ unless target.exist?
14
+ raise "target directory or file does not exist.: " + target.to_s
15
+ end
16
+
17
+ @loader = SmallCage::Loader.new(target)
18
+ @renderer = SmallCage::Renderer.new(@loader)
19
+
20
+ urilist = render_smc_files
21
+ if list_file.exist?
22
+ urilist = delete_expired_files(urilist)
23
+ end
24
+ save_list(urilist)
25
+ end
26
+
27
+ def render_smc_files
28
+ urilist = []
29
+ @loader.each_smc_obj do |obj|
30
+ urilist << obj["uri"].smc
31
+ mark = obj["path"].exist? ? "U " : "A "
32
+ render_smc_obj(obj)
33
+ puts mark + obj["uri"] unless @opts[:quiet]
34
+ end
35
+ return urilist
36
+ end
37
+ private :render_smc_files
38
+
39
+ def render_smc_obj(obj)
40
+ result = @renderer.render(obj["template"], obj)
41
+ result = after_rendering_filters(obj, result)
42
+ output_result(obj, result)
43
+ end
44
+ private :render_smc_obj
45
+
46
+ def delete_expired_files(urilist)
47
+ old_urilist = load_list
48
+ root = @loader.root
49
+ target_uri = SmallCage::DocumentPath.new(root, @loader.target).uri
50
+
51
+ if @loader.target.file?
52
+ old_urilist << target_uri unless old_urilist.include?(target_uri)
53
+ return old_urilist
54
+ end
55
+
56
+ target_uris = []
57
+ not_target_uris = []
58
+ old_urilist.each do |uri|
59
+ if uri.index(target_uri) == 0
60
+ target_uris << uri
61
+ else
62
+ not_target_uris << uri
63
+ end
64
+ end
65
+
66
+ deletelist = target_uris - urilist
67
+
68
+ deletelist.each do |uri|
69
+ delfile = SmallCage::DocumentPath.new(root, root + ("." + uri)).outfile
70
+ next unless delfile.path.file?
71
+
72
+ File.delete(delfile.path)
73
+ puts "D #{delfile.uri}" unless @opts[:quiet]
74
+ end
75
+
76
+ return (not_target_uris + urilist).sort
77
+ end
78
+ private :delete_expired_files
79
+
80
+ def after_rendering_filters(obj, result)
81
+ filters = @loader.filters("after_rendering_filters")
82
+ filters.each do |f|
83
+ result = f.after_rendering_filter(obj, result)
84
+ end
85
+ return result
86
+ end
87
+ private :after_rendering_filters
88
+
89
+ def save_list(urilist)
90
+ f = list_file
91
+ FileUtils.makedirs(f.parent)
92
+ open(f, "w") do |io|
93
+ io << "version: " + SmallCage::VERSION::STRING + "\n"
94
+ urilist.each do |u|
95
+ io << u + "\n"
96
+ end
97
+ end
98
+ end
99
+ private :save_list
100
+
101
+ def load_list
102
+ txt = File.read(list_file)
103
+ result = txt.split(/\n/)
104
+ result.shift
105
+ return result
106
+ end
107
+ private :load_list
108
+
109
+ def list_file
110
+ @loader.root + "./_smc/tmp/list.txt"
111
+ end
112
+ private :list_file
113
+
114
+ def output_result(obj, str)
115
+ open(obj["path"], "w") do |io|
116
+ io << str
117
+ end
118
+ end
119
+ private :output_result
120
+ end
121
+ end