jekyll-minibundle 2.1.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +96 -42
  3. data/LICENSE.txt +1 -1
  4. data/README.md +232 -52
  5. data/Rakefile +16 -0
  6. data/jekyll-minibundle.gemspec +7 -6
  7. data/lib/jekyll/minibundle/asset_bundle.rb +3 -3
  8. data/lib/jekyll/minibundle/asset_file_drop.rb +45 -0
  9. data/lib/jekyll/minibundle/asset_file_properties.rb +12 -8
  10. data/lib/jekyll/minibundle/asset_file_registry.rb +4 -4
  11. data/lib/jekyll/minibundle/asset_tag_markup.rb +21 -20
  12. data/lib/jekyll/minibundle/bundle_file.rb +6 -1
  13. data/lib/jekyll/minibundle/development_file.rb +2 -1
  14. data/lib/jekyll/minibundle/development_file_collection.rb +2 -2
  15. data/lib/jekyll/minibundle/environment.rb +13 -15
  16. data/lib/jekyll/minibundle/files.rb +16 -18
  17. data/lib/jekyll/minibundle/hashes.rb +10 -12
  18. data/lib/jekyll/minibundle/log.rb +5 -7
  19. data/lib/jekyll/minibundle/mini_bundle_block.rb +35 -12
  20. data/lib/jekyll/minibundle/mini_stamp_tag.rb +108 -16
  21. data/lib/jekyll/minibundle/stamp_file.rb +1 -0
  22. data/lib/jekyll/minibundle/variable_template.rb +145 -0
  23. data/lib/jekyll/minibundle/variable_template_registry.rb +19 -0
  24. data/lib/jekyll/minibundle/version.rb +1 -1
  25. data/test/fixture/site/_bin/with_count +1 -1
  26. data/test/integration/minibundle_development_mode_test.rb +146 -61
  27. data/test/integration/minibundle_production_mode_test.rb +271 -143
  28. data/test/integration/ministamp_development_mode_test.rb +66 -25
  29. data/test/integration/ministamp_production_mode_test.rb +129 -37
  30. data/test/integration/static_files_as_asset_sources_test.rb +10 -10
  31. data/test/support/assertions.rb +1 -1
  32. data/test/support/{static_file_api_config.rb → static_file_config.rb} +6 -3
  33. data/test/support/test_case.rb +7 -4
  34. data/test/unit/asset_bundle_test.rb +6 -6
  35. data/test/unit/asset_file_drop_test.rb +65 -0
  36. data/test/unit/asset_file_registry_test.rb +136 -98
  37. data/test/unit/asset_tag_markup_test.rb +11 -5
  38. data/test/unit/bundle_file_properties_test.rb +44 -23
  39. data/test/unit/bundle_file_writing_test.rb +50 -32
  40. data/test/unit/development_file_properties_test.rb +95 -0
  41. data/test/unit/development_file_writing_test.rb +15 -6
  42. data/test/unit/environment_test.rb +3 -3
  43. data/test/unit/files_test.rb +7 -7
  44. data/test/unit/hashes_test.rb +12 -12
  45. data/test/unit/jekyll_static_file_api_test.rb +91 -20
  46. data/test/unit/mini_bundle_block_test.rb +59 -9
  47. data/test/unit/mini_stamp_tag_test.rb +37 -6
  48. data/test/unit/stamp_file_properties_test.rb +47 -24
  49. data/test/unit/stamp_file_writing_test.rb +33 -24
  50. data/test/unit/variable_template_test.rb +121 -0
  51. metadata +27 -6
  52. data/test/unit/development_file_collection_properties_test.rb +0 -106
@@ -4,18 +4,18 @@ require 'jekyll/minibundle/environment'
4
4
  module Jekyll::Minibundle::Test
5
5
  class EnvironmentTest < TestCase
6
6
  def test_find_site_config_returns_value_when_found
7
- assert_equal 1, Environment.find_site_config(make_site(top: {leaf: 1}), [:top, :leaf], Integer)
7
+ assert_equal(1, Environment.find_site_config(make_site(top: {leaf: 1}), [:top, :leaf], Integer))
8
8
  end
9
9
 
10
10
  def test_find_site_config_returns_nil_when_not_found
11
- assert_nil Environment.find_site_config(make_site, [:top, :leaf], Integer)
11
+ assert_nil(Environment.find_site_config(make_site, [:top, :leaf], Integer))
12
12
  end
13
13
 
14
14
  def test_find_site_config_raises_exception_if_found_value_is_of_unexpected_type
15
15
  err = assert_raises(RuntimeError) do
16
16
  Environment.find_site_config(make_site(top: {leaf: '1'}), [:top, :leaf], Integer)
17
17
  end
18
- assert_equal 'Invalid site configuration for key top.leaf; expecting type Integer', err.to_s
18
+ assert_equal('Invalid site configuration for key top.leaf; expecting type Integer', err.to_s)
19
19
  end
20
20
 
21
21
  private
@@ -8,7 +8,7 @@ module Jekyll::Minibundle::Test
8
8
  File.write('foo', 'content')
9
9
  Files.copy_p('foo', 'bar/zap')
10
10
  copied = File.read('bar/zap')
11
- assert_equal 'content', copied
11
+ assert_equal('content', copied)
12
12
  end
13
13
  end
14
14
 
@@ -20,7 +20,7 @@ module Jekyll::Minibundle::Test
20
20
  Tempfile.open('test') do |file|
21
21
  file.close
22
22
 
23
- assert_equal '', Files.read_last(file.path, 4)
23
+ assert_equal('', Files.read_last(file.path, 4))
24
24
  end
25
25
  end
26
26
 
@@ -29,7 +29,7 @@ module Jekyll::Minibundle::Test
29
29
  file.write("1\n2\n3\n4")
30
30
  file.close
31
31
 
32
- assert_equal "\n3\n4", Files.read_last(file.path, 4)
32
+ assert_equal("\n3\n4", Files.read_last(file.path, 4))
33
33
  end
34
34
  end
35
35
 
@@ -38,7 +38,7 @@ module Jekyll::Minibundle::Test
38
38
  file.write("1\n2")
39
39
  file.close
40
40
 
41
- assert_equal "1\n2", Files.read_last(file.path, 100)
41
+ assert_equal("1\n2", Files.read_last(file.path, 100))
42
42
  end
43
43
  end
44
44
 
@@ -47,13 +47,13 @@ module Jekyll::Minibundle::Test
47
47
  file.write("1\n2")
48
48
  file.close
49
49
 
50
- assert_equal '', Files.read_last(file.path, 0)
51
- assert_equal '', Files.read_last(file.path, -1)
50
+ assert_equal('', Files.read_last(file.path, 0))
51
+ assert_equal('', Files.read_last(file.path, -1))
52
52
  end
53
53
  end
54
54
 
55
55
  def test_strip_dot_slash_from_path_start
56
- assert_equal 'path', Files.strip_dot_slash_from_path_start('./path')
56
+ assert_equal('path', Files.strip_dot_slash_from_path_start('./path'))
57
57
  end
58
58
  end
59
59
  end
@@ -4,28 +4,28 @@ require 'jekyll/minibundle/hashes'
4
4
  module Jekyll::Minibundle::Test
5
5
  class HashesTest < TestCase
6
6
  def test_dig_returns_value_when_found
7
- assert_equal 1, Hashes.dig({top: {middle: {leaf: 1}}}, :top, :middle, :leaf)
8
- assert_equal 1, Hashes.dig({top: [{}, {leaf: 1}]}, :top, 1, :leaf)
9
- assert_equal 1, Hashes.dig([{}, {middle: [{}, {leaf: 1}]}], 1, :middle, 1, :leaf)
7
+ assert_equal(1, Hashes.dig({top: {middle: {leaf: 1}}}, :top, :middle, :leaf))
8
+ assert_equal(1, Hashes.dig({top: [{}, {leaf: 1}]}, :top, 1, :leaf))
9
+ assert_equal(1, Hashes.dig([{}, {middle: [{}, {leaf: 1}]}], 1, :middle, 1, :leaf))
10
10
  end
11
11
 
12
12
  def test_dig_returns_same_found_object
13
13
  leaf_obj = {leaf: 1}
14
- assert_same leaf_obj, Hashes.dig({top: {middle: leaf_obj}}, :top, :middle)
14
+ assert_same(leaf_obj, Hashes.dig({top: {middle: leaf_obj}}, :top, :middle))
15
15
  end
16
16
 
17
17
  def test_dig_returns_nil_when_not_found
18
- assert_nil Hashes.dig({}, :no_such)
19
- assert_nil Hashes.dig([], 0)
20
- assert_nil Hashes.dig({top: {}}, :top, :no_such_leaf)
21
- assert_nil Hashes.dig({top: {leaf: 1}}, :top, :no_such_leaf)
22
- assert_nil Hashes.dig({top: []}, :top, 0)
23
- assert_nil Hashes.dig([{leaf: 1}], 0, :no_such)
18
+ assert_nil(Hashes.dig({}, :no_such))
19
+ assert_nil(Hashes.dig([], 0))
20
+ assert_nil(Hashes.dig({top: {}}, :top, :no_such_leaf))
21
+ assert_nil(Hashes.dig({top: {leaf: 1}}, :top, :no_such_leaf))
22
+ assert_nil(Hashes.dig({top: []}, :top, 0))
23
+ assert_nil(Hashes.dig([{leaf: 1}], 0, :no_such))
24
24
  end
25
25
 
26
26
  def test_dig_returns_nil_for_nil
27
- assert_nil Hashes.dig(nil, :no_such_key)
28
- assert_nil Hashes.dig(nil, 0)
27
+ assert_nil(Hashes.dig(nil, :no_such_key))
28
+ assert_nil(Hashes.dig(nil, 0))
29
29
  end
30
30
 
31
31
  def test_pick_returns_hash_with_specified_keys
@@ -1,36 +1,82 @@
1
1
  require 'support/test_case'
2
+ require 'support/static_file_config'
2
3
  require 'jekyll/minibundle/development_file'
3
4
  require 'jekyll/minibundle/bundle_file'
4
5
  require 'jekyll/minibundle/stamp_file'
5
6
 
6
7
  module Jekyll::Minibundle::Test
7
8
  class JekyllStaticFileAPITest < TestCase
8
- def test_development_file_conforms_to_static_file_api
9
- assert_empty missing_api_methods(DevelopmentFile)
9
+ include StaticFileConfig
10
+
11
+ def test_development_file_has_all_static_file_methods
12
+ assert_empty(missing_static_file_methods(DevelopmentFile))
13
+ end
14
+
15
+ def test_bundle_file_has_all_static_file_methods
16
+ assert_empty(missing_static_file_methods(BundleFile))
17
+ end
18
+
19
+ def test_stamp_file_has_all_static_file_methods
20
+ assert_empty(missing_static_file_methods(StampFile))
21
+ end
22
+
23
+ def test_development_file_properties_has_similar_return_types_to_static_file_properties
24
+ with_real_site do |site|
25
+ FileUtils.touch('static.txt')
26
+ FileUtils.touch('dev.js')
27
+
28
+ return_type_diff = diff_non_nil_response_types_of_static_file_properties(
29
+ make_static_file(site, 'static.txt'),
30
+ make_development_file(site, 'dev.js')
31
+ )
32
+
33
+ assert_empty(return_type_diff)
34
+ end
10
35
  end
11
36
 
12
- def test_bundle_file_conforms_to_static_file_api
13
- assert_empty missing_api_methods(BundleFile)
37
+ def test_bundle_file_properties_has_similar_return_types_to_static_file_properties
38
+ with_real_site do |site|
39
+ FileUtils.touch('static.txt')
40
+ FileUtils.touch('dependency.js')
41
+ FileUtils.touch('app.js')
42
+
43
+ return_type_diff = diff_non_nil_response_types_of_static_file_properties(
44
+ make_static_file(site, 'static.txt'),
45
+ make_bundle_file(site, %w{dependency app})
46
+ )
47
+
48
+ assert_empty(return_type_diff)
49
+ end
14
50
  end
15
51
 
16
- def test_stamp_file_conforms_to_static_file_api
17
- assert_empty missing_api_methods(StampFile)
52
+ def test_stamp_file_properties_has_similar_return_types_to_static_file_properties
53
+ with_real_site do |site|
54
+ FileUtils.touch('static.txt')
55
+ FileUtils.touch('stamp.js')
56
+
57
+ return_type_diff = diff_non_nil_response_types_of_static_file_properties(
58
+ make_static_file(site, 'static.txt'),
59
+ make_stamp_file(site, 'stamp.js')
60
+ )
61
+
62
+ assert_empty(return_type_diff)
63
+ end
18
64
  end
19
65
 
20
66
  def test_development_file_has_same_to_liquid_hash_keys_as_static_file
21
- with_empty_site do |site|
67
+ with_real_site do |site|
22
68
  FileUtils.touch('static.txt')
23
69
  FileUtils.touch('dev.js')
24
70
 
25
71
  expected_keys = make_static_file(site, 'static.txt').to_liquid.keys.sort
26
72
  actual_keys = make_development_file(site, 'dev.js').to_liquid.keys.sort
27
73
 
28
- assert_equal expected_keys, actual_keys
74
+ assert_equal(expected_keys, actual_keys)
29
75
  end
30
76
  end
31
77
 
32
78
  def test_bundle_file_has_same_to_liquid_hash_keys_as_static_file
33
- with_empty_site do |site|
79
+ with_real_site do |site|
34
80
  FileUtils.touch('static.txt')
35
81
  FileUtils.touch('dependency.js')
36
82
  FileUtils.touch('app.js')
@@ -38,40 +84,65 @@ module Jekyll::Minibundle::Test
38
84
  expected_keys = make_static_file(site, 'static.txt').to_liquid.keys.sort
39
85
  actual_keys = make_bundle_file(site, %w{dependency app}).to_liquid.keys.sort
40
86
 
41
- assert_equal expected_keys, actual_keys
87
+ assert_equal(expected_keys, actual_keys)
42
88
  end
43
89
  end
44
90
 
45
91
  def test_stamp_file_has_same_to_liquid_hash_keys_as_static_file
46
- with_empty_site do |site|
92
+ with_real_site do |site|
47
93
  FileUtils.touch('static.txt')
48
94
  FileUtils.touch('stamp.js')
49
95
 
50
96
  expected_keys = make_static_file(site, 'static.txt').to_liquid.keys.sort
51
97
  actual_keys = make_stamp_file(site, 'stamp.js').to_liquid.keys.sort
52
98
 
53
- assert_equal expected_keys, actual_keys
99
+ assert_equal(expected_keys, actual_keys)
54
100
  end
55
101
  end
56
102
 
57
103
  private
58
104
 
59
- def missing_api_methods(clazz)
105
+ def missing_static_file_methods(clazz)
60
106
  Jekyll::StaticFile.public_instance_methods - clazz.public_instance_methods
61
107
  end
62
108
 
63
- def with_empty_site(&block)
64
- with_tmp_dir do |dir|
65
- block.call(make_fake_site(dir))
109
+ def response_types_of_methods(file, methods)
110
+ methods.each_with_object({}) do |method_name, acc|
111
+ acc[method_name] =
112
+ begin
113
+ value = file.send(method_name)
114
+ {returned_type: value.class}
115
+ rescue => e
116
+ {raised: e}
117
+ end
118
+ end
119
+ end
120
+
121
+ def diff_non_nil_response_types_of_static_file_properties(file_master, file_conforming)
122
+ methods = STATIC_FILE_PROPERTIES - [:to_liquid]
123
+
124
+ master_response_types = response_types_of_methods(file_master, methods)
125
+ conforming_response_types = response_types_of_methods(file_conforming, methods)
126
+
127
+ master_to_compare = master_response_types.select do |_, value|
128
+ value.key?(:returned_type) && value.fetch(:returned_type) != NilClass
129
+ end
130
+
131
+ master_to_compare.to_a - conforming_response_types.to_a
132
+ end
133
+
134
+ def with_real_site(&block)
135
+ with_site_dir do |dir|
136
+ block.call(make_real_site(dir))
66
137
  end
67
138
  end
68
139
 
69
- def make_static_file(site, filename)
140
+ def make_static_file(site, path)
70
141
  ::Jekyll::StaticFile.new(
71
142
  site,
72
- nil,
73
- nil,
74
- filename
143
+ site.source,
144
+ "/#{File.dirname(path)}",
145
+ File.basename(path)
75
146
  )
76
147
  end
77
148
 
@@ -6,11 +6,46 @@ module Jekyll::Minibundle::Test
6
6
  class MiniBundleBlockTest < TestCase
7
7
  include FixtureConfig
8
8
 
9
+ def setup
10
+ AssetFileRegistry.clear_all
11
+ end
12
+
9
13
  def test_raise_exception_if_no_type_argument
10
14
  err = assert_raises(ArgumentError) do
11
15
  Liquid::Template.parse('{% minibundle %} {% endminibundle %}')
12
16
  end
13
- assert_equal "No asset type for minibundle block; pass value such as 'css' or 'js' as the argument", err.to_s
17
+ assert_equal("Missing asset type for minibundle block; pass value such as 'css' or 'js' as the argument", err.to_s)
18
+ end
19
+
20
+ def test_raise_exception_if_missing_block_contents
21
+ rendered = render_template(<<-END)
22
+ {% minibundle css %}
23
+
24
+ {% endminibundle %}
25
+ END
26
+ expected = "Liquid error: Missing configuration for minibundle block; pass configuration in YAML syntax\n"
27
+ assert_equal(expected, rendered)
28
+ end
29
+
30
+ def test_raise_exception_if_invalid_block_contents_syntax
31
+ rendered = render_template(<<-END)
32
+ {% minibundle css %}
33
+ }
34
+ {% endminibundle %}
35
+ END
36
+ expected =
37
+ 'Liquid error: Failed parsing minibundle block contents syntax as YAML: "}". ' \
38
+ "Cause: (<unknown>): did not find expected node content while parsing a block node at line 2 column 1\n"
39
+ assert_equal(expected, rendered)
40
+ end
41
+
42
+ def test_raise_exception_if_unsupported_block_contents_type
43
+ rendered = render_template(<<-END)
44
+ {% minibundle css %}
45
+ str
46
+ {% endminibundle %}
47
+ END
48
+ assert_equal("Liquid error: Unsupported minibundle block contents type (String), only Hash is supported: \nstr\n\n", rendered)
14
49
  end
15
50
 
16
51
  [
@@ -29,6 +64,16 @@ module Jekyll::Minibundle::Test
29
64
  baseurl_config: 'baseurl: /',
30
65
  expected_asset_url: "/#{CSS_BUNDLE_DESTINATION_FINGERPRINT_PATH}"
31
66
  },
67
+ {
68
+ description: 'dot_baseurl_results_in_asset_url_without_baseurl',
69
+ baseurl_config: 'baseurl: .',
70
+ expected_asset_url: CSS_BUNDLE_DESTINATION_FINGERPRINT_PATH
71
+ },
72
+ {
73
+ description: 'dot_slash_baseurl_results_in_asset_url_without_baseurl',
74
+ baseurl_config: 'baseurl: ./',
75
+ expected_asset_url: CSS_BUNDLE_DESTINATION_FINGERPRINT_PATH
76
+ },
32
77
  {
33
78
  description: 'slash_root_baseurl_results_in_asset_url_with_baseurl',
34
79
  baseurl_config: 'baseurl: /root',
@@ -41,9 +86,7 @@ module Jekyll::Minibundle::Test
41
86
  }
42
87
  ].each do |spec|
43
88
  define_method :"test_normalizing_baseurl_with_#{spec.fetch(:description)}" do
44
- AssetFileRegistry.clear_all
45
-
46
- template = Liquid::Template.parse(<<-END)
89
+ actual_output = render_template(<<-END)
47
90
  {% minibundle css %}
48
91
  source_dir: _assets/styles
49
92
  destination_path: assets/site
@@ -55,14 +98,21 @@ minifier_cmd: #{minifier_cmd_to_remove_comments}
55
98
  {% endminibundle %}
56
99
  END
57
100
 
58
- actual_output = nil
59
- capture_io do
60
- actual_output = template.render({}, registers: {site: make_fake_site(site_fixture_path)})
61
- end
62
101
  expected_output = %{<link rel="stylesheet" href="#{spec.fetch(:expected_asset_url)}">\n}
63
102
 
64
- assert_equal expected_output, actual_output
103
+ assert_equal(expected_output, actual_output)
104
+ end
105
+ end
106
+
107
+ private
108
+
109
+ def render_template(template)
110
+ compiled = Liquid::Template.parse(template)
111
+ rendered = nil
112
+ capture_io do
113
+ rendered = compiled.render({}, registers: {site: make_fake_site(site_fixture_path)})
65
114
  end
115
+ rendered
66
116
  end
67
117
  end
68
118
  end
@@ -6,26 +6,57 @@ module Jekyll::Minibundle::Test
6
6
  class MiniStampTagTest < TestCase
7
7
  include FixtureConfig
8
8
 
9
- def test_raise_exception_if_no_asset_source_argument
9
+ def test_raise_exception_if_argument_is_missing
10
10
  err = assert_raises(ArgumentError) do
11
11
  Liquid::Template.parse('{% ministamp %}')
12
12
  end
13
- assert_equal "No asset source for ministamp tag; pass value such as '_assets/site.css' as the first argument", err.to_s
13
+ assert_equal('Missing asset source and destination paths for ministamp tag; specify value such as "_assets/source.css assets/destination.css" as the argument', err.to_s)
14
14
  end
15
15
 
16
- def test_raise_exception_if_no_asset_destination_argument
16
+ def test_raise_exception_if_asset_destination_is_missing_in_string_argument_type
17
17
  err = assert_raises(ArgumentError) do
18
18
  Liquid::Template.parse('{% ministamp /_assets/site.css %}')
19
19
  end
20
- assert_equal "No asset destination for ministamp tag; pass value such as 'assets/site.css' as the second argument", err.to_s
20
+ assert_equal('Missing asset destination path for ministamp tag; specify value such as "assets/destination.css" after asset source path argument, separated with a space', err.to_s)
21
21
  end
22
22
 
23
- def test_ignore_rest_arguments
23
+ def test_ignores_arguments_after_asset_destination_in_string_argument_type
24
24
  AssetFileRegistry.clear_all
25
25
  output = Liquid::Template
26
26
  .parse("{% ministamp #{STAMP_SOURCE_PATH} #{STAMP_DESTINATION_PATH} rest %}")
27
27
  .render({}, registers: {site: make_fake_site(site_fixture_path)})
28
- assert_equal STAMP_DESTINATION_FINGERPRINT_PATH, output
28
+ assert_equal(STAMP_DESTINATION_FINGERPRINT_PATH, output)
29
+ end
30
+
31
+ def test_raise_exception_if_invalid_arguments_syntax
32
+ err = assert_raises(ArgumentError) do
33
+ Liquid::Template.parse('{% ministamp source_path: src, destination_path: dst %}')
34
+ end
35
+ expected =
36
+ 'Failed parsing ministamp tag argument syntax as YAML: "source_path: src, destination_path: dst". ' \
37
+ 'Cause: (<unknown>): mapping values are not allowed in this context at line 1 column 35'
38
+ assert_equal(expected, err.to_s)
39
+ end
40
+
41
+ def test_raise_exception_if_unsupported_argument_type
42
+ err = assert_raises(ArgumentError) do
43
+ Liquid::Template.parse("{% ministamp ['source_path', 'src', 'destination_path', 'dst'] %}")
44
+ end
45
+ assert_equal("Unsupported ministamp tag argument type (Array), only String and Hash are supported: ['source_path', 'src', 'destination_path', 'dst']", err.to_s)
46
+ end
47
+
48
+ def test_raise_exception_if_asset_source_is_missing_in_hash_argument_type
49
+ err = assert_raises(ArgumentError) do
50
+ Liquid::Template.parse('{% ministamp {} %}')
51
+ end
52
+ assert_equal('Missing asset source path for ministamp tag; specify Hash entry such as "source_path: _assets/site.css"', err.to_s)
53
+ end
54
+
55
+ def test_raise_exception_if_asset_destination_is_missing_in_hash_argument_type
56
+ err = assert_raises(ArgumentError) do
57
+ Liquid::Template.parse('{% ministamp { source_path: src } %}')
58
+ end
59
+ assert_equal('Missing asset destination path for ministamp tag; specify Hash entry such as "destination_path: assets/site.css"', err.to_s)
29
60
  end
30
61
  end
31
62
  end