laze 0.2.0

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 (65) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +150 -0
  5. data/Rakefile +76 -0
  6. data/VERSION.yml +5 -0
  7. data/bin/laze +126 -0
  8. data/examples/website/includes/tagline.html +1 -0
  9. data/examples/website/input/contact/email.md +6 -0
  10. data/examples/website/input/css/screen.css +5 -0
  11. data/examples/website/input/css/test.less +6 -0
  12. data/examples/website/input/img/ruby.gif +0 -0
  13. data/examples/website/input/img/test.jpg +0 -0
  14. data/examples/website/input/img/test.png +0 -0
  15. data/examples/website/input/index.md +13 -0
  16. data/examples/website/input/js/foo.js +1 -0
  17. data/examples/website/input/js/lib.js +5 -0
  18. data/examples/website/layouts/default.html +15 -0
  19. data/examples/website/layouts/subpage.html +5 -0
  20. data/examples/website/laze.yml +1 -0
  21. data/features/create_sites.feature +73 -0
  22. data/features/plugins.feature +49 -0
  23. data/features/site_data.feature +26 -0
  24. data/features/step_definitions/laze_steps.rb +77 -0
  25. data/features/support/env.rb +17 -0
  26. data/lib/laze.rb +64 -0
  27. data/lib/laze/asset.rb +7 -0
  28. data/lib/laze/core_extensions.rb +15 -0
  29. data/lib/laze/item.rb +59 -0
  30. data/lib/laze/javascript.rb +5 -0
  31. data/lib/laze/layout.rb +105 -0
  32. data/lib/laze/page.rb +33 -0
  33. data/lib/laze/plugins.rb +56 -0
  34. data/lib/laze/plugins/cache_buster.rb +49 -0
  35. data/lib/laze/plugins/css_imports.rb +42 -0
  36. data/lib/laze/plugins/cssmin.rb +31 -0
  37. data/lib/laze/plugins/image_check.rb +28 -0
  38. data/lib/laze/plugins/image_optimizer.rb +52 -0
  39. data/lib/laze/plugins/js_requires.rb +63 -0
  40. data/lib/laze/plugins/jsmin.rb +31 -0
  41. data/lib/laze/plugins/less.rb +35 -0
  42. data/lib/laze/plugins/robots.rb +28 -0
  43. data/lib/laze/plugins/sitemap.rb +63 -0
  44. data/lib/laze/renderer.rb +47 -0
  45. data/lib/laze/renderers/javascript_renderer.rb +16 -0
  46. data/lib/laze/renderers/page_renderer.rb +40 -0
  47. data/lib/laze/renderers/stylesheet_renderer.rb +16 -0
  48. data/lib/laze/secretary.rb +74 -0
  49. data/lib/laze/section.rb +39 -0
  50. data/lib/laze/store.rb +51 -0
  51. data/lib/laze/stores/filesystem.rb +127 -0
  52. data/lib/laze/stylesheet.rb +6 -0
  53. data/lib/laze/target.rb +56 -0
  54. data/lib/laze/targets/filesystem.rb +41 -0
  55. data/test/helper.rb +12 -0
  56. data/test/test_assets.rb +28 -0
  57. data/test/test_core_extensions.rb +19 -0
  58. data/test/test_item.rb +59 -0
  59. data/test/test_layout.rb +47 -0
  60. data/test/test_renderer.rb +71 -0
  61. data/test/test_renderers.rb +40 -0
  62. data/test/test_secretary.rb +48 -0
  63. data/test/test_store.rb +18 -0
  64. data/test/test_target.rb +84 -0
  65. metadata +207 -0
@@ -0,0 +1,13 @@
1
+ title: welcome
2
+ layout: default
3
+ ---
4
+ Welcome to our awesome websites!
5
+ {% include 'tagline' %}
6
+
7
+ ## Lorem ipsum dolor sit amet...
8
+
9
+ ...Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
10
+
11
+ ### The title of this page is {{ page.title }}
12
+
13
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et **dolore magna aliqua**. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
@@ -0,0 +1 @@
1
+ var hello = 'Welcome to this awesome page.';
@@ -0,0 +1,5 @@
1
+ var hello = 'Welcome to this page.';
2
+ // requires 'foo.js'
3
+ window.onload = function init() {
4
+ alert(hello);
5
+ };
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>{{ page.title }} &ndash; Laze demo</title>
5
+ <link rel="stylesheet" href="css/screen.css" media="screen" charset="utf-8">
6
+ <script src="js/lib.js"></script>
7
+ </head>
8
+ <body>
9
+ <h1>Laze demonstration website</h1>
10
+ <hr>
11
+ {{ yield }}
12
+ <hr>
13
+ <p>Generated with Laze, the static site generator</p>
14
+ </body>
15
+ </html>
@@ -0,0 +1,5 @@
1
+ layout: default
2
+ ---
3
+ <p><a href="../index.html">Back to the homepage</a></p>
4
+
5
+ {{ yield }}
@@ -0,0 +1 @@
1
+ domain: http://example.com
@@ -0,0 +1,73 @@
1
+ Feature: Create sites
2
+ As a web developer
3
+ I want to be able to make a static website
4
+ In order to earn a living
5
+
6
+ Scenario: Basic site
7
+ Given I have an 'input/index.html' file that contains 'basic site'
8
+ When I run laze
9
+ Then the output directory should exist
10
+ And I should see 'basic site' in 'output/index.html'
11
+
12
+ Scenario: Site with directories
13
+ Given I have an 'input/contact/index.html' file that contains 'contact!'
14
+ When I run laze
15
+ Then the output directory should exist
16
+ And I should see 'contact!' in 'output/contact/index.html'
17
+
18
+ Scenario: Basic site with a layout
19
+ Given I have a layouts directory
20
+ And I have an 'input/index.html' page with layout 'default' that contains 'page with layout'
21
+ And I have a 'default' layout that contains 'Layout: {{ yield }}'
22
+ When I run laze
23
+ Then the output directory should exist
24
+ And I should see 'Layout: <p>page with layout</p>' in 'output/index.html'
25
+
26
+ Scenario: Basic site with nested layouts
27
+ Given I have a layouts directory
28
+ And I have an 'input/index.html' page with layout 'post' that contains 'page'
29
+ And I have a 'post' layout with layout 'default' that contains 'Post: {{ yield }}'
30
+ And I have a 'default' layout that contains 'Layout: {{ yield }}'
31
+ When I run laze
32
+ Then the output directory should exist
33
+ And I should see 'Layout: Post: <p>page</p>' in 'output/index.html'
34
+
35
+ Scenario: Basic site with includes
36
+ Given I have a includes directory
37
+ And I have an 'input/index.html' file that contains "Included: {% include 'foo' %}"
38
+ And I have an 'includes/foo.html' file that contains 'foo'
39
+ When I run laze
40
+ Then the output directory should exist
41
+ And I should see 'Included: foo' in 'output/index.html'
42
+
43
+ Scenario: CSS files
44
+ Given I have an 'input/base.css' file that contains 'foo'
45
+ When I run laze
46
+ Then the output directory should exist
47
+ And I should see 'foo' in 'output/base.css'
48
+
49
+ Scenario: LESS files
50
+ Given I have an 'input/base.less' file that contains '#foo { width: 1+1; }'
51
+ When I run laze
52
+ Then the output directory should exist
53
+ And I should see '#foo \{ width: 2; \}' in 'output/base.css'
54
+
55
+ Scenario: Javascript files
56
+ Given I have an 'input/base.js' file that contains 'foo'
57
+ When I run laze
58
+ Then the output directory should exist
59
+ And I should see 'foo' in 'output/base.js'
60
+
61
+ Scenario: XML Sitemaps
62
+ Given I have an 'input/test.html' file that contains 'foo'
63
+ When I run laze
64
+ Then the output directory should exist
65
+ And I should see 'foo' in 'output/test.html'
66
+ And I should see 'test.html' in 'output/sitemap.xml'
67
+
68
+ Scenario: robots.txt
69
+ Given I have an 'input/test.html' file that contains 'foo'
70
+ When I run laze
71
+ Then the output directory should exist
72
+ And I should see 'foo' in 'output/test.html'
73
+ And I should see 'Sitemap: sitemap.xml' in 'output/robots.txt'
@@ -0,0 +1,49 @@
1
+ @plugins
2
+ Feature: Plugins
3
+ In order to automate tasks
4
+ As a web developer
5
+ I want to use plugins to awesomize my website
6
+
7
+ Scenario: CSS compression
8
+ Given I have an 'input/screen.css' file that contains
9
+ """
10
+ a {
11
+ color: #000;
12
+ }
13
+
14
+ """
15
+ When I run laze with minification
16
+ Then the output directory should exist
17
+ And I should see 'a\{color:#000;\}' in 'output/screen.css'
18
+
19
+ Scenario: Javascript compression
20
+ Given I have an 'input/base.js' file that contains
21
+ """
22
+ var hello = "world";
23
+
24
+ """
25
+ When I run laze with minification
26
+ Then the output directory should exist
27
+ And I should see 'var hello="world";' in 'output/base.js'
28
+
29
+
30
+ Scenario: Javascript requires
31
+ Given I have an 'input/base.js' file that contains '// require "foo.js"'
32
+ And I have an 'input/foo.js' file that contains '// test'
33
+ When I run laze
34
+ Then the output directory should exist
35
+ And I should see '// test' in 'output/base.js'
36
+
37
+ Scenario: CSS imports
38
+ Given I have an 'input/base.css' file that contains '@import url(bar.css)'
39
+ And I have an 'input/bar.css' file that contains 'baaah'
40
+ When I run laze
41
+ Then the output directory should exist
42
+ And I should see 'baaah' in 'output/base.css'
43
+
44
+ Scenario: CSS cache busters
45
+ Given I have an 'input/base.css' file that contains 'foo { background: url(test.png); }'
46
+ And I have an 'input/test.png' file that contains 'foo'
47
+ When I run laze
48
+ Then the output directory should exist
49
+ And I should see 'url\(test.png\?\d+\)' in 'output/base.css'
@@ -0,0 +1,26 @@
1
+ Feature: Site data
2
+ As a web designer creating a static website
3
+ I want to be able to embed data into my site
4
+ In order to speed up development
5
+
6
+ Scenario: use page variable in a page
7
+ Given I have an 'input/index.html' page with title 'Foo' that contains '{{ page.title }}'
8
+ When I run laze
9
+ Then the output directory should exist
10
+ And I should see 'Foo' in 'output/index.html'
11
+
12
+ Scenario: use variables in a layout
13
+ Given I have a layouts directory
14
+ And I have a 'default' layout that contains '{{ page.title }}: {{ yield }}'
15
+ And I have an 'input/index.html' page with title 'Foo' and with layout 'default' that contains 'bar'
16
+ When I run laze
17
+ Then the output directory should exist
18
+ And I should see 'Foo: <p>bar</p>' in 'output/index.html'
19
+
20
+ Scenario: use variables in an include
21
+ Given I have a includes directory
22
+ And I have an 'includes/foo.html' file that contains '{{ page.title }}'
23
+ And I have an 'input/index.html' page with title 'Foo' that contains '{% include \'foo\' %}'
24
+ When I run laze
25
+ Then the output directory should exist
26
+ And I should see 'Foo' in 'output/index.html'
@@ -0,0 +1,77 @@
1
+ Before do
2
+ FileUtils.mkdir(TEST_DIR)
3
+ Dir.chdir(TEST_DIR)
4
+ end
5
+
6
+ After do
7
+ Dir.chdir(TEST_DIR)
8
+ FileUtils.rm_rf(TEST_DIR) if File.directory?(TEST_DIR)
9
+ end
10
+
11
+ Given /^I have an '(.+?)' file that contains ('|")(.*)\2$/ do |file, quote, text|
12
+ FileUtils.mkdir_p(File.dirname(file))
13
+ File.open(file, 'w') do |f|
14
+ f.write(text)
15
+ end
16
+ end
17
+
18
+ Given /^I have a (.+?) directory$/ do |dir|
19
+ FileUtils.mkdir(dir)
20
+ end
21
+
22
+ Given /^I have a '(.+?)' layout that contains ('|")(.*)\2$/ do |layout, quote, text|
23
+ File.open(File.join('layouts', layout + '.html'), 'w') do |f|
24
+ f.write(text)
25
+ end
26
+ end
27
+
28
+ Given /^I have a '(.+?)' layout with layout '(.+?)' that contains '(.*)'$/ do |filename, layout, text|
29
+ File.open(File.join('layouts', filename + '.html'), 'w') do |f|
30
+ f.write <<-EOF
31
+ layout: #{layout}
32
+ ---
33
+ #{text}
34
+ EOF
35
+ end
36
+ end
37
+
38
+ Given /^I have a '(.+?)' file that contains '(.*)'$/ do |file, text|
39
+ File.open(file, 'w') do |f|
40
+ f.write(text)
41
+ end
42
+ end
43
+
44
+ Given /^I have an? '(.+?)' file that contains$/ do |file, text|
45
+ FileUtils.mkdir_p(File.dirname(file))
46
+ File.open(file, 'w') do |f|
47
+ f.write(text)
48
+ end
49
+ end
50
+
51
+ Given /^I have an '(.*?)' page(?: with (.*?) '(.*?)')?(?: and with (.*?) '(.*?)')? that contains '(.*)'$/ do |file, key, value, other_key, other_value, text|
52
+ FileUtils.mkdir('input') unless File.directory?('input')
53
+ File.open(file, 'w') do |f|
54
+ f.write <<EOF
55
+ #{key}: #{value}
56
+ #{other_key + ': ' + other_value unless other_key.nil?}
57
+ ---
58
+ #{text}
59
+ EOF
60
+ end
61
+ end
62
+
63
+ When /^I run laze$/ do
64
+ run_laze
65
+ end
66
+
67
+ When /^I run laze with minification$/ do
68
+ run_laze(:minify => true)
69
+ end
70
+
71
+ Then /^the (.+?) directory should exist$/ do |dir|
72
+ assert File.directory?(dir)
73
+ end
74
+
75
+ Then /^I should see '(.*)' in '(.+?)'$/ do |text, file|
76
+ assert_match Regexp.new(text), File.open(file).readlines.join
77
+ end
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ require 'rr'
3
+ require 'test/unit'
4
+
5
+ World do
6
+ include Test::Unit::Assertions
7
+ end
8
+
9
+ TEST_DIR = File.join(ENV['PWD'], 'tmp')
10
+ LAZE_PATH = File.join(ENV['PWD'], 'bin', 'laze')
11
+
12
+ def run_laze(options = {})
13
+ command = LAZE_PATH.dup
14
+ command << ' -m' if options[:minify]
15
+ command << ' >> /dev/null 2>&1' if options[:debug].nil?
16
+ system command
17
+ end
data/lib/laze.rb ADDED
@@ -0,0 +1,64 @@
1
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
+
3
+ begin
4
+ # Core
5
+ require 'yaml'
6
+
7
+ # Standard library
8
+ require 'fileutils'
9
+ require 'logger'
10
+
11
+ # Third party
12
+ require 'liquid'
13
+ require 'rdiscount'
14
+ require 'redcloth'
15
+ rescue LoadError
16
+ # Gems
17
+ retry if require 'rubygems'
18
+ raise
19
+ end
20
+
21
+ module Laze #:nodoc:
22
+ def debug(msg)
23
+ LOGGER.debug(msg) if const_defined?('LOGGER')
24
+ end
25
+
26
+ def warn(msg)
27
+ LOGGER.warn(msg) if const_defined?('LOGGER')
28
+ end
29
+
30
+ def info(msg)
31
+ LOGGER.info(msg) if const_defined?('LOGGER')
32
+ end
33
+
34
+ def fatal(msg)
35
+ LOGGER.fatal(msg) if const_defined?('LOGGER')
36
+ end
37
+
38
+ def self.version
39
+ yml = YAML.load(File.read(File.join(File.dirname(__FILE__), *%w[.. VERSION.yml])))
40
+ "#{yml[:major]}.#{yml[:minor]}.#{yml[:patch]}"
41
+ end
42
+
43
+ extend self
44
+ end
45
+
46
+ # Internal requires
47
+ require 'laze/core_extensions'
48
+ require 'laze/plugins'
49
+ require 'laze/item'
50
+ require 'laze/page'
51
+ require 'laze/asset'
52
+ require 'laze/stylesheet'
53
+ require 'laze/javascript'
54
+ require 'laze/renderer'
55
+ require 'laze/renderers/page_renderer'
56
+ require 'laze/renderers/stylesheet_renderer'
57
+ require 'laze/renderers/javascript_renderer'
58
+ require 'laze/section'
59
+ require 'laze/layout'
60
+ require 'laze/secretary'
61
+ require 'laze/target'
62
+ require 'laze/targets/filesystem'
63
+ require 'laze/store'
64
+ require 'laze/stores/filesystem'
data/lib/laze/asset.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Laze
2
+ class Asset < Item # :nodoc:
3
+ def filename
4
+ properties[:filename]
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ class Hash #:nodoc:
2
+ def stringify_keys
3
+ inject({}) do |output, (key, value)|
4
+ output[(key.to_s rescue key) || key] = value
5
+ output
6
+ end
7
+ end
8
+
9
+ def symbolize_keys
10
+ inject({}) do |output, (key, value)|
11
+ output[(key.to_sym rescue key) || key] = value
12
+ output
13
+ end
14
+ end
15
+ end
data/lib/laze/item.rb ADDED
@@ -0,0 +1,59 @@
1
+ module Laze
2
+ # An item is a basic node in a site. It is usually not used directly, but
3
+ # only through one of its subclasses, like Page or Section. An item is used
4
+ # as a generic container for static files, such as images.
5
+ class Item
6
+ # Hash of proprties, like page title or output filename.
7
+ attr_accessor :properties
8
+
9
+ # Other item that has this item as one of its subitems.
10
+ attr_accessor :parent
11
+
12
+ # Contents of the file
13
+ attr_accessor :content
14
+
15
+ # New items should be created with a hash of options:
16
+ #
17
+ # Item.new :title => 'Foo'
18
+ #
19
+ def initialize(properties, content)
20
+ @properties, @content, @parent = properties, content, nil
21
+ end
22
+
23
+ # Test if this item has a given property.
24
+ def has?(key)
25
+ @properties.has_key?(key)
26
+ end
27
+
28
+ # Shortcut method to the filename property.
29
+ def filename
30
+ @properties[:filename]
31
+ end
32
+
33
+ def number_of_subitems
34
+ 0
35
+ end
36
+
37
+ # An array of items, where each item is the next's
38
+ # parent.
39
+ def ancestors
40
+ parent ? [parent, *parent.ancestors].reverse : []
41
+ end
42
+
43
+ def to_s #:nodoc:
44
+ filename
45
+ end
46
+
47
+ def inspect #:nodoc:
48
+ "#<#{self.class}:0x#{self.object_id.to_s(16)} #{filename}>"
49
+ end
50
+
51
+ protected
52
+
53
+ def self.include_plugins(kind) #:nodoc:
54
+ Laze::Plugins.each do |plugin|
55
+ include plugin if plugin.applies_to?(kind)
56
+ end
57
+ end
58
+ end
59
+ end