munge 0.4.0 → 0.5.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +10 -0
  4. data/Makefile +21 -0
  5. data/README.md +1 -1
  6. data/exe/munge +6 -0
  7. data/lib/munge/application.rb +11 -53
  8. data/lib/munge/bootstrap.rb +63 -0
  9. data/lib/munge/cli.rb +5 -17
  10. data/lib/munge/commands/view.rb +46 -0
  11. data/lib/munge/core/alterant.rb +2 -2
  12. data/lib/munge/core/collection.rb +1 -1
  13. data/lib/munge/core/item_factory/content_parser.rb +9 -13
  14. data/lib/munge/core/item_factory.rb +1 -24
  15. data/lib/munge/core/router/itemish.rb +22 -0
  16. data/lib/munge/core/router.rb +33 -42
  17. data/lib/munge/helper/capture.rb +24 -0
  18. data/lib/munge/helper/find.rb +4 -0
  19. data/lib/munge/helper/link.rb +6 -1
  20. data/lib/munge/helper/rendering.rb +0 -2
  21. data/lib/munge/item.rb +2 -2
  22. data/lib/munge/routers/add_index_html.rb +36 -0
  23. data/lib/munge/routers/auto_add_extension.rb +44 -0
  24. data/lib/munge/routers/fingerprint.rb +60 -0
  25. data/lib/munge/routers/remove_index_basename.rb +35 -0
  26. data/lib/munge/runner.rb +10 -6
  27. data/lib/munge/system.rb +54 -0
  28. data/lib/munge/transformer/tilt.rb +7 -3
  29. data/lib/munge/util/config.rb +28 -0
  30. data/lib/munge/util/path.rb +58 -0
  31. data/lib/munge/util/symbol_hash.rb +35 -0
  32. data/lib/munge/version.rb +1 -1
  33. data/lib/munge.rb +11 -4
  34. data/munge.gemspec +1 -0
  35. data/seeds/config.yml +1 -0
  36. data/seeds/data.yml +1 -0
  37. data/seeds/layouts/default.html.erb +5 -2
  38. data/seeds/layouts/sitemap.html.erb +6 -0
  39. data/seeds/rules.rb +19 -2
  40. data/seeds/setup.rb +15 -0
  41. data/seeds/src/_vars.scss +6 -0
  42. data/seeds/src/about.html.erb +11 -0
  43. data/seeds/src/basic.css.scss +41 -0
  44. data/seeds/src/index.html.erb +34 -0
  45. metadata +37 -7
  46. data/lib/munge/core/config.rb +0 -23
  47. data/lib/munge/helper.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 493a1b527391a30c807a1c358dda4c9854d1744f
4
- data.tar.gz: cc9fbb10a2e927e85074b46d7e232477ade37928
3
+ metadata.gz: f0ea780f903de0afaf329d50a2e81a69e14b8e4e
4
+ data.tar.gz: 53d5d6025748b56dbc3394b5080afa7ec107a954
5
5
  SHA512:
6
- metadata.gz: b4910b7a5825f85eeb970b4c2bc3b5699622f94d2085ad3dbeab5574531425d613fd5653adc5451988507a61b23c758e7a6c0d4f9ce6412591501ca63cbec5cb
7
- data.tar.gz: 5e85a223fb27596e2fecb3c78ea4860be786c47d272e3d8a0979d1b9b1a05707a580e5b069cf0bde57f1ea14f792f4114af117397061706062e99af585d43a63
6
+ metadata.gz: ec154947682821e309c2d781bf7de1692e86c78bbb6f9236d3b46264ee49fcfbd94ea84ce214f6bb09754c81e9507a570265a22212f2e3f637c97433ffbb5914
7
+ data.tar.gz: 98d471dcfae5960316b92ac17cd4aa9e078d984a74091cfc687b3c4c435ee561f51e1f641efb1e8f6380d8374eb59cb65c84fb5806206580ba99cf830c1a4451
data/.gitignore CHANGED
@@ -7,3 +7,6 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+
11
+ /seeds/dest
12
+ .sass-cache
data/.rubocop.yml CHANGED
@@ -13,6 +13,10 @@ Metrics/MethodLength:
13
13
  Exclude:
14
14
  - test/**/*
15
15
 
16
+ Metrics/ClassLength:
17
+ Exclude:
18
+ - test/**/*
19
+
16
20
  Style/AlignParameters:
17
21
  Enabled: false
18
22
 
@@ -22,8 +26,14 @@ Style/Documentation:
22
26
  Style/ClassAndModuleChildren:
23
27
  Enabled: false
24
28
 
29
+ Style/GuardClause:
30
+ Enabled: false
31
+
25
32
  Style/IfUnlessModifier:
26
33
  Enabled: false
27
34
 
35
+ Style/MultilineOperationIndentation:
36
+ EnforcedStyle: indented
37
+
28
38
  Style/StringLiterals:
29
39
  EnforcedStyle: double_quotes
data/Makefile ADDED
@@ -0,0 +1,21 @@
1
+ .PHONY: all test testc openc release
2
+
3
+ all:
4
+ @echo "usage:"
5
+ @echo
6
+ @echo "make test runs tests"
7
+ @echo "make testc runs tests and logs coverage"
8
+ @echo "make openc starts webserver in coverage directory"
9
+ @echo "make release releases gem (dangerous)"
10
+
11
+ test:
12
+ script/test
13
+
14
+ testc:
15
+ COVERAGE=1 script/test
16
+
17
+ openc:
18
+ cd coverage && adsf
19
+
20
+ release:
21
+ bundle exec rake release
data/README.md CHANGED
@@ -50,7 +50,7 @@ After installing your gem, you can start a project using the command line client
50
50
  munge init path/to/project # create a barebones project
51
51
  cd path/to/project
52
52
  munge build # compiles your project
53
- munge view # open http://localhost:3000/ to see output
53
+ munge view # open http://localhost:7000/ to see output
54
54
  ```
55
55
 
56
56
  The three main files of your application are `config.yml`, `data.yml`, and `rules.rb`.
data/exe/munge CHANGED
@@ -1,4 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
+
3
+ if File.exist?(File.expand_path("../../.git", __FILE__))
4
+ lib = File.expand_path("../../lib", __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ end
7
+
2
8
  require "munge"
3
9
  require "munge/cli"
4
10
 
@@ -1,77 +1,35 @@
1
1
  module Munge
2
2
  class Application
3
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
4
- def initialize(config_path)
5
- config = Core::Config.new(config_path)
6
-
7
- root_path = File.dirname(File.expand_path(config_path))
8
- source_path = File.expand_path(config[:source], root_path)
9
- layouts_path = File.expand_path(config[:layouts], root_path)
10
- output_path = File.expand_path(config[:output], root_path)
11
- data_path = File.expand_path(config[:data], root_path)
12
-
13
- @global_data = YAML.load_file(data_path) || {}
14
-
15
- @item_factory =
16
- Core::ItemFactory.new(
17
- text_extensions: config[:text_extensions],
18
- ignored_basenames: config[:ignored_basenames]
19
- )
20
-
21
- @source =
22
- Core::Collection.new(
23
- item_factory: @item_factory,
24
- items: Reader::Filesystem.new(source_path)
25
- )
26
-
27
- @layouts =
28
- Core::Collection.new(
29
- item_factory: @item_factory,
30
- items: Reader::Filesystem.new(layouts_path)
31
- )
32
-
33
- @router =
34
- Core::Router.new(
35
- index: config[:index],
36
- keep_extensions: config[:keep_extensions]
37
- )
38
-
39
- @alterant =
40
- Core::Alterant.new(scope: self)
41
-
42
- @writer =
43
- Core::Write.new(
44
- output: output_path
45
- )
46
-
47
- @alterant.register(Transformer::Tilt.new(self))
3
+ def initialize(system)
4
+ @system = system
48
5
  end
49
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
50
6
 
51
- attr_reader :source
7
+ def source
8
+ @system.source
9
+ end
52
10
 
53
11
  def write(&block)
54
- @source
12
+ @system.source
55
13
  .reject { |item| item.route.nil? }
56
14
  .each { |item| render_and_write(item, &block) }
57
15
  end
58
16
 
59
17
  def build_virtual_item(*args)
60
- @source.build(*args)
18
+ @system.source.build(*args)
61
19
  end
62
20
 
63
- def create(*args, &block)
21
+ def create(*args)
64
22
  item = build_virtual_item(*args)
65
23
  yield item if block_given?
66
- @source.push(item)
24
+ @system.source.push(item)
67
25
  end
68
26
 
69
27
  private
70
28
 
71
29
  def render_and_write(item, &block)
72
- relpath = @router.filepath(item)
30
+ relpath = @system.router.filepath(item)
73
31
 
74
- write_status = @writer.write(relpath, @alterant.transform(item))
32
+ write_status = @system.writer.write(relpath, @system.alterant.transform(item))
75
33
 
76
34
  if block_given?
77
35
  block.call(item, write_status)
@@ -0,0 +1,63 @@
1
+ module Munge
2
+ class Bootstrap
3
+ class << self
4
+ def new_from_dir(root_path:)
5
+ new_from_fs(
6
+ root_path: root_path,
7
+ config_path: config_path(root_path),
8
+ setup_path: setup_path(root_path),
9
+ rules_path: rules_path(root_path)
10
+ )
11
+ end
12
+
13
+ def new_from_fs(root_path:,
14
+ config_path:,
15
+ setup_path:,
16
+ rules_path:)
17
+ new(
18
+ root_path: root_path,
19
+ config: read_config(config_path),
20
+ setup_string: File.read(setup_path),
21
+ setup_path: setup_path,
22
+ rules_string: File.read(rules_path),
23
+ rules_path: rules_path
24
+ )
25
+ end
26
+
27
+ private
28
+
29
+ def read_config(config_path)
30
+ Munge::Util::Config.read(config_path)
31
+ end
32
+
33
+ def config_path(root_path)
34
+ File.join(root_path, "config.yml")
35
+ end
36
+
37
+ def setup_path(root_path)
38
+ File.join(root_path, "setup.rb")
39
+ end
40
+
41
+ def rules_path(root_path)
42
+ File.join(root_path, "rules.rb")
43
+ end
44
+ end
45
+
46
+ def initialize(root_path:,
47
+ config:,
48
+ setup_string:,
49
+ rules_string:,
50
+ setup_path:,
51
+ rules_path:)
52
+ system = Munge::System.new(root_path, config)
53
+
54
+ binding.eval(setup_string, setup_path)
55
+
56
+ @app = Munge::Application.new(system)
57
+
58
+ binding.eval(rules_string, rules_path)
59
+ end
60
+
61
+ attr_reader :app
62
+ end
63
+ end
data/lib/munge/cli.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require "thor"
2
2
 
3
+ require_relative "commands/view"
4
+
3
5
  module Munge
4
6
  class CLI < Thor
5
7
  include Thor::Actions
@@ -15,28 +17,14 @@ module Munge
15
17
 
16
18
  desc "build", "Build in current directory"
17
19
  def build
18
- Munge::Runner.write(config_path, rules_path)
20
+ Munge::Runner.write(destination_root)
19
21
  end
20
22
 
21
23
  desc "view", "View built files"
22
- method_option :port, aliases: "-p", desc: "Set port", default: 3000, type: :numeric
24
+ method_option :port, aliases: "-p", desc: "Set port", default: 7000, type: :numeric
23
25
  method_option :host, aliases: "-h", desc: "Set host", default: "0.0.0.0", type: :string
24
26
  def view
25
- config = Munge::Core::Config.new(config_path)
26
- handler = Rack::Handler::WEBrick
27
- rack_opts = { Host: options[:host], Port: options[:port] }
28
-
29
- app =
30
- Rack::Builder.new do
31
- use Rack::CommonLogger
32
- use Rack::ShowExceptions
33
- use Rack::Lint
34
- use Rack::Head
35
- use Adsf::Rack::IndexFileFinder, root: config[:output]
36
- run Rack::File.new(config[:output])
37
- end
38
-
39
- Rack::Handler::WEBrick.run(app, rack_opts)
27
+ Munge::Commands::View.new(options, config_path)
40
28
  end
41
29
 
42
30
  desc "version", "Print version"
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2007-2015 Denis Defreyne and contributors
2
+ # Copyright (c) 2015 Zach Ahn
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ # SOFTWARE.
21
+ #
22
+ # https://github.com/nanoc/nanoc/blob/fdf8b28/lib/nanoc/cli/commands/view.rb#L17-L53
23
+
24
+ require "adsf"
25
+ require "rack"
26
+
27
+ module Munge
28
+ class Commands
29
+ class View
30
+ def initialize(options, config_path)
31
+ config = Munge::Util::Config.read(config_path)
32
+ rack_opts = { Host: options[:host], Port: options[:port] }
33
+
34
+ app =
35
+ Rack::Builder.new do
36
+ use Rack::ShowExceptions
37
+ use Rack::Head
38
+ use Adsf::Rack::IndexFileFinder, root: config[:output]
39
+ run Rack::File.new(config[:output])
40
+ end
41
+
42
+ Rack::Handler::WEBrick.run(app, rack_opts)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -12,7 +12,7 @@ module Munge
12
12
 
13
13
  # name should be snake_case Symbol
14
14
  def register_manually(name, transformer)
15
- if @registry.has_key?(name)
15
+ if @registry.key?(name)
16
16
  fail "already registered transformer `#{name}`"
17
17
  else
18
18
  @registry[name] = transformer
@@ -32,7 +32,7 @@ module Munge
32
32
  private
33
33
 
34
34
  def get_transformer(name)
35
- if @registry.has_key?(name)
35
+ if @registry.key?(name)
36
36
  @registry[name]
37
37
  else
38
38
  fail "transformer `#{name}` is not installed"
@@ -42,7 +42,7 @@ module Munge
42
42
  private
43
43
 
44
44
  def prune_args(args)
45
- args.select { |k, v| %i(relpath content frontmatter stat).include?(k) }
45
+ args.select { |k, _| %i(relpath content frontmatter stat).include?(k) }
46
46
  end
47
47
  end
48
48
  end
@@ -29,11 +29,14 @@ module Munge
29
29
 
30
30
  parsed_frontmatter = YAML.load(matchdata[1])
31
31
 
32
- if parsed_frontmatter
33
- parsed_frontmatter
34
- else
35
- {}
36
- end
32
+ frontmatter_hash =
33
+ if parsed_frontmatter.is_a?(Hash)
34
+ parsed_frontmatter
35
+ else
36
+ {}
37
+ end
38
+
39
+ Munge::Util::SymbolHash.deep_convert(frontmatter_hash)
37
40
  end
38
41
 
39
42
  def self.parse_content(matchdata, string)
@@ -44,15 +47,8 @@ module Munge
44
47
  end
45
48
  end
46
49
 
47
- def initialize(string, frontmatter = nil)
50
+ def initialize(string)
48
51
  @frontmatter, @content = self.class.parse(string)
49
-
50
- if frontmatter
51
- @frontmatter = @frontmatter.merge(frontmatter)
52
- end
53
- rescue ArgumentError
54
- @frontmatter = frontmatter || {}
55
- @content = string
56
52
  end
57
53
 
58
54
  attr_accessor :frontmatter, :content
@@ -58,18 +58,6 @@ module Munge
58
58
 
59
59
  private
60
60
 
61
- def compute_content_and_frontmatter(abspath)
62
- case @location
63
- when :fs_memory
64
- content = Munge::Attribute::Content.new(File.read(abspath))
65
- [content.content, content.frontmatter]
66
- when :fs, :virtual
67
- ["", {}]
68
- else
69
- fail "invalid @location `#{@location}`"
70
- end
71
- end
72
-
73
61
  def file_extensions(filepath)
74
62
  extensions = File.basename(filepath).split(".")[1..-1]
75
63
  Set.new(extensions)
@@ -85,17 +73,6 @@ module Munge
85
73
  end
86
74
  end
87
75
 
88
- def compute_relpath(abspath)
89
- folder = Pathname.new(@source_path)
90
- file = Pathname.new(abspath)
91
-
92
- file.relative_path_from(folder).to_s
93
- end
94
-
95
- def compute_stat(abspath)
96
- File.stat(abspath)
97
- end
98
-
99
76
  def compute_id(relpath)
100
77
  dirname = compute_dirname(relpath)
101
78
  basename = compute_basename(relpath)
@@ -114,7 +91,7 @@ module Munge
114
91
  end
115
92
 
116
93
  def compute_dirname(relpath)
117
- dirname = File.dirname(relpath)
94
+ File.dirname(relpath)
118
95
  end
119
96
 
120
97
  def compute_basename(relpath)
@@ -0,0 +1,22 @@
1
+ module Munge
2
+ module Core
3
+ class Router
4
+ class Itemish
5
+ extend Forwardable
6
+
7
+ def initialize(item, alterant)
8
+ @item = item
9
+ @alterant = alterant
10
+ end
11
+
12
+ def compiled_content
13
+ @compiled_content ||= @alterant.transform(@item)
14
+ end
15
+
16
+ def_delegators :@item, *%i(type relpath id frontmatter stat layout)
17
+ def_delegators :@item, *%i(dirname filename basename extensions)
18
+ def_delegators :@item, *%i(relpath? route?)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,62 +1,53 @@
1
+ require_relative "router/itemish"
2
+
1
3
  module Munge
2
4
  module Core
3
5
  class Router
4
- def initialize(index:, keep_extensions:)
5
- @index = index
6
- @keep_extensions = keep_extensions
6
+ def initialize(alterant:)
7
+ @registries = { route: [], filepath: [] }
8
+ @alterant = alterant
7
9
  end
8
10
 
9
- def route(item)
10
- fail "item has no route" unless item.route
11
-
12
- if keep_extension?(item)
13
- "/#{filepath(item)}"
11
+ def register(router)
12
+ case router.type
13
+ when :route
14
+ @registries[:route].push(router)
15
+ when :filepath
16
+ @registries[:filepath].push(router)
14
17
  else
15
- item.route
18
+ fail "invalid router"
16
19
  end
17
20
  end
18
21
 
19
- def filepath(item)
20
- fail "item has no route" unless item.route
21
-
22
- relroute = relativeize(item.route)
23
-
24
- path =
25
- if route_has_extension?(item)
26
- "#{relroute}"
27
- elsif keep_extension?(item)
28
- "#{relroute}.#{main_extension(item)}"
29
- else
30
- "#{relroute}/#{@index}"
31
- end
22
+ def route(item)
23
+ path = route_mapper(item, :route)
24
+ Util::Path.ensure_abspath(path)
25
+ end
32
26
 
33
- relativeize(path)
27
+ def filepath(item)
28
+ initial_route = route(item)
29
+ path = route_mapper(item, :filepath, initial_route)
30
+ Util::Path.ensure_relpath(path)
34
31
  end
35
32
 
36
33
  private
37
34
 
38
- def relativeize(path)
39
- while path[0] == "/"
40
- path = path[1..-1]
35
+ def route_mapper(item, method_name, initial_route = nil)
36
+ if !item.route && !initial_route
37
+ fail "item has no route"
41
38
  end
42
39
 
43
- path
44
- end
40
+ itemish = Itemish.new(item, @alterant)
45
41
 
46
- def route_has_extension?(item)
47
- route_basename(item) =~ /\./
48
- end
49
-
50
- def keep_extension?(item)
51
- @keep_extensions.include?(main_extension(item))
52
- end
53
-
54
- def main_extension(item)
55
- item.extensions.first
56
- end
57
-
58
- def route_basename(item)
59
- File.basename(item.route)
42
+ @registries[method_name]
43
+ .select { |router| router.type == method_name }
44
+ .inject(initial_route || item.route) do |route, router|
45
+ if router.match?(route, itemish)
46
+ router.call(route, itemish)
47
+ else
48
+ route
49
+ end
50
+ end
60
51
  end
61
52
  end
62
53
  end
@@ -0,0 +1,24 @@
1
+ module Munge
2
+ module Helper
3
+ module Capture
4
+ def capture(&block)
5
+ original_erbout = block.binding.local_variable_get(:_erbout)
6
+ block.binding.local_variable_set(:_erbout, "")
7
+
8
+ captured_text = block.call
9
+
10
+ block.binding.local_variable_set(:_erbout, original_erbout)
11
+
12
+ captured_text
13
+ end
14
+
15
+ def append_to_erbout(block_binding, text)
16
+ original_erbout = block_binding.local_variable_get(:_erbout)
17
+
18
+ updated_erbout = original_erbout + text
19
+
20
+ block_binding.local_variable_set(:_erbout, updated_erbout)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -4,6 +4,10 @@ module Munge
4
4
  def items
5
5
  @source
6
6
  end
7
+
8
+ def layouts
9
+ @layouts
10
+ end
7
11
  end
8
12
  end
9
13
  end
@@ -5,9 +5,14 @@ module Munge
5
5
  @router.route(item)
6
6
  end
7
7
 
8
- def link_to(item, text = nil, **opts)
8
+ def link_to(item, text = nil, opts = {})
9
9
  link = url_for(item)
10
10
 
11
+ if text.is_a?(Hash)
12
+ opts = text
13
+ text = nil
14
+ end
15
+
11
16
  optstr = opts.map { |key, val| %(#{key}="#{val}") }
12
17
 
13
18
  parts =
@@ -21,8 +21,6 @@ module Munge
21
21
  inner =
22
22
  if block_given?
23
23
  yield
24
- else
25
- nil
26
24
  end
27
25
 
28
26
  engines
data/lib/munge/item.rb CHANGED
@@ -91,8 +91,8 @@ module Munge
91
91
 
92
92
  def remove_surrounding_slashes(string)
93
93
  string
94
- .sub(%r(^/+), "")
95
- .sub(%r(/+$), "")
94
+ .sub(%r{^/+}, "")
95
+ .sub(%r{/+$}, "")
96
96
  end
97
97
  end
98
98
  end
@@ -0,0 +1,36 @@
1
+ module Munge
2
+ module Router
3
+ class AddIndexHtml
4
+ def initialize(html_extensions:, index:)
5
+ @html_extensions = html_extensions
6
+ @index = index
7
+ end
8
+
9
+ def type
10
+ :filepath
11
+ end
12
+
13
+ def match?(initial_route, item)
14
+ item_is_html?(item) && route_needs_extension?(initial_route)
15
+ end
16
+
17
+ def call(initial_route, _item)
18
+ File.join(initial_route, @index)
19
+ end
20
+
21
+ private
22
+
23
+ def item_is_html?(item)
24
+ intersection = item.extensions & @html_extensions
25
+
26
+ intersection.length > 0
27
+ end
28
+
29
+ def route_needs_extension?(route)
30
+ basename = File.basename(route)
31
+
32
+ !basename.include?(".")
33
+ end
34
+ end
35
+ end
36
+ end