hydeweb 0.0.8.pre2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. data/{CHANGELOG → HISTORY.md} +6 -0
  2. data/Rakefile +2 -52
  3. data/bin/hyde +3 -23
  4. data/bin/hyde01 +7 -0
  5. data/data/new_site/README.md +1 -1
  6. data/data/new_site/hyde.conf +9 -6
  7. data/lib/hyde/cli/helpers.rb +40 -0
  8. data/lib/hyde/cli.rb +86 -0
  9. data/lib/hyde/config.rb +37 -0
  10. data/lib/hyde/helpers.rb +6 -47
  11. data/lib/hyde/layout.rb +17 -9
  12. data/lib/hyde/meta.rb +5 -21
  13. data/lib/hyde/page.rb +207 -159
  14. data/lib/hyde/partial.rb +10 -5
  15. data/lib/hyde/project.rb +58 -208
  16. data/lib/hyde/server.rb +57 -0
  17. data/lib/hyde.rb +28 -51
  18. data/test/fixture/extensions/extensions/a/a.rb +1 -0
  19. data/test/fixture/extensions/hyde.conf +8 -0
  20. data/test/fixture/extensions/site/index.haml +1 -0
  21. data/test/fixture/fail_type/control/about/index.html +2 -0
  22. data/test/fixture/fail_type/control/about/us.html +2 -0
  23. data/test/fixture/fail_type/control/index.html +1 -0
  24. data/test/fixture/fail_type/hyde.conf +8 -0
  25. data/test/fixture/fail_type/site/index.haml +4 -0
  26. data/test/fixture/nested_layout/control/index.html +2 -0
  27. data/test/fixture/nested_layout/hyde.conf +8 -0
  28. data/test/fixture/nested_layout/layouts/default.haml +2 -0
  29. data/test/{fixtures/content_for/site/default.html.haml → fixture/nested_layout/layouts/post.haml} +1 -0
  30. data/test/fixture/nested_layout/site/index.haml +4 -0
  31. data/test/fixture/one/control/about/index.css +2 -0
  32. data/test/fixture/one/control/cheers.html +5 -0
  33. data/test/fixture/one/control/css/style.css +2 -0
  34. data/test/fixture/one/control/hello.html +5 -0
  35. data/test/fixture/one/control/hi.html +1 -0
  36. data/test/fixture/one/control/index.html +7 -0
  37. data/test/fixture/one/hyde.conf +9 -0
  38. data/test/fixture/one/layouts/default.haml +4 -0
  39. data/test/fixture/one/partials/menu.haml +3 -0
  40. data/test/fixture/one/site/about/index.scss +1 -0
  41. data/test/fixture/one/site/cheers.html.haml +1 -0
  42. data/test/fixture/one/site/css/style.scss +2 -0
  43. data/test/fixture/one/site/hello.haml +1 -0
  44. data/test/fixture/one/site/hi.html +1 -0
  45. data/test/fixture/one/site/index.haml +7 -0
  46. data/test/fixture/parent/control/about/index.html +2 -0
  47. data/test/fixture/parent/control/about/us.html +2 -0
  48. data/test/fixture/parent/control/index.html +1 -0
  49. data/test/fixture/parent/hyde.conf +8 -0
  50. data/test/fixture/parent/site/about/index.haml +3 -0
  51. data/test/fixture/parent/site/about/us.haml +3 -0
  52. data/test/fixture/parent/site/index.haml +3 -0
  53. data/test/fixture/sort/hyde.conf +8 -0
  54. data/test/fixture/sort/site/about/hardy.haml +4 -0
  55. data/test/fixture/sort/site/about/intrepid.haml +4 -0
  56. data/test/fixture/sort/site/about.haml +3 -0
  57. data/test/fixture/subclass/control/index.html +1 -0
  58. data/test/fixture/subclass/extensions/a/a.rb +12 -0
  59. data/test/fixture/subclass/hyde.conf +8 -0
  60. data/test/fixture/subclass/layouts/default.haml +1 -0
  61. data/test/fixture/subclass/layouts/post.haml +1 -0
  62. data/test/fixture/subclass/site/index.haml +4 -0
  63. data/test/helper.rb +15 -21
  64. data/test/unit/extensions_test.rb +16 -0
  65. data/test/unit/fixture_test.rb +77 -0
  66. data/test/unit/hyde_test.rb +30 -0
  67. metadata +107 -153
  68. data/.yardopts +0 -5
  69. data/LICENSE +0 -20
  70. data/VERSION +0 -1
  71. data/data/new_site/.gitignore +0 -24
  72. data/data/pages/404.html +0 -3
  73. data/hydeweb.gemspec +0 -159
  74. data/lib/hyde/clicommand.rb +0 -60
  75. data/lib/hyde/clicommands.rb +0 -128
  76. data/lib/hyde/ostruct.rb +0 -13
  77. data/lib/hyde/page_factory.rb +0 -90
  78. data/lib/hyde/renderer.rb +0 -133
  79. data/lib/hyde/renderers.rb +0 -100
  80. data/lib/hyde/sinatra/init.rb +0 -64
  81. data/lib/hyde/utils.rb +0 -43
  82. data/lib/hyde_misc/console.rb +0 -4
  83. data/manual/Extending/ExtendingHyde.md +0 -118
  84. data/manual/Hyde.md +0 -63
  85. data/manual/Introduction/Configuration.md +0 -70
  86. data/manual/Introduction/GettingStarted.md +0 -64
  87. data/manual/Introduction/Installation.md +0 -16
  88. data/manual/Introduction/Layouts.md +0 -14
  89. data/manual/Introduction/Metadata.md +0 -94
  90. data/manual/Introduction/Partials.md +0 -73
  91. data/manual/Introduction/TemplateLanguages.md +0 -59
  92. data/manual/Tips/Tips.md +0 -42
  93. data/test/fixtures/content_for/_config.yml +0 -8
  94. data/test/fixtures/content_for/layouts/cf-args.haml +0 -2
  95. data/test/fixtures/content_for/layouts/cf.haml +0 -14
  96. data/test/fixtures/content_for/layouts/default.haml +0 -4
  97. data/test/fixtures/content_for/layouts/shared/test.haml +0 -4
  98. data/test/fixtures/content_for/site/cf-args-default.haml +0 -2
  99. data/test/fixtures/content_for/site/cf-args.haml +0 -5
  100. data/test/fixtures/content_for/site/cf.haml +0 -6
  101. data/test/fixtures/content_for/site/cf2.haml +0 -3
  102. data/test/fixtures/content_for/site/index.html.haml +0 -9
  103. data/test/fixtures/content_for/site/var.html.haml +0 -5
  104. data/test/fixtures/content_for/www_control/cf-args-default.html +0 -1
  105. data/test/fixtures/content_for/www_control/cf-args.html +0 -2
  106. data/test/fixtures/content_for/www_control/cf.html +0 -17
  107. data/test/fixtures/content_for/www_control/cf2.html +0 -19
  108. data/test/fixtures/content_for/www_control/default.html +0 -2
  109. data/test/fixtures/content_for/www_control/index.html +0 -10
  110. data/test/fixtures/content_for/www_control/var.html +0 -2
  111. data/test/fixtures/custom/_config.yml +0 -8
  112. data/test/fixtures/custom/extensions/custom/custom.rb +0 -9
  113. data/test/fixtures/custom/layouts/default.haml +0 -8
  114. data/test/fixtures/custom/layouts/erbtest.erb +0 -2
  115. data/test/fixtures/custom/layouts/shared/sidebar.haml +0 -4
  116. data/test/fixtures/custom/site/about/index.html +0 -1
  117. data/test/fixtures/custom/site/assets/common.css.less +0 -1
  118. data/test/fixtures/custom/site/assets/style.css.less +0 -3
  119. data/test/fixtures/custom/site/foo.html.haml +0 -3
  120. data/test/fixtures/custom/site/index.html.haml +0 -6
  121. data/test/fixtures/custom/site/layout_test.html.haml +0 -6
  122. data/test/fixtures/custom/site/lol.html.erb +0 -7
  123. data/test/fixtures/custom/site/markdown.html.md +0 -8
  124. data/test/fixtures/custom/site/yes.html +0 -2
  125. data/test/fixtures/custom/www_control/about/index.html +0 -1
  126. data/test/fixtures/custom/www_control/assets/common.css +0 -1
  127. data/test/fixtures/custom/www_control/assets/style.css +0 -6
  128. data/test/fixtures/custom/www_control/foo.html +0 -1
  129. data/test/fixtures/custom/www_control/index.html +0 -16
  130. data/test/fixtures/custom/www_control/layout_test.html +0 -16
  131. data/test/fixtures/custom/www_control/lol.html +0 -5
  132. data/test/fixtures/custom/www_control/markdown.html +0 -17
  133. data/test/fixtures/custom/www_control/yes.html +0 -2
  134. data/test/fixtures/default/_config.yml +0 -8
  135. data/test/fixtures/default/extensions/custom/custom.rb +0 -2
  136. data/test/fixtures/default/layouts/default.haml +0 -5
  137. data/test/fixtures/default/site/about/index.html +0 -1
  138. data/test/fixtures/default/site/foo.html.haml +0 -3
  139. data/test/fixtures/default/site/index.html.haml +0 -6
  140. data/test/fixtures/default/site/layout_test.html.haml +0 -6
  141. data/test/fixtures/default/site/yes.html +0 -2
  142. data/test/fixtures/default/www_control/about/index.html +0 -1
  143. data/test/fixtures/default/www_control/foo.html +0 -1
  144. data/test/fixtures/default/www_control/index.html +0 -9
  145. data/test/fixtures/default/www_control/layout_test.html +0 -9
  146. data/test/fixtures/default/www_control/yes.html +0 -2
  147. data/test/test_all_fixtures.rb +0 -51
  148. data/test/test_build.rb +0 -20
  149. data/test/test_hyde.rb +0 -75
  150. data/test/test_page.rb +0 -26
  151. data/test/test_utils.rb +0 -22
data/lib/hyde/page.rb CHANGED
@@ -1,209 +1,257 @@
1
- module Hyde
2
- class Page
3
- include Hyde::Utils
1
+ class Hyde
2
+ class Page
3
+ attr_reader :project
4
+ attr_reader :file
5
+
6
+ # Returns the URL path for a page.
7
+ def path
8
+ path = @file.sub(root_path, '')
9
+
10
+ # if xx.haml (but not xx.html.haml),
11
+ if tilt?
12
+ path = path.sub(/\.[^\.]*$/, "")
13
+ path += ".#{default_ext}" unless File.basename(path).include?('.')
14
+ end
4
15
 
5
- attr :renderer
16
+ path
17
+ end
6
18
 
7
- # The filename of the source file.
8
- #
9
- # @example
10
- # puts page.name
11
- # puts page.filename
12
- #
13
- # # about/index.html
14
- # # about/index.html.haml
15
- #
16
- attr_accessor :filename
19
+ def title
20
+ (meta.title if tilt?) || path
21
+ end
17
22
 
18
- # Metadata hash
19
- attr_accessor :meta
23
+ alias to_s title
20
24
 
21
- # Path
22
- # @see {#filename} for an example
23
- attr_accessor :name
25
+ def <=>(other)
26
+ result = self.position <=> other.position
27
+ result ||= self.position.to_s <=> other.position.to_s
28
+ result
29
+ end
24
30
 
25
- # A reference to the parent {Project} instance
26
- attr_reader :project
31
+ def html?
32
+ mime_type == 'text/html'
33
+ end
27
34
 
28
- attr_accessor :referrer
35
+ def mime_type
36
+ return nil unless tilt?
29
37
 
30
- DEFAULT_LAYOUT = 'default'
38
+ mime = nil
39
+ mime = tilt_engine.default_mime_type if tilt_engine.respond_to?(:default_mime_type)
31
40
 
32
- # Factory
33
- #
34
- def self.[](path, project, def_page_class = Page)
35
- PageFactory.create path, project, def_page_class
41
+ mime ||= case tilt_engine.name
42
+ when 'Tilt::SassTemplate' then 'text/css'
43
+ when 'Tilt::ScssTemplate' then 'text/css'
44
+ when 'Tilt::LessTemplate' then 'text/css'
45
+ when 'Tilt::CoffeeScriptTemplate' then 'application/javascript'
46
+ when 'Tilt::NokogiriTemplate' then 'text/xml'
47
+ when 'Tilt::BuilderTemplate' then 'text/xml'
48
+ else 'text/html'
36
49
  end
50
+ end
37
51
 
38
- # Returns the rendered output.
39
- def render(data = {}, &block)
40
- output = content(data, &block)
41
- output = layout.render(get_data(data)) { output } unless layout.nil?
42
- output
52
+ def default_ext
53
+ case mime_type
54
+ when 'text/html' then 'html'
55
+ when 'text/css' then 'css'
56
+ when 'text/xml' then 'xml'
57
+ when 'application/javascript' then 'js'
43
58
  end
59
+ end
44
60
 
45
- # Returns the HTML content.
46
- def content(data = {}, &block)
47
- @renderer.render(get_data(data), &block)
48
- end
61
+ def self.[](id, project=$project)
62
+ site = lambda { |*x| File.join root_path(project), *(x.compact) }
63
+ try = lambda { |id| p = new(id, project); p if p.exists? }
49
64
 
50
- def layout=(val)
51
- @layout = val
65
+ # Account for:
66
+ # ~/mysite/site/about/us.html.haml
67
+ # about/us.html.haml => ~/mysite/site/about/us.html.haml
68
+ # about/us.html => ~/mysite/site/about/us.html.*
69
+ # about/us.html => ~/mysite/site/about/us.*
70
+ # about/us => ~/mysite/site/about/us/index.*
71
+ #
72
+ page = try[id]
73
+ page ||= try[site[id]]
74
+ page ||= try[Dir[site["#{id}.*"]].first]
75
+ page ||= try[Dir[site["#{id.to_s.sub(/\.[^\.]*/,'')}.*"]].first]
76
+ page ||= try[Dir[site[id, "index.*"]].first]
77
+
78
+ # Subclass
79
+ if page && page.tilt? && page.meta.type
80
+ klass = Page.get_type(page.meta.type)
81
+ raise Error, "Class for type '#{page.meta.type}' not found" unless klass
82
+ page = klass.new(id, project)
52
83
  end
84
+ page
85
+ end
53
86
 
54
- def layout
55
- begin
56
- @layout ||= project[DEFAULT_LAYOUT, :Layout] if !@renderer.nil? and @renderer.layoutable? and meta.layout != false
57
- @layout
58
- rescue NotFound
59
- nil
60
- end
61
- end
87
+ # Returns a page subtype.
88
+ # @example Page.get_type('post') => Hyde::Page::Post
89
+ def self.get_type(type)
90
+ klass = type[0].upcase + type[1..-1].downcase
91
+ klass = klass.to_sym
92
+ self.const_get(klass) if self.const_defined?(klass)
93
+ end
62
94
 
63
- def title
64
- @title ||= if meta.title
65
- meta.title
66
- elsif is_index?
67
- File.basename(File.dirname(filename))
68
- else
69
- File.basename(filename, '.*')
70
- end
71
- end
95
+ def initialize(file, project=$project)
96
+ @file = file
97
+ @project = project
98
+ raise Error if project.nil?
99
+ end
72
100
 
73
- # Returns the URL path for the page.
74
- def path
75
- @url ||= begin
76
- if renderer.is_a?(Renderer::Passthru)
77
- '/' + @name
78
- else
79
- url = [ File.dirname(@name), File.basename(@filename) ]
80
- url[1] = File.basename(url[1], '.*')
81
- url[1] = (url[1] + @renderer.default_ext) unless url[1].include?('.')
82
- '/' + url.join('/')
83
- end
84
- end
85
- end
101
+ def exists?
102
+ @file and File.file?(@file) and valid?
103
+ end
86
104
 
87
- def output_path
88
- File.join(project.config.output_path, path)
89
- end
105
+ # Make sure that it's in the right folder.
106
+ def valid?
107
+ prefix = File.expand_path(root_path)
108
+ prefix == File.expand_path(@file)[0...prefix.size]
109
+ end
90
110
 
91
- def get_binding #(&blk)
92
- binding
93
- end
111
+ def content(locals={}, &blk)
112
+ return markup unless tilt?
113
+ # Build scope
114
+ scope = self.dup
115
+ scope.extend Helpers
116
+ scope.meta.merge! locals
94
117
 
95
- def to_s
96
- name
97
- end
118
+ tilt.render(scope, &blk)
119
+ end
98
120
 
99
- def to_sym
100
- (filename).to_sym
101
- end
121
+ def to_html(locals={}, &blk)
122
+ html = content(locals, &blk)
123
+ html = layout.to_html(locals) { html } if layout?
124
+ html
125
+ end
102
126
 
103
- def <=>(other)
104
- result = self.position <=> other.position
105
- result ||= self.position.to_s <=> other.position.to_s
106
- result
107
- end
127
+ def layout
128
+ layout = meta.layout
129
+ layout ||= default_layout unless meta.layout == false
130
+ Layout[layout, page] if layout
131
+ end
108
132
 
109
- def position
110
- meta.position || title
111
- end
133
+ def page
134
+ self
135
+ end
112
136
 
113
- def parent
114
- folder = File.dirname(@name)
115
- folder = File.join(folder, '..') if is_index?
116
- folder = File.expand_path(folder)
137
+ def layout?
138
+ !! layout
139
+ end
117
140
 
118
- files = Dir[File.join(folder, 'index.*')]
119
- return nil if files.empty?
141
+ def meta
142
+ @meta ||= Meta.new(YAML::load(parts.first))
143
+ end
120
144
 
121
- page = PageFactory.create(files.first, @project)
122
- return nil if page === self
145
+ # Writes to the given output file.
146
+ def write(out=nil)
147
+ out ||= project.path(:output, path)
148
+ FileUtils.mkdir_p File.dirname(out)
123
149
 
124
- page
150
+ if tilt?
151
+ File.open(out, 'w') { |f| f.write to_html }
152
+ else
153
+ FileUtils.cp file, out
125
154
  end
155
+ end
126
156
 
127
- def children
128
- return [] unless is_index?
129
- folder = File.dirname(@name)
157
+ # Checks if the file is supported by tilt.
158
+ def tilt?
159
+ !! tilt_engine
160
+ end
130
161
 
131
- get_pages_from folder
132
- end
162
+ # Returns the Tilt engine (eg Tilt::HamlEngine).
163
+ def tilt_engine
164
+ Tilt[@file]
165
+ end
133
166
 
134
- def siblings
135
- folder = File.dirname(@name)
136
- folder = File.join(folder, '..') if is_index?
167
+ def tilt_engine_name
168
+ tilt_engine.name.match(/:([^:]*)(?:Template?)$/)[1]
169
+ end
137
170
 
138
- get_pages_from folder
171
+ # Returns the tilt layout.
172
+ def tilt
173
+ if tilt?
174
+ begin
175
+ # HAML options and such (like :escape_html)
176
+ options = project.config.tilt_options_for(@file)
177
+ offset = parts.first.count("\n") + 2
178
+ @tilt ||= Tilt.new(@file, offset, options) { markup }
179
+ rescue LoadError => e
180
+ gem = e.message.split(' ').last
181
+ ext = File.extname(@file)
182
+ raise NoGemError, "You need the '#{gem}' gem to parse #{ext} files."
183
+ end
139
184
  end
185
+ end
140
186
 
141
- def get_pages_from(folder)
142
- # Sanity check: don't go beyond the root
143
- return [] unless File.expand_path(folder).include?(File.expand_path(@project.root(:site)))
187
+ def markup
188
+ parts.last
189
+ end
144
190
 
145
- files = Dir[@project.root(:site, folder, '*')]
146
- files.inject([]) do |a, name|
147
- if File.directory?(name)
148
- name = Dir[File.join(name, 'index.*')].first
149
- a << PageFactory.create(name, @project) unless name.nil?
191
+ def method_missing(meth, *args, &blk)
192
+ super unless meta.instance_variable_get(:@table).keys.include?(meth.to_sym)
193
+ meta.send(meth)
194
+ end
150
195
 
151
- else
152
- page = PageFactory.create name, @project
153
- a << page unless page.is_index?
196
+ def parent
197
+ parts = path.split('/')
198
+ parent_path = index? ? parts[0...-2] : parts[0...-1]
199
+ self.class[parent_path.join('/'), project]
200
+ end
154
201
 
155
- end
156
- a
157
- end.sort
202
+ def children
203
+ files = if index?
204
+ # about/index.html => about/*
205
+ File.expand_path('../*', @file)
206
+ else
207
+ # products.html => products/*
208
+ base = File.basename(@file, '.*')
209
+ File.expand_path("../#{base}/*", @file)
158
210
  end
159
211
 
160
- # Returns an array of the page's ancestors, starting from the root page.
161
- def breadcrumbs
162
- @crumbs ||= parent.nil? ? [] : (parent.breadcrumbs + [parent])
163
- end
212
+ Dir[files].reject { |f| f == @file }.map { |f| self.class[f, project] }.compact.sort
213
+ end
164
214
 
165
- def ===(other)
166
- return false if other.nil?
167
- super || (File.expand_path(self.filename) === File.expand_path(other.filename))
168
- end
215
+ def siblings
216
+ p = parent and p.children
217
+ end
169
218
 
170
- def next
171
- siblings.each_cons(2) { |(i, other)| return other if i === self }
172
- end
219
+ def breadcrumbs
220
+ parent? ? (parent.breadcrumbs + [self]) : [self]
221
+ end
222
+
223
+ def index?
224
+ File.basename(path, '.*') == 'index'
225
+ end
173
226
 
174
- def previous
175
- siblings.each_cons(2) { |(other, i)| return other if i === self }
176
- end
227
+ def parent?
228
+ !parent.nil?
229
+ end
177
230
 
178
- def is_index?
179
- !@name.match(/(^|\/)index/).nil?
180
- end
231
+ def root?
232
+ parent.nil?
233
+ end
181
234
 
182
- protected
235
+ protected
236
+ def default_layout
237
+ 'default' if html?
238
+ end
183
239
 
184
- # Constructor.
185
- # The `page` argument is a page name
186
- # Don't use me: use {Project#[]}
187
- #
188
- def initialize(path, project, renderer, filename)
189
- @project = project
190
- @name ||= path
191
- @meta ||= Meta.new self
192
- @filename = filename
193
- @renderer = renderer.new(self, filename)
194
- end
195
-
196
- def self.get_filename(path, project)
197
- project.root(:site, path)
240
+ # Returns the two parts of the markup.
241
+ def parts
242
+ @parts ||= begin
243
+ t = File.open(@file).read.force_encoding('UTF-8')
244
+ m = t.match(/^(.*)--+\n(.*)$/m)
245
+ m.nil? ? ['', t] : [m[1], m[2]]
198
246
  end
247
+ end
199
248
 
200
- private
249
+ def self.root_path(project, *a)
250
+ project.path(:site, *a)
251
+ end
201
252
 
202
- # Data for rendering
203
- def get_data(data)
204
- data = @meta | data
205
- data[:page] ||= self
206
- data
207
- end
253
+ def root_path(*a)
254
+ self.class.root_path(project, *a)
208
255
  end
209
256
  end
257
+ end
data/lib/hyde/partial.rb CHANGED
@@ -1,7 +1,12 @@
1
- module Hyde
2
- class Partial < Layout
3
- def self.get_filename(path, project)
4
- project.root(:partials, path)
5
- end
1
+ class Hyde
2
+ class Partial < Layout
3
+ protected
4
+ def self.root_path(project, *a)
5
+ project.path(:partials, *a)
6
6
  end
7
+
8
+ def default_layout
9
+ nil
10
+ end
11
+ end
7
12
  end