usmu 0.2.1 → 0.2.2

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +18 -22
  3. data/CHANGELOG.md +82 -0
  4. data/README.md +0 -8
  5. data/Rakefile +32 -0
  6. data/bin/usmu +1 -5
  7. data/lib/usmu.rb +5 -3
  8. data/lib/usmu/configuration.rb +13 -1
  9. data/lib/usmu/plugin/core.rb +35 -1
  10. data/lib/usmu/site_generator.rb +13 -13
  11. data/lib/usmu/template/helpers.rb +19 -0
  12. data/lib/usmu/template/include.rb +87 -0
  13. data/lib/usmu/template/layout.rb +198 -0
  14. data/lib/usmu/template/page.rb +22 -0
  15. data/lib/usmu/template/static_file.rb +50 -0
  16. data/lib/usmu/version.rb +1 -1
  17. data/share/init-site/.gitignore +2 -0
  18. data/share/init-site/Gemfile +6 -0
  19. data/share/init-site/layouts/html.slim +8 -0
  20. data/share/init-site/source/index.md +3 -0
  21. data/share/init-site/usmu.yml +3 -0
  22. data/test/expected-site/.dotfiletest.txt +1 -0
  23. data/test/expected-site/default.html +4 -0
  24. data/test/expected-site/embedded.html +7 -0
  25. data/test/expected-site/index.html +4 -0
  26. data/test/site/content/.dotfiletest.txt +1 -0
  27. data/test/site/includes/footer.meta.yml +2 -0
  28. data/test/site/includes/footer.slim +1 -0
  29. data/test/site/layouts/embedded.slim +2 -0
  30. data/test/site/layouts/html.slim +2 -0
  31. data/test/spec/acceptance/full_site_build.feature +7 -2
  32. data/test/spec/acceptance/steps/full_site_build_steps.rb +9 -4
  33. data/test/spec/configuration_spec.rb +35 -14
  34. data/test/spec/site_generator_spec.rb +2 -2
  35. data/test/spec/{layout_spec.rb → template/layout_spec.rb} +4 -4
  36. data/test/spec/{page_spec.rb → template/page_spec.rb} +4 -4
  37. data/test/spec/{static_file_spec.rb → template/static_file_spec.rb} +5 -5
  38. data/usmu-jruby.gemspec +1 -1
  39. data/usmu.gemspec +1 -1
  40. metadata +29 -13
  41. data/lib/usmu/layout.rb +0 -189
  42. data/lib/usmu/page.rb +0 -20
  43. data/lib/usmu/static_file.rb +0 -48
@@ -0,0 +1,198 @@
1
+ require 'tilt'
2
+ require 'deep_merge'
3
+ require 'usmu/template/helpers'
4
+ require 'usmu/template/static_file'
5
+
6
+ module Usmu
7
+ module Template
8
+ # Class to represent files templated with a Tilt library. Most of the custom rendering logic is contained here.
9
+ class Layout < StaticFile
10
+ # @!attribute [r] type
11
+ # @return [String] the type of file this is. This is used to determine which template engine to use.
12
+ attr_reader :type
13
+
14
+ # @param configuration [Usmu::Configuration] The configuration for the website we're generating.
15
+ # @param name [String] The name of the file in the source directory.
16
+ # @param type [String] The type of template to use with the file. Used for testing purposes.
17
+ # @param content [String] The content of the file. Used for testing purposes.
18
+ # @param metadata [String] The metadata for the file. Used for testing purposes.
19
+ def initialize(configuration, name, type = nil, content = nil, metadata = nil)
20
+ super(configuration, name)
21
+
22
+ if type.nil?
23
+ type = name.split('.').last
24
+ unless ::Tilt.default_mapping[type]
25
+ raise "Templates of type '#{type}' aren't currently supported by Tilt. " +
26
+ 'Do you have the required gem installed?'
27
+ end
28
+ end
29
+ @type = type
30
+ path = File.join("#{content_path}", "#{name[0, name.length - type.length - 1]}")
31
+
32
+ if content.nil?
33
+ content = File.read("#{path}.#{type}")
34
+ end
35
+ @content = content
36
+
37
+ if metadata.nil?
38
+ meta_file = "#{path}.meta.yml"
39
+ metadata = if File.exist? meta_file
40
+ YAML.load_file(meta_file)
41
+ else
42
+ {}
43
+ end
44
+ end
45
+ @metadata = metadata
46
+
47
+ @parent = nil
48
+ @parent = Layout.find_layout(configuration, self.metadata['layout'])
49
+ end
50
+
51
+ # @!attribute [r] metadata
52
+ # @return [Hash] the metadata associated with this layout.
53
+ #
54
+ # Returns the metadata associated with this layout.
55
+ #
56
+ # This will include any metadata from parent templates and default metadata
57
+ def metadata
58
+ if @parent.nil?
59
+ (@configuration['default meta'] || {}).dup.deep_merge!(@metadata)
60
+ else
61
+ @parent.metadata.deep_merge!(@metadata)
62
+ end
63
+ end
64
+
65
+ # Renders the file with any templating language required and returns the result
66
+ #
67
+ # @param variables [Hash] Variables to be used in the template.
68
+ # @return [String] The rendered file.
69
+ def render(variables = {})
70
+ content = template_class.new("#{@name}.#{@type}", 1, @configuration[provider_name]) { @content }.
71
+ render(helpers, get_variables(variables))
72
+ has_cr = content.index("\r")
73
+ content += (has_cr ? "\r\n" : "\n") if content[-1] != "\n"
74
+ if @parent.nil?
75
+ content
76
+ else
77
+ @parent.render({'content' => content})
78
+ end
79
+ end
80
+
81
+ # @!attribute [r] input_path
82
+ # @return [String] the full path to the file in the source directory
83
+ def input_path
84
+ File.join(content_path, @name)
85
+ end
86
+
87
+ # @!attribute [r] output_extension
88
+ # @return [String] the extension to use with the output file.
89
+ def output_extension
90
+ case @type
91
+ when 'erb', 'rhtml', 'erubis', 'liquid'
92
+ nil
93
+ when 'coffee'
94
+ 'js'
95
+ when 'less', 'sass', 'scss'
96
+ 'css'
97
+ else
98
+ 'html'
99
+ end
100
+ end
101
+
102
+ # @!attribute [r] output_filename
103
+ # @return [String] the filename to use in the output directory.
104
+ #
105
+ # Returns the filename to use for the output directory with any modifications to the input filename required.
106
+ def output_filename
107
+ if output_extension
108
+ @name[0..@name.rindex('.')] + output_extension
109
+ else
110
+ @name[0..@name.rindex('.') - 1]
111
+ end
112
+ end
113
+
114
+ # Static method to create a layout for a given configuration by it's name if it exists. This differs from
115
+ # `#initialise` in that it allows different types of values to be supplied as the name and will not fail if name
116
+ # is nil
117
+ #
118
+ # @param configuration [Usmu::Configuration] The configuration to use for the search
119
+ # @param name [String]
120
+ # If name is a string then search for a template with that name. Name here should not include
121
+ # file extension, eg. body not body.slim. If name is not a string then it will be returned verbatim. This means
122
+ # that name is nilable and can also be passed in as an Usmu::Template::Layout already for testing purposes.
123
+ # @return [Usmu::Layout]
124
+ def self.find_layout(configuration, name)
125
+ if name === 'none'
126
+ nil
127
+ elsif name.class.name == 'String'
128
+ Dir["#{configuration.layouts_path}/#{name}.*"].each do |f|
129
+ filename = File.basename(f)
130
+ if filename != "#{name}.meta.yml"
131
+ return new(configuration, f[(configuration.layouts_path.length + 1)..f.length])
132
+ end
133
+ end
134
+ nil
135
+ else
136
+ name
137
+ end
138
+ end
139
+
140
+ # Tests if a given file is a valid Tilt template based on the filename.
141
+ #
142
+ # @param folder_type [String]
143
+ # One of `"source"` or `"layout"` depending on where the template is in the source tree.
144
+ # Not used by Usmu::Template::Layout directly but intended to be available for future API.
145
+ # @param name [String] The filename to be tested.
146
+ # @return [Boolean]
147
+ def self.is_valid_file?(folder_type, name)
148
+ type = name.split('.').last
149
+ ::Tilt.default_mapping[type] ? true : false
150
+ end
151
+
152
+ protected
153
+
154
+ # @!attribute [r] template_class
155
+ # @return [Tilt::Template] the Tilt template engine for this layout
156
+ def template_class
157
+ @template_class ||= ::Tilt.default_mapping[@type]
158
+ end
159
+
160
+ # @!attribute [r] provider_name
161
+ # @return [String] the Tilt template engine's name for this layout
162
+ #
163
+ # Returns the Tilt template engine's name for this layout.
164
+ #
165
+ # This is used to determine which settings to use from the configuration file.
166
+ def provider_name
167
+ Tilt.default_mapping.lazy_map[@type].select {|x| x[0] == template_class.name }.first[1].split('/').last
168
+ end
169
+
170
+ # @!attribute [r] content_path
171
+ # @return [string] the base path to the files used by this class.
172
+ #
173
+ # Returns the base path to the files used by this class.
174
+ #
175
+ # This folder should be the parent folder for the file named by the name attribute.
176
+ #
177
+ # @see #name
178
+ def content_path
179
+ @configuration.layouts_path
180
+ end
181
+
182
+ # @!attribute [r] helpers
183
+ # @return [Usmu::Template::Helpers] the Helpers class to use as a scope for templates
184
+ def helpers
185
+ @helpers ||= Usmu::Template::Helpers.new(@configuration)
186
+ end
187
+
188
+ private
189
+
190
+ # Utility function which collates variables to pass to the template engine.
191
+ #
192
+ # @return [Hash]
193
+ def get_variables(variables)
194
+ {'site' => @configuration}.deep_merge!(metadata).deep_merge!(variables)
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,22 @@
1
+ require 'usmu/template/layout'
2
+
3
+ module Usmu
4
+ module Template
5
+ # Represents a page in the source directory of the website.
6
+ class Page < Layout
7
+ protected
8
+
9
+ # @!attribute [r] content_path
10
+ # @return [string] the base path to the files used by this class.
11
+ #
12
+ # Returns the base path to the files used by this class.
13
+ #
14
+ # This folder should be the parent folder for the file named by the name attribute.
15
+ #
16
+ # @see #name
17
+ def content_path
18
+ @configuration.source_path
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,50 @@
1
+ require 'usmu/configuration'
2
+
3
+ module Usmu
4
+ module Template
5
+ # Represents a static file which should be transferred to the destination unchanged. This also acts as the base
6
+ # class for all layouts and page types. The basic interface defined here is used to process all types of files.
7
+ class StaticFile
8
+ @log = Logging.logger[self]
9
+
10
+ # @!attribute [r] name
11
+ # @return [String] the name of the file in the source directory
12
+ attr_reader :name
13
+
14
+ # @param configuration [Usmu::Configuration] The configuration for the website we're generating.
15
+ # @param name [String] The name of the file in the source directory.
16
+ # @param type [String] The type of template to use with the file. Not used for StaticFile.
17
+ # Used for testing purposes.
18
+ # @param content [String] The content of the file. Used for testing purposes.
19
+ # @param metadata [String] The metadata for the file. Used for testing purposes.
20
+ def initialize(configuration, name, type = nil, content = nil, metadata = nil)
21
+ @configuration = configuration
22
+ @name = name
23
+ @type = type
24
+ @content = content
25
+ end
26
+
27
+ # Renders the file with any templating language required and returns the result
28
+ #
29
+ # @param variables [Hash] Variables to be used in the template.
30
+ # @return [String] The rendered file
31
+ def render(variables = {})
32
+ @content || File.read(input_path)
33
+ end
34
+
35
+ # @!attribute [r] input_path
36
+ # @return [String] the full path to the file in the source directory
37
+ def input_path
38
+ File.join(@configuration.source_path, @name)
39
+ end
40
+
41
+ # @!attribute [r] output_filename
42
+ # @return [String] the filename to use in the output directory.
43
+ #
44
+ # Returns the filename to use for the output directory with any modifications to the input filename required.
45
+ def output_filename
46
+ @name
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/usmu/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Usmu
3
3
  # The current version string for the gem
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.2'
5
5
  end
@@ -0,0 +1,2 @@
1
+ /site
2
+ /Gemfile.lock
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'usmu'
4
+
5
+ ## Add any Usmu plugins you need for your site here.
6
+ #gem 'usmu-s3'
@@ -0,0 +1,8 @@
1
+ doctype html
2
+ html
3
+ head
4
+ meta http-equiv="Content-Type" content="text/html; charset=utf-8"
5
+ title #{site.title}
6
+
7
+ body
8
+ | #{{content}}
@@ -0,0 +1,3 @@
1
+ # It works!
2
+
3
+ Welcome to your new Usmu website! Feel free to look around and find out what's in store for you.
@@ -0,0 +1,3 @@
1
+ ---
2
+
3
+ title: Example site
@@ -0,0 +1 @@
1
+ Maybe we want to include a dotfile in our website? I don't know why, but we should copy these as well.
@@ -10,5 +10,9 @@
10
10
  <p>No metadata for this file. Uh oh!</p>
11
11
 
12
12
  </div>
13
+ <footer>
14
+ Copyright &copy; Testers Inc.
15
+ </footer>
16
+
13
17
  </body>
14
18
  </html>
@@ -9,7 +9,14 @@
9
9
  <h1>Embedded test</h1>
10
10
 
11
11
  </div>
12
+ <footer>
13
+ Copyright &copy; Special Corp Pty. Ltd.
14
+ </footer>
12
15
 
13
16
  </div>
17
+ <footer>
18
+ Copyright &copy; Testers Inc.
19
+ </footer>
20
+
14
21
  </body>
15
22
  </html>
@@ -10,5 +10,9 @@
10
10
  <p>This is some test content</p>
11
11
 
12
12
  </div>
13
+ <footer>
14
+ Copyright &copy; Testers Inc.
15
+ </footer>
16
+
13
17
  </body>
14
18
  </html>
@@ -0,0 +1 @@
1
+ Maybe we want to include a dotfile in our website? I don't know why, but we should copy these as well.
@@ -0,0 +1,2 @@
1
+ ---
2
+ name: Testers Inc.
@@ -0,0 +1 @@
1
+ footer Copyright &copy; #{name}
@@ -1,2 +1,4 @@
1
1
  .embedded
2
2
  | #{{content}}
3
+
4
+ == include 'footer', name: 'Special Corp Pty. Ltd.'
@@ -6,3 +6,5 @@ html
6
6
  body
7
7
  #content
8
8
  | #{{content}}
9
+
10
+ == include 'footer'
@@ -4,8 +4,13 @@ Feature:
4
4
  As a user
5
5
  I would like to generate a static website
6
6
 
7
+ Scenario:
8
+ When I run usmu with the arguments "init tmp"
9
+ Then the directory "tmp" should match "share/init-site"
10
+
11
+
7
12
  Scenario:
8
13
  Given I have a site at "test/site"
9
- When I generate the site
10
- Then the destination directory should match "test/expected-site"
14
+ When I run usmu with the arguments "generate"
15
+ Then the directory "test/site/site" should match "test/expected-site"
11
16
  And the modification time for the input file "index.md" should match the output file "index.html"
@@ -5,12 +5,17 @@ step 'I have a site at :location' do |location|
5
5
  @location = "#{location}/usmu.yml"
6
6
  end
7
7
 
8
- step 'I generate the site' do
9
- @site = Usmu::Ui::Console.new(['generate', '--config', @location])
8
+ step 'I run usmu with the arguments :args' do |args|
9
+ args = args.split(' ')
10
+ if @location
11
+ args << '--config' << @location
12
+ end
13
+ args << '--trace'
14
+ @site = Usmu::Ui::Console.new(args)
10
15
  end
11
16
 
12
- step 'the destination directory should match :test_folder' do |test_folder|
13
- run = %W{diff -qr #{@site.configuration.destination_path} #{test_folder}}
17
+ step 'the directory :destination should match :test_folder' do |destination, test_folder|
18
+ run = %W{diff -qr --strip-trailing-cr #{destination} #{test_folder}}
14
19
  Open3.popen2e(*run) do |i, o, t|
15
20
  output = run.join(' ') + "\n" + o.read
16
21
  fail output if t.value != 0
@@ -7,6 +7,7 @@ RSpec.describe Usmu::Configuration do
7
7
  'source' => 'source',
8
8
  'destination' => 'destination',
9
9
  'layouts' => 'templates',
10
+ 'includes' => 'includes',
10
11
  }
11
12
  @configuration = Usmu::Configuration.from_hash(hash, 'test/usmu.yaml')
12
13
  end
@@ -22,6 +23,10 @@ RSpec.describe Usmu::Configuration do
22
23
  it 'to layouts' do
23
24
  expect(@configuration.layouts_path).to eq('test/templates')
24
25
  end
26
+
27
+ it 'to includes' do
28
+ expect(@configuration.includes_path).to eq('test/includes')
29
+ end
25
30
  end
26
31
 
27
32
  context 'should have a default path' do
@@ -41,32 +46,48 @@ RSpec.describe Usmu::Configuration do
41
46
  it 'for layouts' do
42
47
  expect(@configuration.layouts_path).to eq('layouts')
43
48
  end
49
+
50
+ it 'for includes' do
51
+ expect(@configuration.includes_path).to eq('includes')
52
+ end
44
53
  end
45
54
 
46
55
  it 'should have a list of source files' do
47
56
  @configuration = Usmu::Configuration.from_hash({})
48
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/test.md))
57
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/test.md))
49
58
  expect(@configuration.source_files).to eq(%w(index.md test.md))
50
59
  end
51
60
 
52
61
  it 'should ignore metadata files in the source folder' do
53
62
  @configuration = Usmu::Configuration.from_hash({})
54
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/index.meta.yml src/test.md))
63
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/index.meta.yml src/test.md))
55
64
  expect(@configuration.source_files).to eq(%w(index.md test.md))
56
65
  end
57
66
 
58
67
  it 'should have a list of layouts files' do
59
68
  @configuration = Usmu::Configuration.from_hash({})
60
- allow(Dir).to receive(:'[]').with('layouts/**/*').and_return(%w(layouts/html.slim layouts/page.slim))
69
+ allow(Dir).to receive(:'[]').with('layouts/**/{*,.??*}').and_return(%w(layouts/html.slim layouts/page.slim))
61
70
  expect(@configuration.layouts_files).to eq(%w(html.slim page.slim))
62
71
  end
63
72
 
64
73
  it 'should ignore metadata files in the layouts folder' do
65
74
  @configuration = Usmu::Configuration.from_hash({})
66
- allow(Dir).to receive(:'[]').with('layouts/**/*').and_return(%w(layouts/html.slim layouts/html.meta.yml layouts/page.slim))
75
+ allow(Dir).to receive(:'[]').with('layouts/**/{*,.??*}').and_return(%w(layouts/html.slim layouts/html.meta.yml layouts/page.slim))
67
76
  expect(@configuration.layouts_files).to eq(%w(html.slim page.slim))
68
77
  end
69
78
 
79
+ it 'should have a list of includes files' do
80
+ @configuration = Usmu::Configuration.from_hash({})
81
+ allow(Dir).to receive(:'[]').with('includes/**/{*,.??*}').and_return(%w(includes/footer.slim))
82
+ expect(@configuration.includes_files).to eq(%w(footer.slim))
83
+ end
84
+
85
+ it 'should ignore metadata files in the includes folder' do
86
+ @configuration = Usmu::Configuration.from_hash({})
87
+ allow(Dir).to receive(:'[]').with('includes/**/{*,.??*}').and_return(%w(includes/footer.slim includes/footer.meta.yml))
88
+ expect(@configuration.includes_files).to eq(%w(footer.slim))
89
+ end
90
+
70
91
  it 'should remember arbitrary configuration' do
71
92
  configuration = Usmu::Configuration.from_hash({:test => 'foo'})
72
93
  expect(configuration[:test]).to eq('foo')
@@ -75,37 +96,37 @@ RSpec.describe Usmu::Configuration do
75
96
  context 'should exclude files from source' do
76
97
  it 'as specified' do
77
98
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['foo.md']})
78
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/foo.md))
99
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/foo.md))
79
100
  expect(@configuration.source_files).to eq(%w(index.md))
80
101
  end
81
102
 
82
103
  it 'in ignored folders if trailing "/" is used' do
83
104
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['test/']})
84
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/test/foo/test.md src/test/foo.md))
105
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/test/foo/test.md src/test/foo.md))
85
106
  expect(@configuration.source_files).to eq(%w(index.md))
86
107
  end
87
108
 
88
109
  it 'and honor *' do
89
110
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['*/foo.md']})
90
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/test/foo/foo.md src/test/foo.md))
111
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/test/foo/foo.md src/test/foo.md))
91
112
  expect(@configuration.source_files).to eq(%w(index.md test/foo/foo.md))
92
113
  end
93
114
 
94
115
  it 'and * ignores folders without a trailing /' do
95
116
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['*']})
96
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/test/foo.md src/test.md))
117
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/test/foo.md src/test.md))
97
118
  expect(@configuration.source_files).to eq(%w(test/foo.md))
98
119
  end
99
120
 
100
121
  it 'and honor **' do
101
122
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['**/foo.md']})
102
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/test/foo/foo.md src/test/foo.md))
123
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/test/foo/foo.md src/test/foo.md))
103
124
  expect(@configuration.source_files).to eq(%w(index.md))
104
125
  end
105
126
 
106
127
  it 'and honor []' do
107
128
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['[ab].md']})
108
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/a.md src/b.md))
129
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/a.md src/b.md))
109
130
  expect(@configuration.source_files).to eq(%w(index.md))
110
131
  end
111
132
 
@@ -114,26 +135,26 @@ RSpec.describe Usmu::Configuration do
114
135
  if defined?(File::FNM_EXTGLOB)
115
136
  it 'and honor {a,b}' do
116
137
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['{a,b}.md']})
117
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/a.md src/b.md))
138
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/a.md src/b.md))
118
139
  expect(@configuration.source_files).to eq(%w(index.md))
119
140
  end
120
141
  end
121
142
 
122
143
  it 'and honor \\ as an escape' do
123
144
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['\*.md']})
124
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/*.md))
145
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/*.md))
125
146
  expect(@configuration.source_files).to eq(%w(index.md))
126
147
  end
127
148
 
128
149
  it 'and honor ?' do
129
150
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['?.md']})
130
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/a.md src/b.md))
151
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/a.md src/b.md))
131
152
  expect(@configuration.source_files).to eq(%w(index.md))
132
153
  end
133
154
 
134
155
  it 'and ignore files inside folders specified via globs with trailing "/"' do
135
156
  @configuration = Usmu::Configuration.from_hash({'exclude' => ['test/*/']})
136
- allow(Dir).to receive(:'[]').with('src/**/*').and_return(%w(src/index.md src/test/foo/foo.md src/test/foo.md))
157
+ allow(Dir).to receive(:'[]').with('src/**/{*,.??*}').and_return(%w(src/index.md src/test/foo/foo.md src/test/foo.md))
137
158
  expect(@configuration.source_files).to eq(%w(index.md test/foo.md))
138
159
  end
139
160
  end