gumdrop 0.8.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. data/.gitignore +3 -0
  2. data/ChangeLog.md +13 -0
  3. data/Gemfile +6 -2
  4. data/Gemfile.lock +43 -3
  5. data/Rakefile +37 -21
  6. data/Readme.md +60 -158
  7. data/bin/gumdrop +2 -1
  8. data/gumdrop.gemspec +11 -4
  9. data/lib/gumdrop/builder.rb +164 -0
  10. data/lib/gumdrop/cli/external.rb +14 -9
  11. data/lib/gumdrop/cli/internal.rb +54 -22
  12. data/lib/gumdrop/cli.rb +21 -0
  13. data/lib/gumdrop/content.rb +195 -132
  14. data/lib/gumdrop/data.rb +185 -0
  15. data/lib/gumdrop/data_providers/csv.rb +18 -0
  16. data/lib/gumdrop/data_providers/pstore.rb +25 -0
  17. data/lib/gumdrop/data_providers/sqlite.rb +43 -0
  18. data/lib/gumdrop/data_providers/xml.rb +15 -0
  19. data/lib/gumdrop/data_providers/yaml_and_json.rb +18 -0
  20. data/lib/gumdrop/data_providers/yamldb.rb +18 -0
  21. data/lib/gumdrop/data_providers/yamldoc.rb +12 -0
  22. data/lib/gumdrop/generator.rb +118 -94
  23. data/lib/gumdrop/renderer.rb +272 -0
  24. data/lib/gumdrop/server.rb +36 -27
  25. data/lib/gumdrop/site.rb +283 -338
  26. data/lib/gumdrop/support/compressor.rb +52 -0
  27. data/lib/gumdrop/support/sprockets.rb +14 -23
  28. data/lib/gumdrop/support/stitch.rb +25 -14
  29. data/lib/gumdrop/support/yaml_doc_template.rb +29 -0
  30. data/lib/gumdrop/util/configurable.rb +44 -0
  31. data/lib/gumdrop/util/core_ex.rb +84 -0
  32. data/lib/gumdrop/util/eventable.rb +35 -0
  33. data/lib/gumdrop/util/hash_object.rb +70 -0
  34. data/lib/gumdrop/util/loggable.rb +44 -0
  35. data/lib/gumdrop/util/pager.rb +51 -0
  36. data/lib/gumdrop/{support → util}/proxy_handler.rb +7 -6
  37. data/lib/gumdrop/util/scanner.rb +47 -0
  38. data/lib/gumdrop/util/site_access.rb +16 -0
  39. data/lib/gumdrop/util/view_helpers.rb +50 -0
  40. data/lib/gumdrop/util/yaml_doc.rb +51 -0
  41. data/lib/gumdrop/version.rb +2 -2
  42. data/lib/gumdrop.rb +40 -77
  43. data/specs/content_spec.rb +83 -73
  44. data/specs/fixtures/expected/data-access/from-csv.html +4 -0
  45. data/specs/fixtures/expected/data-access/from-json.html +6 -0
  46. data/specs/fixtures/expected/data-access/from-sqlite.html +5 -0
  47. data/specs/fixtures/expected/data-access/from-xml.html +4 -0
  48. data/specs/fixtures/expected/data-access/from-yaml.html +5 -0
  49. data/specs/fixtures/expected/data-access/from-yamldb.html +5 -0
  50. data/specs/fixtures/expected/data-access/from-yamldoc.html +2 -0
  51. data/specs/fixtures/expected/gen-with-block/as-file.html +1 -0
  52. data/specs/fixtures/expected/gen-with-block/as-plain.html +1 -0
  53. data/specs/fixtures/expected/gen-with-block/layout-nested.html +1 -0
  54. data/specs/fixtures/expected/gen-with-block/layout-nil.html +1 -0
  55. data/specs/fixtures/expected/gen-with-block/layout-wrap.html +1 -0
  56. data/specs/fixtures/expected/gen-with-inline-render/0-as-file.html +4 -0
  57. data/specs/fixtures/expected/gen-with-inline-render/0-as-plain.html +4 -0
  58. data/specs/fixtures/expected/gen-with-inline-render/0-layout-nil.html +4 -0
  59. data/specs/fixtures/expected/gen-with-inline-render/0-layout-sub.html +4 -0
  60. data/specs/fixtures/expected/gen-with-inline-render/0-layout-wrap.html +4 -0
  61. data/specs/fixtures/expected/gen-with-inline-render/1-as-file.html +4 -0
  62. data/specs/fixtures/expected/gen-with-inline-render/1-as-plain.html +4 -0
  63. data/specs/fixtures/expected/gen-with-inline-render/1-layout-nil.html +4 -0
  64. data/specs/fixtures/expected/gen-with-inline-render/1-layout-sub.html +4 -0
  65. data/specs/fixtures/expected/gen-with-inline-render/1-layout-wrap.html +4 -0
  66. data/specs/fixtures/expected/goodbye.html +1 -0
  67. data/specs/fixtures/expected/hello.html +1 -0
  68. data/specs/fixtures/expected/image.png +0 -0
  69. data/specs/fixtures/expected/index.html +47 -0
  70. data/specs/fixtures/expected/js/sprockets-app.js +7 -0
  71. data/specs/fixtures/expected/js/stitch-app.js +65 -0
  72. data/specs/fixtures/expected/js/stitch-app.min.js +5 -0
  73. data/specs/fixtures/expected/js/stitch-app.min.src.js +65 -0
  74. data/specs/fixtures/expected/js/straight.js +8 -0
  75. data/specs/fixtures/expected/js/test-coffee.js +5 -0
  76. data/specs/fixtures/expected/pages/docs/force-abs.html +2 -0
  77. data/specs/fixtures/expected/pages/docs/index.html +2 -0
  78. data/specs/fixtures/expected/partials/hoisted-data.html +3 -0
  79. data/specs/fixtures/expected/partials/nested.html +7 -0
  80. data/specs/fixtures/expected/partials/params.html +1 -0
  81. data/specs/fixtures/expected/partials/with-layouts.html +1 -0
  82. data/specs/fixtures/expected/robots.txt +1 -0
  83. data/specs/fixtures/expected/test-multi-procs.html +4 -0
  84. data/specs/fixtures/expected/test-nested-layout.html +1 -0
  85. data/specs/fixtures/expected/test-no-layout.html +2 -0
  86. data/specs/fixtures/expected/test-yamldoc.html +1 -0
  87. data/specs/fixtures/expected/test.html +2 -0
  88. data/{templates/backbone → specs/fixtures/source}/Gemfile +8 -4
  89. data/specs/fixtures/source/Gemfile.lock +84 -0
  90. data/specs/fixtures/source/Gumdrop +60 -9
  91. data/specs/fixtures/source/data/csv_data.csv +2 -0
  92. data/specs/fixtures/source/data/json_data.json +13 -0
  93. data/specs/fixtures/source/data/sql_data.sqlite +0 -0
  94. data/specs/fixtures/source/data/xml_data.xml +4 -0
  95. data/specs/fixtures/source/data/yaml_db.yamldb +9 -0
  96. data/specs/fixtures/source/data/yaml_items.yaml +2 -0
  97. data/specs/fixtures/source/data/yamldoc.yamldoc +4 -0
  98. data/specs/fixtures/source/data-access/from-csv.html.erb +4 -0
  99. data/specs/fixtures/source/data-access/from-json.html.erb +6 -0
  100. data/specs/fixtures/source/data-access/from-sqlite.html.erb +5 -0
  101. data/specs/fixtures/source/data-access/from-xml.html.erb +5 -0
  102. data/specs/fixtures/source/data-access/from-yaml.html.erb +5 -0
  103. data/specs/fixtures/source/data-access/from-yamldb.html.erb +5 -0
  104. data/specs/fixtures/source/data-access/from-yamldoc.html.erb +2 -0
  105. data/specs/fixtures/source/gen-with-inline-render.generator +7 -0
  106. data/specs/fixtures/source/goodbye.html.erb +1 -0
  107. data/specs/fixtures/source/hello.html +1 -0
  108. data/specs/fixtures/source/image.png +0 -0
  109. data/specs/fixtures/source/index.html.erb +6 -0
  110. data/specs/fixtures/source/js/sprockets/app.js +2 -0
  111. data/specs/fixtures/source/js/sprockets/view.js.coffee +1 -0
  112. data/specs/fixtures/source/js/stitch/app.js +1 -0
  113. data/specs/fixtures/source/js/stitch/view.js.coffee +1 -0
  114. data/specs/fixtures/source/js/straight.js +8 -0
  115. data/specs/fixtures/source/js/test-coffee.js.coffee +1 -0
  116. data/specs/fixtures/source/layouts/site.layout.erb +1 -0
  117. data/specs/fixtures/source/layouts/sub.layout.erb +1 -0
  118. data/specs/fixtures/source/layouts/wrap.layout.erb +1 -0
  119. data/specs/fixtures/source/pages/_users-nested.html.erb +7 -0
  120. data/specs/fixtures/source/pages/docs/force-abs.html.erb +2 -0
  121. data/specs/fixtures/source/pages/docs/index.html.erb +2 -0
  122. data/specs/fixtures/source/partials/_post_entry.html.erb +4 -0
  123. data/specs/fixtures/source/partials/_provides_name.html.erb +1 -0
  124. data/specs/fixtures/source/partials/_user-params.html.erb +1 -0
  125. data/specs/fixtures/source/partials/_user.html.erb +1 -0
  126. data/specs/fixtures/source/partials/_user_sets_layout.html.erb +1 -0
  127. data/specs/fixtures/source/partials/hoisted-data.html.erb +6 -0
  128. data/specs/fixtures/source/partials/nested.html.erb +1 -0
  129. data/specs/fixtures/source/partials/params.html.erb +1 -0
  130. data/specs/fixtures/source/partials/with-layouts.html.erb +1 -0
  131. data/specs/fixtures/source/test-multi-procs.html.markdown.erb +3 -0
  132. data/specs/fixtures/source/test-nested-layout.html.erb +1 -0
  133. data/specs/fixtures/source/test-no-layout.html.erb +2 -0
  134. data/specs/fixtures/source/test-yamldoc.html.erb.yamldoc +4 -0
  135. data/specs/fixtures/source/test.html.erb +2 -0
  136. data/specs/hash_object_spec.rb +53 -8
  137. data/specs/render_spec.rb +10 -0
  138. data/specs/site_spec.rb +79 -0
  139. data/specs/spec_helper.rb +59 -0
  140. data/templates/blank/Gemfile +0 -4
  141. data/templates/blank/Gumdrop +180 -113
  142. data/templates/default/Gemfile +3 -8
  143. data/templates/default/Gumdrop +166 -95
  144. data/templates/default/ReadMe.md +14 -0
  145. data/templates/default/config.ru +1 -0
  146. data/templates/default/data/news/20120703.yamldoc +14 -0
  147. data/templates/default/data/news/20120704.yamldoc +8 -0
  148. data/templates/{backbone/source/feed.xml.builder.txt → default/source/feed.xml.builder} +4 -4
  149. data/templates/default/source/index.html.erb +10 -1
  150. data/templates/default/source/theme/layout/_sidebar.html +1 -0
  151. data/templates/{backbone/source/theme/templates/site.template.slim → default/source/theme/layout/site.layout.slim} +3 -3
  152. metadata +212 -63
  153. data/lib/gumdrop/context.rb +0 -135
  154. data/lib/gumdrop/data_manager.rb +0 -214
  155. data/lib/gumdrop/support/base_packager.rb +0 -60
  156. data/lib/gumdrop/support/callbacks.rb +0 -30
  157. data/lib/gumdrop/support/hash_object.rb +0 -22
  158. data/lib/gumdrop/view_helpers.rb +0 -25
  159. data/notes.md +0 -347
  160. data/specs/deferred_loader_spec.rb +0 -31
  161. data/specs/fixtures/expected/posts/post1.html +0 -1
  162. data/specs/fixtures/expected/posts/post1.js +0 -14
  163. data/specs/fixtures/expected/posts/post2.html +0 -5
  164. data/specs/fixtures/expected/sub/sub/sub/test.html +0 -5
  165. data/specs/fixtures/expected/sub/sub/sub/test2.html +0 -5
  166. data/specs/fixtures/expected/test.js +0 -14
  167. data/specs/fixtures/source/posts/post1.html.slim +0 -6
  168. data/specs/fixtures/source/posts/post1.js.coffee +0 -3
  169. data/specs/fixtures/source/posts/post2.html.erb +0 -5
  170. data/specs/fixtures/source/sub/sub/sub/test.html +0 -5
  171. data/specs/fixtures/source/sub/sub/sub/test2.html.erb +0 -5
  172. data/specs/fixtures/source/test.js.coffee +0 -4
  173. data/specs/fixtures/source/test.js.erb.coffee +0 -3
  174. data/templates/backbone/Gumdrop +0 -123
  175. data/templates/backbone/Rakefile +0 -38
  176. data/templates/backbone/app/app.js.coffee +0 -49
  177. data/templates/backbone/app/init.js.coffee +0 -10
  178. data/templates/backbone/app/models/.gitkeep +0 -0
  179. data/templates/backbone/app/utils/index.js.coffee +0 -27
  180. data/templates/backbone/app/views/home.js.coffee +0 -17
  181. data/templates/backbone/app/views/styles/home.scss +0 -8
  182. data/templates/backbone/app/views/templates/home.mustache +0 -2
  183. data/templates/backbone/config.ru +0 -20
  184. data/templates/backbone/lib/all.js.coffee +0 -18
  185. data/templates/backbone/lib/backbone.js +0 -1158
  186. data/templates/backbone/lib/hogan.js +0 -509
  187. data/templates/backbone/lib/jquery.js +0 -9266
  188. data/templates/backbone/lib/underscore.js +0 -981
  189. data/templates/backbone/powrc +0 -2
  190. data/templates/backbone/source/default.htaccess.erb +0 -27
  191. data/templates/backbone/source/favicon.ico +0 -0
  192. data/templates/backbone/source/index.html.erb +0 -2
  193. data/templates/backbone/source/theme/screen.css.sass +0 -9
  194. data/templates/backbone/source/theme/scripts/app.js.coffee +0 -4
  195. data/templates/backbone/source/theme/styles/_tools.scss +0 -434
  196. data/templates/backbone/source/theme/templates/app.template.slim +0 -14
  197. data/templates/default/Rakefile +0 -38
  198. data/templates/default/powrc +0 -2
  199. data/templates/default/source/default.htaccess.erb +0 -27
  200. data/templates/default/source/feed.xml.builder.txt +0 -23
  201. data/templates/default/source/theme/templates/site.template.slim +0 -33
@@ -14,29 +14,33 @@ module Gumdrop::CLI
14
14
  method_option :env, default:'production', aliases:'-e'
15
15
  method_option :assets, aliases:'-a', type: :array, desc:"List of assets to render."
16
16
  method_option :quiet, default:false, aliases:'-q', type: :boolean
17
- method_option :subdued, default:false, aliases:'-s', type: :boolean, desc:"Subdued output (....)"
18
17
  method_option :resume, default:false, aliases:'-r', type: :boolean, desc:"Auto resume rendering after any errors"
19
- def build()
20
- Gumdrop.run(options)
18
+ method_option :force, default:false, aliases:'-f', type: :boolean, desc:"Ignore file checksums and create all files"
19
+ def build
20
+ if options[:quiet]
21
+ Gumdrop.configure do |c|
22
+ c.log_level= :warn
23
+ end
24
+ end
25
+ Gumdrop.run options.merge(mode:'build')
21
26
  end
22
27
 
23
28
  desc 'server', 'Run development server'
24
- method_option :env, default:'production', aliases:'-e'
25
29
  def server
30
+ Gumdrop.site.options = options.merge(mode:'build')
26
31
  Gumdrop::Server
27
32
  end
28
33
 
29
34
  desc 'watch', "Watch filesystem for changes and recompile"
30
- method_option :env, default:'production', aliases:'-e'
31
35
  method_option :quiet, default:false, aliases:'-q', type: :boolean
32
36
  method_option :subdued, default:false, aliases:'-s', type: :boolean, desc:"Subdued output (....)"
33
37
  method_option :resume, default:false, aliases:'-r', type: :boolean, desc:"Auto resume rendering after any errors"
34
38
  def watch
35
- Gumdrop.run options
36
- paths= [SITE.src_path]
37
- paths << SITE.data_path if File.directory? SITE.data_path
39
+ Gumdrop.run options.merge(mode:'merge')
40
+ paths= [Gumdrop.site.source_dir, Gumdrop.site.sitefile] #? Sitefile too?
41
+ paths << Gumdrop.site.data_dir if File.directory? Gumdrop.site.data_dir
38
42
  Listen.to(*paths, :latency => 0.5) do |m, a, r|
39
- SITE.rebuild
43
+ Gumdrop.rebuild options.merge(mode:'merge')
40
44
  end
41
45
  end
42
46
 
@@ -50,26 +54,54 @@ module Gumdrop::CLI
50
54
  else
51
55
  say "Creating template: #{name}"
52
56
  say " ~/.gumdrop/templates/#{name}"
53
- site_root= Gumdrop.site_dirname
57
+ site_root= Gumdrop.site.root
54
58
  FileUtils.mkdir_p File.dirname(template_path)
55
- FileUtils.cp_r File.join(site_root, "."), template_path
59
+ FileUtils.cp_r (site_root / "."), template_path
56
60
  end
57
61
  end
58
62
 
59
- private
60
-
61
- def home_path(name="")
62
- File.expand_path File.join("~", ".gumdrop", name)
63
- end
64
63
 
65
- def home_template_path(template)
66
- home_path 'tempaltes', template
64
+ desc 'uris', "Print list of the uri that will be generated."
65
+ def uris
66
+ Gumdrop.configure do |c|
67
+ c.log_level= :error
67
68
  end
69
+ Gumdrop.site.scan
68
70
 
69
- def local_path(name="")
70
- File.join( ".", name ) # ?
71
+ say "Gumdrop found:"
72
+ say ""
73
+ Gumdrop.site.contents.keys.sort.each do |uri|
74
+ content= Gumdrop.site.contents[uri]
75
+ blackout= Gumdrop.site.in_blacklist?(uri) ? 'X' : ' '
76
+ generated= content.generated? ? '*' : ' '
77
+ binary= content.binary? ? '!' : ' '
78
+ say " #{blackout + generated + binary} #{content.uri}"
71
79
  end
80
+ say ""
81
+ say "Legend:"
82
+ say " X = On on the blacklist"
83
+ say " * = Generated (not on fs)"
84
+ say " ! = Binary file"
85
+ end
86
+
87
+ desc "version", "Displays Gumdrop version"
88
+ def version
89
+ say "Gumdrop v#{ Gumdrop::VERSION }"
90
+ end
91
+
92
+
93
+ private
94
+
95
+ def home_path(name="")
96
+ File.expand_path "~" /".gumdrop" / name
97
+ end
98
+
99
+ def home_template_path(template)
100
+ home_path 'templates' / template
101
+ end
102
+
103
+ def local_path(name="")
104
+ "." / name
105
+ end
72
106
  end
73
107
  end
74
-
75
- SITE= Gumdrop::Site.new Gumdrop.fetch_site_file unless defined?( SITE )
@@ -0,0 +1,21 @@
1
+ module Gumdrop
2
+
3
+ class << self
4
+
5
+ # Allows addition of CLI commands from Gumdrop file:
6
+ #
7
+ # Gumdrop.cli do
8
+ # desc 'ping'
9
+ # method_option :loud, default:false
10
+ # def ping
11
+ # say options[:loud] ? 'PONG!' : 'pong'
12
+ # end
13
+ # end
14
+ #
15
+ def cli(&block)
16
+ CLI::Internal.class_eval &block
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -1,36 +1,34 @@
1
-
2
1
  module Gumdrop
3
-
2
+
3
+ # All content (layouts, partials, images, html, js css, etc) found in
4
+ # the source directory are represented as a Content object in memory
4
5
  class Content
6
+ include Util::SiteAccess
5
7
 
6
- MUNGABLE_RE= Regexp.new(%Q<(href|data|src)([\s]*)=([\s]*)('|"|&quot;|&#34;|&#39;)?\\/([\\/]?)>, 'i')
7
- LAYOUTLESS_EXTS= %w(.css .js .xml)
8
-
9
- attr_reader :full_path, :path, :params, :site
8
+ attr_reader :source_path, :params
10
9
 
11
- def initialize(path, site, params={})
12
- @site= site
13
- @params= HashObject.new params
14
- @full_path= path
10
+ def initialize(source_path, generator=nil, &block)
11
+ @source_path= source_path
12
+ @generator= generator
13
+ @ignore= false
14
+ @block= block
15
+ @params= Util::HashObject.new
15
16
  end
16
17
 
17
- def slug
18
- @slug ||= uri.gsub('/', '-').gsub(ext, '')
19
- end
18
+ # TODO: Use a Pathname for all path operations instead of File.*
19
+ # Add support for relative_to and relative_from to
20
+ # ContentList (find?)
20
21
 
21
- def ignored
22
- @ignored ||= false
23
- end
24
- def ignore(state=true)
25
- @ignored= state
22
+ def params=(value={})
23
+ @params.merge! value
26
24
  end
27
25
 
28
- def generated
29
- @generated ||= false
26
+ def slug
27
+ @slug ||= uri.gsub('/', '-').gsub(ext, '')
30
28
  end
31
29
 
32
30
  def path
33
- @path ||= get_source_path
31
+ @path ||= _source_path
34
32
  end
35
33
 
36
34
  def level
@@ -38,11 +36,11 @@ module Gumdrop
38
36
  end
39
37
 
40
38
  def source_filename
41
- @source_filename ||= File.basename @full_path
39
+ @source_filename ||= File.basename source_path
42
40
  end
43
41
 
44
42
  def filename
45
- @filename ||= get_target_filename
43
+ @filename ||= _target_filename
46
44
  end
47
45
 
48
46
  def type
@@ -54,92 +52,98 @@ module Gumdrop
54
52
  end
55
53
 
56
54
  def uri
57
- @uri ||= get_uri
55
+ @uri ||= _uri
58
56
  end
59
57
 
60
- def template
61
- @template ||= unless Tilt[@full_path].nil?
62
- Tilt.new @full_path
63
- else
64
- nil
58
+ def binary?
59
+ @is_binary ||= begin
60
+ if generated? or has_block? or missing?
61
+ false
62
+ else
63
+ # from ptools
64
+ s = (File.read(source_path, File.stat(source_path).blksize) || "").split(//)
65
+ ((s.size - s.grep(" ".."~").size) / s.size.to_f) > 0.30
66
+ end
65
67
  end
66
68
  end
67
- def template=(t)
68
- @template = t
69
+
70
+ # Can I call #body() ?
71
+ def exists?
72
+ has_block? or File.exists? @source_path
69
73
  end
70
-
71
- def render(context=nil, ignore_layout=false, reset_context=true, locals={})
72
- context= site.render_context if context.nil?
73
- if reset_context
74
- default_layout= LAYOUTLESS_EXTS.include?(ext) ? nil : 'site'
75
- context.reset_data 'current_depth'=>level, 'current_slug'=>slug, 'page'=>self, 'layout'=>default_layout, 'params'=>params
76
- end
77
- context.set_content self, locals
78
- content= render_all(context)
79
- return relativize content, context if ignore_layout
80
- begin
81
- layout= context.get_template()
82
- while !layout.nil? and !layout.template.nil?
83
- content = layout.template.render(context, content:content) { content }
84
- layout= context.get_template()
85
- end
86
- rescue => ex
87
- raise StandardError, "Layout: #{ex.to_s}", ex.backtrace
88
- end
89
- relativize content, context
90
- rescue => ex
91
- raise StandardError, "Rendering exception: #{ex.to_s}", ex.backtrace
74
+
75
+ def missing?
76
+ !exists?
92
77
  end
93
-
94
- def renderTo(context, output_path, filters=[], opts={})
95
- return copyTo(output_path, opts) unless useLayout?
96
- site.report " rendering: #{uri}"
97
- output= render(context)
98
- filters.each {|f| output= f.call(output, self) }
99
- File.open output_path, 'w' do |f|
100
- f.write output
101
- end
78
+
79
+ def generated?
80
+ !@generator.nil?
102
81
  end
103
-
104
- # This probably belongs to the BUILD, not here
105
- def copyTo(output, layout=nil, opts={})
106
- do_copy= if File.exists? output
107
- !FileUtils.identical? @full_path, output
108
- else
109
- true
110
- end
111
- if do_copy
112
- site.report " copying: #{uri}"
113
- FileUtils.cp_r @full_path, output, opts
114
- else
115
- site.report " (same): #{uri}"
116
- end
82
+
83
+ def has_block?
84
+ !@block.nil?
117
85
  end
118
-
119
- def mtime
120
- if File.exists? @full_path
121
- File.new(@full_path).mtime
122
- else
123
- Time.now
124
- end
86
+
87
+ def partial?
88
+ source_filename[0] == "_"
125
89
  end
126
-
127
- def useLayout?
128
- !template.nil?
90
+
91
+ def layout?
92
+ ext == '.layout'
129
93
  end
130
94
 
131
- def ignore?
132
- ignored
95
+ def generator?
96
+ ext == '.generator'
133
97
  end
134
-
98
+
99
+ def body # Memoize this?
100
+ @body ||= case
101
+ when has_block?
102
+ @block.call
103
+ when missing?, binary?
104
+ nil
105
+ else
106
+ File.read @source_path
107
+ end
108
+ end
109
+
110
+ def mtime
111
+ @mtime ||= if exists? and !generated?
112
+ File.new(@source_path).mtime
113
+ else
114
+ Time.now
115
+ end
116
+ end
117
+
135
118
  def to_s
136
119
  uri
137
120
  end
138
-
121
+
122
+ def method_missing(sym, *args, &block)
123
+ if params.has_key? sym
124
+ params[sym]
125
+ else
126
+ super
127
+ end
128
+ end
129
+
139
130
  private
140
131
 
141
- def get_source_path
142
- path= @full_path.sub site.src_path, ''
132
+ def _uri
133
+ # Do I need to do anything for windoze here to make sure
134
+ # the slashes are / and not \ ?
135
+ uri= File.dirname(path) / filename
136
+ if uri.starts_with? './'
137
+ uri[2..-1]
138
+ elsif uri.starts_with? '/'
139
+ uri[1..-1]
140
+ else
141
+ uri
142
+ end
143
+ end
144
+
145
+ def _source_path
146
+ path= @source_path.gsub site.source_path, ''
143
147
  if path[0] == '/'
144
148
  path[1..-1]
145
149
  else
@@ -147,61 +151,120 @@ module Gumdrop
147
151
  end
148
152
  end
149
153
 
150
- def get_target_filename
154
+ def _target_filename
151
155
  filename_parts= source_filename.split('.')
152
156
  ext= filename_parts.pop
153
- while !Tilt[ext].nil?
157
+ while !Renderer.for(ext).nil?
154
158
  ext= filename_parts.pop
155
159
  end
156
160
  filename_parts << ext # push the last file ext back on there!
157
- filename_parts.join('.')
158
- end
159
-
160
- def render_all(ctx)
161
- if generated or !File.exists?(@full_path)
162
- content= template.render(ctx)
161
+ fname= filename_parts.join('.')
162
+ if partial?
163
+ fname[1..-1]
163
164
  else
164
- content= File.read @full_path
165
- exts= source_filename.gsub filename, ''
166
- exts.split('.').reverse.each do |ext|
167
- unless ext.blank?
168
- templateClass= Tilt[".#{ext}"]
169
- template= templateClass.new(@full_path) do
170
- content
171
- end
172
- content= template.render(ctx)
173
- end
174
- end
165
+ fname
175
166
  end
167
+ end
168
+
169
+ def self.path_match?(path, pattern)
170
+ File.fnmatch pattern, path, File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_CASEFOLD
171
+ end
172
+ end
173
+
174
+ class ContentList < Hash
175
+
176
+ def create(path, generator=nil, &block)
177
+ content= Content.new path, generator, &block
178
+ add content #, path
179
+ end
180
+
181
+ def add(content, uri=nil)
182
+ uri= content.uri if uri.nil?
183
+ self[uri]= content
176
184
  content
177
185
  end
178
186
 
179
- def get_uri
180
- uri= File.join File.dirname(path), filename
181
- if uri.starts_with? './'
182
- uri[2..-1]
183
- else
184
- uri
185
- end
187
+ def remove(content)
188
+ uri = content.is_a? String ? content : content.uri
189
+ self.delete uri
186
190
  end
187
191
 
188
- def relativize(content, ctx)
189
- if site.config.relative_paths and !ctx.force_absolute
190
- if site.config.relative_paths_for == :all or site.config.relative_paths_for.include?(ext)
191
- path_to_root= ctx.path_to_root
192
- content.force_encoding("UTF-8") if content.respond_to? :force_encoding
193
- content = content.gsub MUNGABLE_RE do |match|
194
- if $5 == '/'
195
- "#{ $1 }#{ $2 }=#{ $3 }#{ $4 }/"
196
- else
197
- "#{ $1 }#{ $2 }=#{ $3 }#{ $4 }#{ path_to_root }"
198
- end
199
- end
192
+ # Returns Array of content objects
193
+ def all(pattern=nil)
194
+ pattern.nil? ? values : find(pattern)
195
+ end
196
+
197
+ # Scans the filenames (keys) and uses fnmatch to find maches
198
+ def find(pattern)
199
+ patterns= [pattern].flatten
200
+ contents=[]
201
+ self.each_pair do |path, content|
202
+ patterns.each do |pattern|
203
+ contents << content if Content.path_match? path, pattern
200
204
  end
201
205
  end
202
- content
206
+ contents
207
+ end
208
+
209
+ def get(key)
210
+ self[key]
211
+ end
212
+
213
+ def first(pattern)
214
+ find(pattern).first
203
215
  end
216
+
217
+ end
218
+
219
+ # Keeps a ref to content at full path and just the basename
220
+ class SpecialContentList < ContentList
204
221
 
222
+ def initialize(default_ext=false)#, *args)
223
+ @ext= default_ext || ".html" # ???
224
+ super()
225
+ end
226
+
227
+ def add(content, uri=nil)
228
+ uri= content.uri if uri.nil?
229
+ buri = File.basename uri
230
+ self[uri]= content
231
+ self[buri]= content
232
+ content
233
+ end
234
+
235
+ def remove(content)
236
+ uri = content.is_a? String ? content : content.uri
237
+ self.delete uri
238
+ self.delete File.basename uri
239
+ end
240
+
241
+ # Find isn't fuzzy for Special Content. It looks for full
242
+ # uri or the uri's basename, optionally tacking on @ext
243
+ def find(uri)
244
+ _try_variations_of(uri) do |path|
245
+ content= get path
246
+ return [content] unless content.nil?
247
+ end unless uri.nil?
248
+ []
249
+ end
250
+
251
+ private
252
+
253
+ def _try_variations_of(uri)
254
+ # try the uri
255
+ yield uri
256
+ # plus default ext
257
+ yield uri + @ext
258
+ urip= Pathname.new uri
259
+ # just the filename
260
+ yield urip.basename
261
+ # filename plus default extension
262
+ yield urip.basename + @ext
263
+ # filename minus the ext
264
+ yield urip.basename.to_s.gsub urip.extname, ''
265
+ # uri minus ext
266
+ yield uri.gsub urip.extname, ''
267
+ end
268
+
205
269
  end
206
-
207
270
  end