pith 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README.markdown +10 -3
  2. data/Rakefile +13 -3
  3. data/cucumber.yml +1 -6
  4. data/features/helpers.feature~ +23 -0
  5. data/features/ignorance.feature +12 -1
  6. data/features/ignorance.feature~ +12 -1
  7. data/features/incremental_rebuild.feature~ +24 -0
  8. data/features/layouts.feature +22 -2
  9. data/features/layouts.feature~ +20 -0
  10. data/features/metadata.feature +1 -1
  11. data/features/{linking.feature → relative_linking.feature} +32 -2
  12. data/features/relative_linking.feature~ +109 -0
  13. data/features/step_definitions/build_steps.rb +20 -16
  14. data/features/step_definitions/build_steps.rb~ +32 -11
  15. data/features/support/env.rb +6 -6
  16. data/features/support/env.rb~ +36 -4
  17. data/features/support/rspec_matchers.rb~ +5 -0
  18. data/lib/pith/input/abstract.rb +120 -0
  19. data/lib/pith/input/abstract.rb~ +120 -0
  20. data/lib/pith/input/template.rb +56 -0
  21. data/lib/pith/input/template.rb~ +46 -0
  22. data/lib/pith/input/verbatim.rb +31 -0
  23. data/lib/pith/input/verbatim.rb~ +31 -0
  24. data/lib/pith/input.rb +5 -176
  25. data/lib/pith/input.rb~ +10 -85
  26. data/lib/pith/project.rb +14 -7
  27. data/lib/pith/project.rb~ +36 -11
  28. data/lib/pith/render_context.rb +34 -13
  29. data/lib/pith/render_context.rb~ +54 -17
  30. data/lib/pith/server.rb +0 -1
  31. data/lib/pith/server.rb~ +13 -17
  32. data/lib/pith/version.rb +1 -1
  33. data/lib/pith/version.rb~ +1 -1
  34. data/lib/pith.rb~ +0 -1
  35. data/sample/_out/index.html +14 -0
  36. data/sample/_out/stylesheets/app.css +38 -0
  37. data/sample/index.html.haml +1 -2
  38. data/spec/pith/input/abstract_spec.rb +31 -0
  39. data/spec/pith/input/abstract_spec.rb~ +31 -0
  40. data/spec/pith/metadata_spec.rb +2 -2
  41. data/spec/pith/project_spec.rb +21 -8
  42. data/spec/pith/project_spec.rb~ +74 -0
  43. data/spec/spec_helper.rb~ +27 -0
  44. metadata +76 -6
data/README.markdown CHANGED
@@ -5,11 +5,13 @@ Pith is a static web-site generator, written in Ruby.
5
5
 
6
6
  Using Pith, you can:
7
7
 
8
- * __Express yourself succintly__ using [Haml][haml], [Sass][sass], ERb, Markdown and Textile.
8
+ * __Express yourself succintly__ using Markdown or Textile.
9
9
 
10
- * __Encapsulate common markup__ in "partial" templates.
10
+ * __Layout your pages__ written in ERb, [Haml][haml], or Liquid.
11
11
 
12
- * __Separate content and layout__ using "layout" templates.
12
+ * __Style things up using__ [Sass][sass].
13
+
14
+ * __Encapsulate common markup__ in "layout" and "partial" templates.
13
15
 
14
16
  * __Easily link pages and resources__ using relative links.
15
17
 
@@ -17,6 +19,11 @@ Using Pith, you can:
17
19
 
18
20
  * __Define custom helper-methods__ to increase expressiveness.
19
21
 
22
+ Why Pith?
23
+ ---------
24
+
25
+ Why another static web-site generator, when there are other good options out there? Pith's main differentiating factor is that structure of the output slavishly mirrors the structure of the input; there are no magic input directories for layouts, or dynamic content, or anything else.
26
+
20
27
  Install it
21
28
  ----------
22
29
 
data/Rakefile CHANGED
@@ -10,7 +10,17 @@ task :default => :cucumber
10
10
 
11
11
  require 'cucumber/rake/task'
12
12
 
13
- Cucumber::Rake::Task.new(:cucumber) do |t|
14
- t.fork = true
15
- t.profile = 'default'
13
+ namespace :cucumber do
14
+
15
+ [:wip, :default].each do |profile|
16
+
17
+ Cucumber::Rake::Task.new(profile) do |t|
18
+ t.fork = true
19
+ t.profile = profile
20
+ end
21
+
22
+ end
23
+
16
24
  end
25
+
26
+ task :cucumber => ["cucumber:wip", "cucumber:default"]
data/cucumber.yml CHANGED
@@ -1,7 +1,2 @@
1
- <%
2
- rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
- rerun_opts = rerun.to_s.strip.empty? ? "--format progress features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4
- std_opts = "#{rerun_opts} --format rerun --out rerun.txt --strict --tags ~@wip --require features/support --require features/step_definitions"
5
- %>
6
- default: <%= std_opts %>
1
+ default: --tags ~@wip features
7
2
  wip: --tags @wip:3 --wip features
@@ -0,0 +1,23 @@
1
+ Feature: helper methods
2
+
3
+ I want to extend Pith with helper methods
4
+ So that I can use them in templates
5
+
6
+ Scenario: call a helper from a template
7
+
8
+ Given input file "_pith/config.rb" contains
9
+ """
10
+ project.helpers do
11
+
12
+ def greet(subject = "mate")
13
+ "Hello, #{subject}"
14
+ end
15
+
16
+ end
17
+ """
18
+
19
+ And input file "index.html.haml" contains "= greet('World')"
20
+
21
+ When I build the site
22
+
23
+ Then output file "index.html" should contain "Hello, World"
@@ -14,7 +14,7 @@ Scenario: a layout template at the input root
14
14
 
15
15
  Then output file "_layout" should not exist
16
16
 
17
- Scenario: a partial in a subdirectory
17
+ Scenario: a partial in an ignored subdirectory
18
18
 
19
19
  Given input file "_partials/foo.html.haml" contains
20
20
  """
@@ -24,3 +24,14 @@ Scenario: a partial in a subdirectory
24
24
  When I build the site
25
25
 
26
26
  Then output file "_partials/foo.html" should not exist
27
+
28
+ Scenario: an ignored partial in a subdirectory
29
+
30
+ Given input file "partials/_foo.html.haml" contains
31
+ """
32
+ Blah de blah
33
+ """
34
+
35
+ When I build the site
36
+
37
+ Then output file "partials/_foo.html" should not exist
@@ -14,7 +14,7 @@ Scenario: a layout template at the input root
14
14
 
15
15
  Then output file "_layout" should not exist
16
16
 
17
- Scenario: a partial in a subdirectory
17
+ Scenario: a partial in an ignored subdirectory
18
18
 
19
19
  Given input file "_partials/foo.html.haml" contains
20
20
  """
@@ -24,3 +24,14 @@ Scenario: a partial in a subdirectory
24
24
  When I build the site
25
25
 
26
26
  Then output file "_partials/foo.html" should not exist
27
+
28
+ Scenario: an ignored partial in a subdirectory
29
+
30
+ Given input file "partials/_foo.html.haml" contains
31
+ """
32
+ Blah de blah
33
+ """
34
+
35
+ When I build the site
36
+
37
+ Then output file "partials/_foo.html" should not exist
@@ -0,0 +1,24 @@
1
+ Feature: incremental rebuilding
2
+
3
+ I want to rebuild just the outputs whose inputs have changed
4
+ So that that I can bring the project up-to-date efficiently
5
+
6
+ Scenario: alter an input, and the output changes
7
+
8
+ Given input file "page.html.haml" contains "Old content"
9
+ And the site is up-to-date
10
+
11
+ When I change input file "page.html.haml" to contain "New content"
12
+ And I rebuild the site
13
+
14
+ Then output file "page.html" should be re-generated
15
+ And output file "page.html" should contain "New content"
16
+
17
+ Scenario: don't alter an input, and the output is untouched
18
+
19
+ Given input file "page.html.haml" contains "Content"
20
+ And the site is up-to-date
21
+
22
+ When I rebuild the site
23
+
24
+ Then output file "page.html" should not be re-generated
@@ -7,7 +7,7 @@ Scenario: Haml template with a layout
7
7
 
8
8
  Given input file "index.html.haml" contains
9
9
  """
10
- = include "layouts/_simple.haml" do
10
+ = inside "layouts/_simple.haml" do
11
11
  blah blah
12
12
  """
13
13
  And input file "layouts/_simple.haml" contains
@@ -25,7 +25,7 @@ Scenario: instance variable assigned within the layed-out block
25
25
 
26
26
  Given input file "index.html.haml" contains
27
27
  """
28
- = include "layouts/_with_header.haml" do
28
+ = inside "layouts/_with_header.haml" do
29
29
  - @title = "XXX"
30
30
  %p blah blah
31
31
  """
@@ -41,3 +41,23 @@ Scenario: instance variable assigned within the layed-out block
41
41
  <h1>XXX</h1>
42
42
  <p>blah blah</p>
43
43
  """
44
+
45
+ Scenario: Layout specified in meta-data
46
+
47
+ Given input file "index.html.haml" contains
48
+ """
49
+ -# ---
50
+ -# layout: layouts/_simple.haml
51
+ -#...
52
+ blah blah
53
+ """
54
+ And input file "layouts/_simple.haml" contains
55
+ """
56
+ %p= yield
57
+ """
58
+
59
+ When I build the site
60
+ Then output file "index.html" should contain
61
+ """
62
+ <p>blah blah</p>
63
+ """
@@ -41,3 +41,23 @@ Scenario: instance variable assigned within the layed-out block
41
41
  <h1>XXX</h1>
42
42
  <p>blah blah</p>
43
43
  """
44
+
45
+ Scenario: Layout specified in meta-data
46
+
47
+ Given input file "index.html.haml" contains
48
+ """
49
+ -# ---
50
+ -# layout: layouts/_simple.haml
51
+ -#...
52
+ blah blah
53
+ """
54
+ And input file "layouts/_simple.haml" contains
55
+ """
56
+ %p= yield
57
+ """
58
+
59
+ When I build the site
60
+ Then output file "index.html" should contain
61
+ """
62
+ <p>blah blah</p>
63
+ """
@@ -3,7 +3,7 @@ Feature: metadata
3
3
  I want extract metadata from page source
4
4
  So that I can use it elsewhere
5
5
 
6
- Scenario: link from one top-level page to another
6
+ Scenario: use meta-data from YAML comment
7
7
 
8
8
  Given input file "page.html.haml" contains
9
9
  """
@@ -1,6 +1,7 @@
1
1
  Feature: linking between files
2
2
 
3
- I want to be able to link pages easily
3
+ I want to be able to generate relative reference to other pages
4
+ So that the generated site is re-locateable
4
5
 
5
6
  Scenario: link from one top-level page to another
6
7
 
@@ -8,7 +9,8 @@ Scenario: link from one top-level page to another
8
9
  """
9
10
  = link("page.html", "Page")
10
11
  """
11
-
12
+ And input file "page.html" exists
13
+
12
14
  When I build the site
13
15
  Then output file "index.html" should contain
14
16
  """
@@ -21,6 +23,7 @@ Scenario: link from a sub-directory to a root-level page
21
23
  """
22
24
  = link("/help.html", "Help")
23
25
  """
26
+ And input file "help.html" exists
24
27
 
25
28
  When I build the site
26
29
  Then output file "subdir/page.html" should contain
@@ -34,6 +37,7 @@ Scenario: link to an image
34
37
  """
35
38
  %img{:src => href("/logo.png")}
36
39
  """
40
+ And input file "logo.png" exists
37
41
 
38
42
  When I build the site
39
43
  Then output file "subdir/page.html" should contain
@@ -54,6 +58,8 @@ Scenario: links within a layout block
54
58
  = yield
55
59
  """
56
60
 
61
+ And input file "subdir/other.html" exists
62
+
57
63
  When I build the site
58
64
  Then output file "subdir/page.html" should contain
59
65
  """
@@ -72,8 +78,32 @@ Scenario: links included from a partial
72
78
  %link{ :href=>href("/stylesheets/app.css"), :rel=>"stylesheet", :type=>"text/css" }
73
79
  """
74
80
 
81
+ And input file "stylesheets/app.css" exists
82
+
75
83
  When I build the site
76
84
  Then output file "subdir/page.html" should contain
77
85
  """
78
86
  <link href='../stylesheets/app.css' rel='stylesheet' type='text/css' />
79
87
  """
88
+
89
+ Scenario: use "title" meta-data attribute in link
90
+
91
+ Given input file "index.html.haml" contains
92
+ """
93
+ = link("page.html")
94
+ """
95
+
96
+ And input file "page.html.haml" contains
97
+ """
98
+ -# ---
99
+ -# title: "Title from meta-data"
100
+ -# ...
101
+ Target content
102
+ """
103
+
104
+ When I build the site
105
+
106
+ Then output file "index.html" should contain
107
+ """
108
+ <a href="page.html">Title from meta-data</a>
109
+ """
@@ -0,0 +1,109 @@
1
+ Feature: linking between files
2
+
3
+ I want to be able to generate relative reference to other pages
4
+ So that the generated site is re-locateable
5
+
6
+ Scenario: link from one top-level page to another
7
+
8
+ Given input file "index.html.haml" contains
9
+ """
10
+ = link("page.html", "Page")
11
+ """
12
+ And input file "page.html" exists
13
+
14
+ When I build the site
15
+ Then output file "index.html" should contain
16
+ """
17
+ <a href="page.html">Page</a>
18
+ """
19
+
20
+ Scenario: link from a sub-directory to a root-level page
21
+
22
+ Given input file "subdir/page.html.haml" contains
23
+ """
24
+ = link("/help.html", "Help")
25
+ """
26
+ And input file "help.html" exists
27
+
28
+ When I build the site
29
+ Then output file "subdir/page.html" should contain
30
+ """
31
+ <a href="../help.html">Help</a>
32
+ """
33
+
34
+ Scenario: link to an image
35
+
36
+ Given input file "subdir/page.html.haml" contains
37
+ """
38
+ %img{:src => href("/logo.png")}
39
+ """
40
+ And input file "logo.png" exists
41
+
42
+ When I build the site
43
+ Then output file "subdir/page.html" should contain
44
+ """
45
+ <img src='../logo.png' />
46
+ """
47
+
48
+ Scenario: links within a layout block
49
+
50
+ Given input file "subdir/page.html.haml" contains
51
+ """
52
+ = include "/common/_layout.haml" do
53
+ = link "other.html", "Other page"
54
+ """
55
+
56
+ And input file "common/_layout.haml" contains
57
+ """
58
+ = yield
59
+ """
60
+
61
+ And input file "subdir/other.html" exists
62
+
63
+ When I build the site
64
+ Then output file "subdir/page.html" should contain
65
+ """
66
+ <a href="other.html">Other page</a>
67
+ """
68
+
69
+ Scenario: links included from a partial
70
+
71
+ Given input file "subdir/page.html.haml" contains
72
+ """
73
+ = include "/common/_partial.haml"
74
+ """
75
+
76
+ And input file "common/_partial.haml" contains
77
+ """
78
+ %link{ :href=>href("/stylesheets/app.css"), :rel=>"stylesheet", :type=>"text/css" }
79
+ """
80
+
81
+ And input file "stylesheets/app.css" exists
82
+
83
+ When I build the site
84
+ Then output file "subdir/page.html" should contain
85
+ """
86
+ <link href='../stylesheets/app.css' rel='stylesheet' type='text/css' />
87
+ """
88
+
89
+ Scenario: use "title" meta-data attribute in link
90
+
91
+ Given input file "index.html.haml" contains
92
+ """
93
+ = link("page.html")
94
+ """
95
+
96
+ And input file "page.html.haml" contains
97
+ """
98
+ -# ---
99
+ -# title: "Title from meta-data"
100
+ -# ...
101
+ Target content
102
+ """
103
+
104
+ When I build the site
105
+
106
+ Then output file "index.html" should contain
107
+ """
108
+ <a href="page.html">Title from meta-data</a>
109
+ """
@@ -1,17 +1,21 @@
1
- Given /^input file "([^\"]*)" contains "([^\"]*)"$/ do |file_name, content|
2
- @inputs.write(file_name, content, :mtime => (Time.now - 5))
1
+ Given /^input file "([^\"]*)" contains "([^\"]*)"$/ do |path, content|
2
+ @inputs.write(path, content, :mtime => (Time.now - 5))
3
3
  end
4
4
 
5
- Given /^input file "([^\"]*)" contains$/ do |file_name, content|
6
- @inputs.write(file_name, content, :mtime => (Time.now - 5))
5
+ Given /^input file "([^\"]*)" contains$/ do |path, content|
6
+ @inputs.write(path, content, :mtime => (Time.now - 5))
7
+ end
8
+
9
+ Given /^input file "([^\"]*)" exists$/ do |path|
10
+ Given %{input file "#{path}" contains "something"}
7
11
  end
8
12
 
9
13
  Given "the site is up-to-date" do
10
14
  When "I build the site"
11
15
  end
12
16
 
13
- When /^I change input file "([^\"]*)" to contain "([^\"]*)"$/ do |file_name, content|
14
- @inputs[file_name] = content
17
+ When /^I change input file "([^\"]*)" to contain "([^\"]*)"$/ do |path, content|
18
+ @inputs[path] = content
15
19
  end
16
20
 
17
21
  When /^I (?:re)?build the site$/ do
@@ -25,22 +29,22 @@ class String
25
29
  end
26
30
  end
27
31
 
28
- Then /^output file "([^\"]*)" should contain "([^\"]*)"$/ do |file_name, content|
29
- @outputs[file_name].clean.should == content.clean
32
+ Then /^output file "([^\"]*)" should contain "([^\"]*)"$/ do |path, content|
33
+ @outputs[path].clean.should == content.clean
30
34
  end
31
35
 
32
- Then /^output file "([^\"]*)" should contain$/ do |file_name, content|
33
- @outputs[file_name].clean.should == content.clean
36
+ Then /^output file "([^\"]*)" should contain$/ do |path, content|
37
+ @outputs[path].clean.should == content.clean
34
38
  end
35
39
 
36
- Then /^output file "([^\"]*)" should not exist$/ do |file_name|
37
- @outputs[file_name].should == nil
40
+ Then /^output file "([^\"]*)" should not exist$/ do |path|
41
+ @outputs[path].should == nil
38
42
  end
39
43
 
40
- Then /^output file "([^"]*)" should be re\-generated$/ do |file_name|
41
- @project.logger.messages.should contain(/--> +#{file_name}/)
44
+ Then /^output file "([^"]*)" should be re\-generated$/ do |path|
45
+ @project.logger.messages.should contain(/--> +#{path}/)
42
46
  end
43
47
 
44
- Then /^output file "([^"]*)" should not be re\-generated$/ do |file_name|
45
- @project.logger.messages.should_not contain(/--> +#{file_name}/)
48
+ Then /^output file "([^"]*)" should not be re\-generated$/ do |path|
49
+ @project.logger.messages.should_not contain(/--> +#{path}/)
46
50
  end
@@ -1,12 +1,25 @@
1
- Given /^input file "([^\"]*)" contains "([^\"]*)"$/ do |file_name, content|
2
- @inputs[file_name] = content
1
+ Given /^input file "([^\"]*)" contains "([^\"]*)"$/ do |path, content|
2
+ @inputs.write(path, content, :mtime => (Time.now - 5))
3
3
  end
4
4
 
5
- Given /^input file "([^\"]*)" contains$/ do |file_name, content|
6
- @inputs[file_name] = content
5
+ Given /^input file "([^\"]*)" contains$/ do |path, content|
6
+ @inputs.write(path, content, :mtime => (Time.now - 5))
7
7
  end
8
8
 
9
- When /^I build the site$/ do
9
+ Given /^input file "([^\"]*)" exists$/ do |path|
10
+ Given %{input file "#{path}" contains "something"}
11
+ end
12
+
13
+ Given "the site is up-to-date" do
14
+ When "I build the site"
15
+ end
16
+
17
+ When /^I change input file "([^\"]*)" to contain "([^\"]*)"$/ do |path, content|
18
+ @inputs[path] = content
19
+ end
20
+
21
+ When /^I (?:re)?build the site$/ do
22
+ @project.logger.clear
10
23
  @project.build
11
24
  end
12
25
 
@@ -16,14 +29,22 @@ class String
16
29
  end
17
30
  end
18
31
 
19
- Then /^output file "([^\"]*)" should contain "([^\"]*)"$/ do |file_name, content|
20
- @outputs[file_name].clean.should == content.clean
32
+ Then /^output file "([^\"]*)" should contain "([^\"]*)"$/ do |path, content|
33
+ @outputs[path].clean.should == content.clean
34
+ end
35
+
36
+ Then /^output file "([^\"]*)" should contain$/ do |path, content|
37
+ @outputs[path].clean.should == content.clean
38
+ end
39
+
40
+ Then /^output file "([^\"]*)" should not exist$/ do |path|
41
+ @outputs[path].should == nil
21
42
  end
22
43
 
23
- Then /^output file "([^\"]*)" should contain$/ do |file_name, content|
24
- @outputs[file_name].clean.should == content.clean
44
+ Then /^output file "([^"]*)" should be re\-generated$/ do |path|
45
+ @project.logger.messages.should contain(/--> +#{path}/)
25
46
  end
26
47
 
27
- Then /^output file "([^\"]*)" should not exist$/ do |file_name|
28
- @outputs[file_name].should == nil
48
+ Then /^output file "([^"]*)" should not be re\-generated$/ do |path|
49
+ @project.logger.messages.should_not contain(/--> +#{path}/)
29
50
  end
@@ -6,17 +6,17 @@ class DirHash
6
6
  @dir = Pathname(dir)
7
7
  end
8
8
 
9
- def [](file_name)
10
- file_path = @dir + file_name
9
+ def [](file)
10
+ file_path = @dir + file
11
11
  file_path.read if file_path.exist?
12
12
  end
13
13
 
14
- def []=(file_name, content)
15
- write(file_name, content)
14
+ def []=(file, content)
15
+ write(file, content)
16
16
  end
17
17
 
18
- def write(file_name, content, options = {})
19
- file_path = @dir + file_name
18
+ def write(file, content, options = {})
19
+ file_path = @dir + file
20
20
  file_path.parent.mkpath
21
21
  file_path.open("w") do |io|
22
22
  io << content
@@ -6,19 +6,50 @@ class DirHash
6
6
  @dir = Pathname(dir)
7
7
  end
8
8
 
9
- def [](file_name)
10
- file_path = @dir + file_name
9
+ def [](file)
10
+ file_path = @dir + file
11
11
  file_path.read if file_path.exist?
12
12
  end
13
13
 
14
- def []=(file_name, content)
15
- file_path = @dir + file_name
14
+ def []=(file, content)
15
+ write(file, content)
16
+ end
17
+
18
+ def write(file, content, options = {})
19
+ file_path = @dir + file
16
20
  file_path.parent.mkpath
17
21
  file_path.open("w") do |io|
18
22
  io << content
19
23
  end
24
+ if options[:mtime]
25
+ timestamp = options[:mtime]
26
+ file_path.utime(timestamp, timestamp)
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ class InternalLogger
33
+
34
+ def initialize
35
+ @messages = []
36
+ end
37
+
38
+ attr_reader :messages
39
+
40
+ def clear
41
+ @messages.clear
20
42
  end
21
43
 
44
+ def info(message, &block)
45
+ message ||= block.call
46
+ write(message)
47
+ end
48
+
49
+ def write(message)
50
+ @messages << message
51
+ end
52
+
22
53
  end
23
54
 
24
55
  $project_dir = Pathname(__FILE__).expand_path.parent.parent.parent
@@ -38,6 +69,7 @@ Before do
38
69
  dir.mkpath
39
70
  end
40
71
  @project = Pith::Project.new(:input_dir => $input_dir, :output_dir => $output_dir)
72
+ @project.logger = InternalLogger.new
41
73
  @inputs = DirHash.new($input_dir)
42
74
  @outputs = DirHash.new($output_dir)
43
75
  end
@@ -0,0 +1,5 @@
1
+ Spec::Matchers.define :contain do |expected|
2
+ match do |actual|
3
+ actual.any? { |x| expected === x }
4
+ end
5
+ end