ruhoh 2.5 → 2.6

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 (72) hide show
  1. data/Gemfile +1 -1
  2. data/bin/ruhoh +10 -3
  3. data/features/_root.feature +11 -0
  4. data/features/data.feature +78 -0
  5. data/features/javascripts.feature +36 -0
  6. data/features/permalinks.feature +23 -0
  7. data/features/plugins.feature +84 -0
  8. data/features/sort_order.feature +121 -0
  9. data/features/step_defs.rb +3 -3
  10. data/features/support/helpers.rb +3 -5
  11. data/history.json +21 -0
  12. data/lib/ruhoh.rb +28 -123
  13. data/lib/ruhoh/base/collectable.rb +273 -0
  14. data/lib/ruhoh/base/compilable.rb +30 -0
  15. data/lib/ruhoh/base/compilable_asset.rb +30 -0
  16. data/lib/ruhoh/base/model_viewable.rb +30 -0
  17. data/lib/ruhoh/base/modelable.rb +44 -0
  18. data/lib/ruhoh/base/page_like.rb +111 -0
  19. data/lib/ruhoh/base/page_viewable.rb +92 -0
  20. data/lib/ruhoh/base/routable.rb +20 -0
  21. data/lib/ruhoh/base/watchable.rb +18 -0
  22. data/lib/ruhoh/cascade.rb +93 -0
  23. data/lib/ruhoh/client.rb +1 -3
  24. data/lib/ruhoh/collections.rb +2 -1
  25. data/lib/ruhoh/config.rb +67 -0
  26. data/lib/ruhoh/console_methods.rb +0 -2
  27. data/lib/ruhoh/parse.rb +7 -5
  28. data/lib/ruhoh/plugins/initializer.rb +24 -0
  29. data/lib/ruhoh/plugins/local_plugins_plugin.rb +10 -0
  30. data/lib/ruhoh/plugins/plugin.rb +27 -0
  31. data/lib/ruhoh/programs/compile.rb +2 -6
  32. data/lib/ruhoh/programs/preview.rb +5 -2
  33. data/lib/ruhoh/programs/watch.rb +4 -6
  34. data/lib/ruhoh/publish/rsync.rb +2 -2
  35. data/lib/ruhoh/resources/_base/collection.rb +6 -0
  36. data/lib/ruhoh/resources/_base/compiler.rb +3 -0
  37. data/lib/ruhoh/resources/_base/model.rb +3 -0
  38. data/lib/ruhoh/resources/_base/model_view.rb +3 -0
  39. data/lib/ruhoh/resources/_base/watcher.rb +4 -0
  40. data/lib/ruhoh/resources/data/collection.rb +30 -9
  41. data/lib/ruhoh/resources/javascripts/collection_view.rb +5 -1
  42. data/lib/ruhoh/resources/javascripts/model_view.rb +15 -0
  43. data/lib/ruhoh/resources/layouts/client.rb +1 -1
  44. data/lib/ruhoh/resources/pages/client.rb +2 -2
  45. data/lib/ruhoh/resources/pages/collection.rb +2 -21
  46. data/lib/ruhoh/resources/theme/compiler.rb +2 -2
  47. data/lib/ruhoh/resources/widgets/collection.rb +2 -2
  48. data/lib/ruhoh/routes.rb +1 -1
  49. data/lib/ruhoh/summarizer.rb +2 -2
  50. data/lib/ruhoh/ui/dashboard.rb +13 -0
  51. data/lib/ruhoh/ui/page_not_found.rb +3 -2
  52. data/lib/ruhoh/url_slug.rb +23 -9
  53. data/lib/ruhoh/version.rb +1 -1
  54. data/lib/ruhoh/views/master_view.rb +1 -1
  55. data/spec/lib/ruhoh/plugins/initializer_spec.rb +43 -0
  56. data/spec/lib/ruhoh/plugins/plugin_spec.rb +40 -0
  57. data/spec/spec_helper.rb +1 -0
  58. data/system/config.json +21 -0
  59. data/system/{dash/index.html → dashboard.html} +1 -1
  60. data/{lib/ruhoh/ui → system}/page_not_found.html +0 -0
  61. data/system/plugins/sprockets/compiler.rb +1 -0
  62. data/system/widgets/comments/disqus.html +1 -1
  63. metadata +34 -15
  64. data/lib/ruhoh/base/collection.rb +0 -284
  65. data/lib/ruhoh/base/compiler.rb +0 -67
  66. data/lib/ruhoh/base/model.rb +0 -161
  67. data/lib/ruhoh/base/model_view.rb +0 -129
  68. data/lib/ruhoh/base/watcher.rb +0 -25
  69. data/lib/ruhoh/resources/dash/collection.rb +0 -10
  70. data/lib/ruhoh/resources/dash/model.rb +0 -5
  71. data/lib/ruhoh/resources/dash/model_view.rb +0 -5
  72. data/lib/ruhoh/resources/dash/previewer.rb +0 -13
data/Gemfile CHANGED
@@ -13,5 +13,5 @@ end
13
13
  group :test do
14
14
  gem 'cucumber'
15
15
  gem 'capybara'
16
- gem "rspec-expectations"
16
+ gem 'rspec'
17
17
  end
data/bin/ruhoh CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
4
 
5
+ # Set up gems listed in the Gemfile.
6
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
7
+ if File.exists?(ENV['BUNDLE_GEMFILE'])
8
+ require 'bundler/setup'
9
+ Bundler.require :default
10
+ end
11
+
5
12
  require 'ruhoh'
6
13
  require 'ruhoh/version'
7
14
  require 'ruhoh/client'
@@ -13,7 +20,7 @@ options = Options.new
13
20
 
14
21
  opt_parser = OptionParser.new do |opts|
15
22
  opts.banner = 'Use `ruhoh help` for full command list.'
16
-
23
+
17
24
  opts.on("--hg", "Use mercurial (hg) instead of git for source control.") do
18
25
  options.hg = true
19
26
  end
@@ -21,13 +28,13 @@ opt_parser = OptionParser.new do |opts|
21
28
  opts.on("-v", "--[no-]verbose", "Run verbosely. For pages, shows extra title, url meta-data.") do |v|
22
29
  options.verbose = v
23
30
  end
24
-
31
+
25
32
  opts.on("--version", "Display current gem and ruhoh specification versions.") do
26
33
  puts "ruhoh " + Ruhoh::VERSION
27
34
  puts "RuhohSpec " + Ruhoh::RuhohSpec
28
35
  exit 0
29
36
  end
30
-
37
+
31
38
  end
32
39
  opt_parser.parse!
33
40
 
@@ -0,0 +1,11 @@
1
+ Feature: _root collection
2
+ As a content publisher
3
+ I want to include pages at my domain's root
4
+ so I can organize my content.
5
+
6
+ Scenario: Adding a page to _root folder
7
+ Given some files with values:
8
+ | file |
9
+ | _root/index.html |
10
+ When I compile my site
11
+ Then my compiled site should have the file "index.html"
@@ -61,3 +61,81 @@ Feature: Data
61
61
  And this file should contain the content node "city|alhambra"
62
62
  And this file should contain the content node "li|mango"
63
63
  And this file should contain the content node "li|kiwi"
64
+
65
+
66
+ Scenario: Defining a basic data structure in data.json and merging with a theme data.json
67
+ Given a config file with values:
68
+ | theme-test | { "use" : "theme" } |
69
+ And the file "data.json" with body:
70
+ """
71
+ {
72
+ "address": {
73
+ "city": "alhambra"
74
+ },
75
+ "name": "jade",
76
+ "fruits": [
77
+ "mango",
78
+ "kiwi"
79
+ ]
80
+ }
81
+ """
82
+ And the file "theme-test/data.json" with body:
83
+ """
84
+ {
85
+ "address": {
86
+ "city": "Berkeley"
87
+ },
88
+ "greeting": "Hai!"
89
+ }
90
+ """
91
+ And the file "_root/index.html" with body:
92
+ """
93
+ <name>{{ data.name }}</name>
94
+ <city>{{ data.address.city }}</city>
95
+ <greeting>{{ data.greeting }}</greeting>
96
+ <ul>
97
+ {{# data.fruits }}
98
+ <li>{{ . }}</li>
99
+ {{/ data.fruits }}
100
+ </ul>
101
+ """
102
+ When I compile my site
103
+ Then my compiled site should have the file "index.html"
104
+ And this file should contain the content node "name|jade"
105
+ And this file should contain the content node "city|Berkeley"
106
+ And this file should contain the content node "li|mango"
107
+ And this file should contain the content node "li|kiwi"
108
+ And this file should contain the content node "greeting|Hai!"
109
+
110
+ Scenario: Defining a basic data structure in custom data collection
111
+ Given a config file with values:
112
+ | meta | { "use" : "data" } |
113
+ Given the file "meta/data.json" with body:
114
+ """
115
+ {
116
+ "address": {
117
+ "city": "alhambra"
118
+ },
119
+ "name": "jade",
120
+ "fruits": [
121
+ "mango",
122
+ "kiwi"
123
+ ]
124
+ }
125
+ """
126
+ And the file "_root/index.html" with body:
127
+ """
128
+ <name>{{ meta.data.name }}</name>
129
+ <city>{{ meta.data.address.city }}</city>
130
+ <ul>
131
+ {{# meta.data.fruits }}
132
+ <li>{{ . }}</li>
133
+ {{/ meta.data.fruits }}
134
+ </ul>
135
+ """
136
+ When I compile my site
137
+ Then my compiled site should have the file "index.html"
138
+ And this file should contain the content node "name|jade"
139
+ And this file should contain the content node "city|alhambra"
140
+ And this file should contain the content node "li|mango"
141
+ And this file should contain the content node "li|kiwi"
@@ -40,3 +40,39 @@ Feature: Javascripts
40
40
  When I compile my site
41
41
  Then my compiled site should have the file "index.html"
42
42
  And this file should have the fingerprinted javascripts "base, app, custom"
43
+
44
+ Scenario: Using javascript objects to resolve url
45
+ Given some files with values:
46
+ | file | body |
47
+ | javascripts/base.js | var meep; |
48
+ | javascripts/app.js | console.log('haro world') |
49
+ | javascripts/custom.js | console.log('haro world') |
50
+ And the file "_root/index.html" with body:
51
+ """
52
+ ---
53
+ custom: base.js
54
+ ---
55
+ {{# page.custom?to_javascripts }}
56
+ <script type="text/javascript" src="{{url}}"></script>
57
+ {{/ page.custom?to_javascripts }}
58
+ """
59
+ When I compile my site
60
+ Then my compiled site should have the file "index.html"
61
+ And this file should have the fingerprinted javascripts "base"
62
+
63
+ Scenario: Using javascript object to resolve url and id
64
+ Given some files with values:
65
+ | file | body |
66
+ | javascripts/base.js | var meep; |
67
+ | javascripts/app.js | console.log('haro world') |
68
+ | javascripts/custom.js | console.log('haro world') |
69
+ And the file "_root/index.html" with body:
70
+ """
71
+ {{# javascripts.all }}
72
+ <script type="text/javascript" id="{{id}}" src="{{url}}"></script>
73
+ {{/ javascripts.all }}
74
+ """
75
+ When I compile my site
76
+ Then my compiled site should have the file "index.html"
77
+ And this file should have the fingerprinted javascripts "app, base, custom"
78
+
@@ -10,6 +10,13 @@ Feature: Page Permalinks
10
10
  When I compile my site
11
11
  Then my compiled site should have the file "essays/hello/index.html"
12
12
 
13
+ Scenario: Default Permalink format with nested file
14
+ Given some files with values:
15
+ | file | body |
16
+ | essays/one/two/hello.md | |
17
+ When I compile my site
18
+ Then my compiled site should have the file "essays/one/two/hello/index.html"
19
+
13
20
  # in-page configuration
14
21
 
15
22
  Scenario: Custom permalink format in page metadata.
@@ -54,6 +61,13 @@ Feature: Page Permalinks
54
61
  When I compile my site
55
62
  Then my compiled site should have the file "essays/2012/1/2/hello/index.html"
56
63
 
64
+ Scenario: Custom permalink format in page metadata using custom metadata attributes.
65
+ Given some files with values:
66
+ | file | permalink | title | arbitrary_name | body |
67
+ | essays/hello.md | /:path/:title/:arbitrary_name | Haro World | custom data | |
68
+ When I compile my site
69
+ Then my compiled site should have the file "essays/haro-world/custom-data/index.html"
70
+
57
71
  Scenario: Custom permalink format in page metadata using explicit html extension
58
72
  Given some files with values:
59
73
  | file | permalink |
@@ -139,3 +153,12 @@ Feature: Page Permalinks
139
153
  | essays/hello.md | 2012-01-02 | |
140
154
  When I compile my site
141
155
  Then my compiled site should have the file "essays/2012/1/2/hello/index.html"
156
+
157
+ Scenario: Custom permalink format in collection config using custom metadata
158
+ Given a config file with values:
159
+ | essays | { "permalink" : "/legacy/:custom_id/:rank" } |
160
+ And some files with values:
161
+ | file | custom_id | rank | body |
162
+ | essays/hello.md | 12345 | medium | |
163
+ When I compile my site
164
+ Then my compiled site should have the file "legacy/12345/medium/index.html"
@@ -0,0 +1,84 @@
1
+ Feature: Plugins
2
+ As a content publisher
3
+ I want to include custom plugins
4
+ so I have the freedom and power to customize my website and workflow.
5
+
6
+ Scenario: Loading a pages collection plugin from the plugins folder.
7
+ Given the file "plugins/pages_test.rb" with body:
8
+ """
9
+ module PagesTest
10
+ def test_plugin_method
11
+ "Hi this is output from the test plugin"
12
+ end
13
+ end
14
+ Ruhoh::Resources::Pages::CollectionView.send(:include, PagesTest)
15
+ """
16
+ And the file "_root/index.html" with body:
17
+ """
18
+ <output>{{ _root.test_plugin_method }}</output>
19
+ """
20
+ When I compile my site
21
+ Then my compiled site should have the file "index.html"
22
+ And this file should contain the content node "output|Hi this is output from the test plugin"
23
+
24
+ Scenario: Loading a pages model plugin from the plugins folder.
25
+ Given some files with values:
26
+ | file | date | body |
27
+ | _root/index.html | 2013-12-01 | <date>{{ page.friendly_date }}</date> |
28
+ Given the file "plugins/paged_model_view_addons.rb" with body:
29
+ """
30
+ module PagesModelViewAddons
31
+ def friendly_date
32
+ date.strftime("%B %d, %Y")
33
+ end
34
+ end
35
+ Ruhoh.model('pages').send(:include, PagesModelViewAddons)
36
+ """
37
+ When I compile my site
38
+ Then my compiled site should have the file "index.html"
39
+ And this file should contain the content node "date|December 01, 2013"
40
+
41
+ Scenario: Loading a custom converter from the plugins folder.
42
+ Given some files with values:
43
+ | file | body |
44
+ | _root/index.strip | <output>the quick brown fox jumps over the lazy dog</output> |
45
+ Given the file "plugins/strip_converter.rb" with body:
46
+ """
47
+ class Ruhoh
48
+ module Converter
49
+ module Strip
50
+ def self.extensions
51
+ ['.strip']
52
+ end
53
+ def self.convert(content)
54
+ content.gsub(/\s/, '')
55
+ end
56
+ end
57
+ end
58
+ end
59
+ """
60
+ When I compile my site
61
+ Then my compiled site should have the file "index.html"
62
+ And this file should contain the content node "output|thequickbrownfoxjumpsoverthelazydog"
63
+
64
+ Scenario: Loading a custom compiler from the plugins folder.
65
+ Given the file "plugins/test_compiler.rb" with body:
66
+ """
67
+ class Ruhoh
68
+ module Compiler
69
+ class Test
70
+ def initialize(ruhoh)
71
+ @ruhoh = ruhoh
72
+ end
73
+ def run
74
+ File.open(@ruhoh.compiled_path("test-file.txt"), 'w:UTF-8') do |p|
75
+ p.puts "Domo's World ^_^"
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ """
82
+ When I compile my site
83
+ Then my compiled site should have the file "test-file.txt"
84
+ And this file should contain the content "Domo's World ^_^"
@@ -0,0 +1,121 @@
1
+ Feature: Page Sort Order
2
+ As a content publisher
3
+ I want to sort pages by a custom criteria
4
+ so my content makes intuitive sense to my audience.
5
+
6
+ Scenario: Default sort order - alpha title ascending
7
+ Given some files with values:
8
+ | file | body |
9
+ | essays/hello.md | |
10
+ | essays/zebra.md | |
11
+ | essays/apple.md | |
12
+ And the file "_root/index.md" with body:
13
+ """
14
+ <essays>
15
+ {{# essays.all }}{{ title }}-{{/ essays.all }}
16
+ </essays>
17
+ """
18
+ When I compile my site
19
+ Then my compiled site should have the file "index.html"
20
+ And this file should contain the content node "essays|Apple-Hello-Zebra-"
21
+
22
+ Scenario: Sort order alpha title descending
23
+ Given a config file with value:
24
+ """
25
+ { "essays" : {"sort" : ["title", "desc"]} }
26
+ """
27
+ And some files with values:
28
+ | file |
29
+ | essays/hello.md |
30
+ | essays/zebra.md |
31
+ | essays/apple.md |
32
+ And the file "_root/index.md" with body:
33
+ """
34
+ <essays>
35
+ {{# essays.all }}{{ title }}-{{/ essays.all }}
36
+ </essays>
37
+ """
38
+ When I compile my site
39
+ Then my compiled site should have the file "index.html"
40
+ And this file should contain the content node "essays|Zebra-Hello-Apple-"
41
+
42
+
43
+ Scenario: Sort order date descending
44
+ Given a config file with value:
45
+ """
46
+ { "essays" : { "sort" : ["date", "desc"] } }
47
+ """
48
+ And some files with values:
49
+ | file | date |
50
+ | essays/hello.md | 2013-12-01 |
51
+ | essays/zebra.md | 2013-12-10 |
52
+ | essays/apple.md | 2013-12-25 |
53
+ And the file "_root/index.md" with body:
54
+ """
55
+ <essays>
56
+ {{# essays.all }}{{ title }}-{{/ essays.all }}
57
+ </essays>
58
+ """
59
+ When I compile my site
60
+ Then my compiled site should have the file "index.html"
61
+ And this file should contain the content node "essays|Apple-Zebra-Hello-"
62
+
63
+ Scenario: Sort order date ascending
64
+ Given a config file with value:
65
+ """
66
+ { "essays" : { "sort" : ["date", "asc"] } }
67
+ """
68
+ And some files with values:
69
+ | file | date |
70
+ | essays/hello.md | 2013-12-01 |
71
+ | essays/zebra.md | 2013-12-10 |
72
+ | essays/apple.md | 2013-12-25 |
73
+ And the file "_root/index.md" with body:
74
+ """
75
+ <essays>
76
+ {{# essays.all }}{{ title }}-{{/ essays.all }}
77
+ </essays>
78
+ """
79
+ When I compile my site
80
+ Then my compiled site should have the file "index.html"
81
+ And this file should contain the content node "essays|Hello-Zebra-Apple-"
82
+
83
+ Scenario: Sort order numerically coerced custom-attribute
84
+ Given a config file with value:
85
+ """
86
+ { "essays" : { "sort" : ["position", "asc"] } }
87
+ """
88
+ And some files with values:
89
+ | file | position |
90
+ | essays/hello.md | 2 |
91
+ | essays/zebra.md | 1 |
92
+ | essays/apple.md | 3 |
93
+ And the file "_root/index.md" with body:
94
+ """
95
+ <essays>
96
+ {{# essays.all }}{{ title }}-{{/ essays.all }}
97
+ </essays>
98
+ """
99
+ When I compile my site
100
+ Then my compiled site should have the file "index.html"
101
+ And this file should contain the content node "essays|Zebra-Hello-Apple-"
102
+
103
+ Scenario: Sort order alpha coerced custom-attribute
104
+ Given a config file with value:
105
+ """
106
+ { "essays" : { "sort" : ["position", "asc"] } }
107
+ """
108
+ And some files with values:
109
+ | file | position |
110
+ | essays/hello.md | c |
111
+ | essays/zebra.md | b |
112
+ | essays/apple.md | a |
113
+ And the file "_root/index.md" with body:
114
+ """
115
+ <essays>
116
+ {{# essays.all }}{{ title }}-{{/ essays.all }}
117
+ </essays>
118
+ """
119
+ When I compile my site
120
+ Then my compiled site should have the file "index.html"
121
+ And this file should contain the content node "essays|Apple-Zebra-Hello-"
@@ -52,7 +52,7 @@ end
52
52
 
53
53
  Then(/^my compiled site (should|should NOT) have the file "(.*?)"$/) do |matcher, path|
54
54
  @filepath = path
55
- FileUtils.cd(@ruhoh.paths.compiled) {
55
+ FileUtils.cd(@ruhoh.config['compiled_path']) {
56
56
  # Done this way so the error output is more informative.
57
57
  files = Dir.glob("**/*").delete_if{ |a| File.directory?(a) }
58
58
  files.__send__(matcher, include(path))
@@ -61,7 +61,7 @@ end
61
61
 
62
62
  Then(/^my compiled site (should|should NOT) have the (?:directory|folder) "(.*?)"$/) do |matcher, path|
63
63
  @filepath = path
64
- FileUtils.cd(@ruhoh.paths.compiled) {
64
+ FileUtils.cd(@ruhoh.config['compiled_path']) {
65
65
  # Done this way so the error output is more informative.
66
66
  files = Dir.glob("**/*").delete_if{ |a| File.file?(a) }
67
67
  files.__send__(matcher, include(path))
@@ -90,7 +90,7 @@ end
90
90
  Then(/^this file (should|should NOT) have the fingerprinted (stylesheets|javascripts) "(.*)"$/) do |matcher, filetype, names|
91
91
  names = names.split(/[\s,]+/).map(&:strip)
92
92
  files = nil
93
- FileUtils.cd(File.join(@ruhoh.paths.compiled, 'assets', filetype)){
93
+ FileUtils.cd(File.join(@ruhoh.config['compiled_path'], 'assets', filetype)){
94
94
  files = Dir['*']
95
95
  }
96
96