jekyll-minibundle 2.1.2 → 2.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 (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