munge 0.17.0 → 0.18.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/munge/application.rb +1 -1
  3. data/lib/munge/cleaner.rb +31 -0
  4. data/lib/munge/cli/commands/build.rb +13 -11
  5. data/lib/munge/cli/commands/clean.rb +61 -0
  6. data/lib/munge/cli/commands/server.rb +28 -8
  7. data/lib/munge/cli/commands/view.rb +3 -3
  8. data/lib/munge/cli/dispatch.rb +25 -5
  9. data/lib/munge/cli.rb +2 -0
  10. data/lib/munge/config.rb +2 -2
  11. data/lib/munge/extras/livereload/server.rb +4 -2
  12. data/lib/munge/formatters/default.rb +3 -3
  13. data/lib/munge/formatters/silent.rb +14 -0
  14. data/lib/munge/go/sass/asset_urls.rb +24 -22
  15. data/lib/munge/helpers/asset_tags.rb +2 -2
  16. data/lib/munge/helpers/rendering.rb +5 -5
  17. data/lib/munge/init.rb +2 -2
  18. data/lib/munge/io/dry_run.rb +31 -0
  19. data/lib/munge/{writers → io}/filesystem.rb +21 -1
  20. data/lib/munge/{writers → io}/noop.rb +15 -1
  21. data/lib/munge/item.rb +19 -8
  22. data/lib/munge/routers/auto_add_extension.rb +1 -1
  23. data/lib/munge/routers/fingerprint.rb +3 -3
  24. data/lib/munge/runner.rb +36 -15
  25. data/lib/munge/system/collection.rb +2 -8
  26. data/lib/munge/system/item_factory/item_identifier.rb +3 -3
  27. data/lib/munge/system/readers/filesystem.rb +1 -1
  28. data/lib/munge/system/router/itemish.rb +1 -1
  29. data/lib/munge/system.rb +10 -14
  30. data/lib/munge/version.rb +1 -1
  31. data/lib/munge/write_manager/all.rb +27 -0
  32. data/lib/munge/write_manager/only_needed.rb +25 -0
  33. data/lib/munge.rb +6 -3
  34. data/seeds/config.rb +1 -2
  35. data/seeds/layouts/blog.html.erb +1 -1
  36. data/seeds/layouts/blog_archives.html.erb +1 -1
  37. data/seeds/layouts/blog_index.html.erb +1 -1
  38. data/seeds/layouts/blog_show.html.erb +1 -1
  39. data/seeds/rules.rb +17 -18
  40. metadata +12 -7
  41. data/lib/munge/write_manager.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 94019c2c419a44b2c4be2aca94cbc587e7875439
4
- data.tar.gz: b8113ced2804eb5b33093ba9a33da97324fbbb7a
3
+ metadata.gz: 6789b26f5adfbb4e63f7765b893eb1e76d9b2cb4
4
+ data.tar.gz: 2b3aa5cdebf2d78b0bb5af87c17cbe198438b04f
5
5
  SHA512:
6
- metadata.gz: a75c4565e8cf70ca137a5516b5d320300dc51d181f28fa5c18b69c68aee7fe2e0d9f86a353c152b89552a1979a85059fb7025279e1aada0e2150597d1ed51d51
7
- data.tar.gz: b1a255bde2c32b711c5751261a5eb2c5545a5f3aeb1e433c151059fb8549d9202eeb3a157b2cc0733caf54679de8a79f8d8c396d4f748248cfb7acfde75ba943
6
+ metadata.gz: fd0195d991650cc4d4fc0b149db88b5f844a15e77f19b948accf22fb8f4bd23d2f97cb8a145d776395d6df46595442f1cafb015c242ca872159addf165ccfd17
7
+ data.tar.gz: 78d5a5efdc0e9b2b97ad70daf23689855b8d04389e7c82bcbd0211a79e08e812d8e03a3fc12eef50b4cfcdb2beb2903868b7f3adb6a8611d588c6a4fa113f02b
@@ -25,7 +25,7 @@ module Munge
25
25
  #
26
26
  # @return [Item]
27
27
  def build_virtual_item(relpath, content, **frontmatter)
28
- @system.items.build(relpath: relpath, content: content, frontmatter: frontmatter)
28
+ @system.item_factory.build(relpath: relpath, content: content, frontmatter: frontmatter)
29
29
  end
30
30
 
31
31
  # Creates an Item and inserts it into the registry of Items.
@@ -0,0 +1,31 @@
1
+ module Munge
2
+ class Cleaner
3
+ def initialize(path_to_clean:, paths_to_write:, io:)
4
+ @path_to_clean = path_to_clean
5
+ @paths_to_write = paths_to_write
6
+ @io = io
7
+ end
8
+
9
+ def orphans
10
+ existing_files - @paths_to_write
11
+ end
12
+
13
+ def delete
14
+ orphans.each { |orphan| @io.rm(orphan) }
15
+
16
+ Dir.glob(File.join(@path_to_clean, "**", "*")).reverse_each do |dir|
17
+ if !File.directory?(dir)
18
+ next
19
+ end
20
+
21
+ @io.rmdir(dir)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def existing_files
28
+ Dir.glob(File.join(@path_to_clean, "**", "*")).select { |path| File.file?(path) }
29
+ end
30
+ end
31
+ end
@@ -9,19 +9,21 @@ module Munge
9
9
  # @param build_root [String, nil]
10
10
  def initialize(bootloader, dry_run:, reporter:, verbosity:, build_root: nil)
11
11
  destination_root = bootloader.root_path
12
- config = bootloader.config
13
- app = application(bootloader)
14
- destination = File.expand_path(build_root || config[:output_path], destination_root)
12
+ config = bootloader.config
13
+ app = application(bootloader)
14
+ destination = File.expand_path(build_root || config[:output_path], destination_root)
15
+
16
+ io = new_io(dry_run)
15
17
 
16
18
  @runner =
17
19
  Munge::Runner.new(
18
20
  items: app.vomit(:items),
19
21
  router: app.vomit(:router),
20
22
  processor: app.vomit(:processor),
21
- writer: writer(dry_run),
22
- formatter: formatter(reporter),
23
- verbosity: verbosity.to_sym,
24
- destination: destination
23
+ io: io,
24
+ reporter: Munge::Reporter.new(formatter: new_formatter(reporter), verbosity: verbosity.to_sym),
25
+ destination: destination,
26
+ manager: Munge::WriteManager::OnlyNeeded.new(io)
25
27
  )
26
28
  end
27
29
 
@@ -38,15 +40,15 @@ module Munge
38
40
  bootstrap.app
39
41
  end
40
42
 
41
- def writer(dry_run)
43
+ def new_io(dry_run)
42
44
  if dry_run
43
- Munge::Writers::Noop.new
45
+ Munge::Io::DryRun.new(Munge::Io::Filesystem.new)
44
46
  else
45
- Munge::Writers::Filesystem.new
47
+ Munge::Io::Filesystem.new
46
48
  end
47
49
  end
48
50
 
49
- def formatter(class_name)
51
+ def new_formatter(class_name)
50
52
  Munge::Formatters.const_get(class_name).new
51
53
  end
52
54
  end
@@ -0,0 +1,61 @@
1
+ module Munge
2
+ module Cli
3
+ module Commands
4
+ # This class is used by the CLI to build and calculate output
5
+ class Clean
6
+ def initialize(bootloader, dry_run:, reporter:, verbosity:, build_root: nil)
7
+ destination_root = bootloader.root_path
8
+ config = bootloader.config
9
+ app = application(bootloader)
10
+ destination = File.expand_path(build_root || config[:output_path], destination_root)
11
+ @dry_run = dry_run
12
+
13
+ io = Munge::Io::DryRun.new(Munge::Io::Filesystem.new)
14
+
15
+ @runner =
16
+ Munge::Runner.new(
17
+ items: app.vomit(:items),
18
+ router: app.vomit(:router),
19
+ processor: app.vomit(:processor),
20
+ io: io,
21
+ reporter: Munge::Reporter.new(formatter: formatter("Silent"), verbosity: :silent),
22
+ destination: destination,
23
+ manager: Munge::WriteManager::All.new(io)
24
+ )
25
+
26
+ @output_path = File.expand_path(build_root || config[:output_path], destination_root)
27
+ end
28
+
29
+ def call
30
+ io =
31
+ if @dry_run
32
+ Munge::Io::DryRun.new(Munge::Io::Filesystem.new)
33
+ else
34
+ Munge::Io::Filesystem.new
35
+ end
36
+
37
+ cleaner =
38
+ Munge::Cleaner.new(
39
+ path_to_clean: @output_path,
40
+ paths_to_write: @runner.write,
41
+ io: io
42
+ )
43
+
44
+ cleaner.delete
45
+ end
46
+
47
+ private
48
+
49
+ def application(bootloader)
50
+ bootstrap = bootloader.init
51
+
52
+ bootstrap.app
53
+ end
54
+
55
+ def formatter(class_name)
56
+ Munge::Formatters.const_get(class_name).new
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -2,9 +2,11 @@ module Munge
2
2
  module Cli
3
3
  module Commands
4
4
  class Server
5
- def initialize(bootloader, livereload:)
5
+ def initialize(bootloader, livereload:, host:, port:)
6
6
  @bootloader = bootloader
7
7
  @listener = listener
8
+ @view_host = host
9
+ @view_port = port
8
10
  @livereload =
9
11
  if livereload
10
12
  if Gem.loaded_specs.key?("reel")
@@ -23,7 +25,7 @@ module Munge
23
25
 
24
26
  munge_build
25
27
 
26
- system("munge view")
28
+ munge_view
27
29
  rescue Interrupt
28
30
  @listener.stop
29
31
  end
@@ -34,9 +36,14 @@ module Munge
34
36
  require "listen"
35
37
 
36
38
  listen = Listen.to(@bootloader.root_path) do
37
- built_files = munge_build
39
+ begin
40
+ built_files = munge_build
38
41
 
39
- @livereload.notify_changes(files: built_files)
42
+ @livereload.notify_changes(files: built_files)
43
+ rescue => e
44
+ puts "ERROR: #{e.message}"
45
+ puts e.backtrace.map { |line| "\t" + line }.join("\n")
46
+ end
40
47
 
41
48
  GC.start
42
49
  end
@@ -55,12 +62,9 @@ module Munge
55
62
  end
56
63
 
57
64
  def munge_build
58
- bootloader =
59
- Munge::Bootloader.new(root_path: @bootloader.root_path)
60
-
61
65
  build_command =
62
66
  Munge::Cli::Commands::Build.new(
63
- bootloader,
67
+ new_bootloader,
64
68
  dry_run: false,
65
69
  reporter: "Default",
66
70
  verbosity: "written",
@@ -69,6 +73,22 @@ module Munge
69
73
 
70
74
  build_command.call
71
75
  end
76
+
77
+ def munge_view
78
+ view_command =
79
+ Munge::Cli::Commands::View.new(
80
+ new_bootloader,
81
+ host: @view_host,
82
+ port: @view_port,
83
+ build_root: ENV["BUILD_ROOT"]
84
+ )
85
+
86
+ view_command.call
87
+ end
88
+
89
+ def new_bootloader
90
+ Munge::Bootloader.new(root_path: @bootloader.root_path)
91
+ end
72
92
  end
73
93
  end
74
94
  end
@@ -35,9 +35,9 @@ module Munge
35
35
  # @param build_root [String, nil]
36
36
  def initialize(bootloader, host:, port:, build_root: nil)
37
37
  config = bootloader.config
38
- @host = host
39
- @port = port
40
- root = File.expand_path(build_root || config[:output_path], bootloader.root_path)
38
+ @host = host
39
+ @port = port
40
+ root = File.expand_path(build_root || config[:output_path], bootloader.root_path)
41
41
 
42
42
  @app =
43
43
  Rack::Builder.new do
@@ -12,7 +12,7 @@ module Munge
12
12
  method_option :dry_run, desc: "Run without writing files", default: false, type: :boolean
13
13
  method_option :verbosity, aliases: "-v", desc: "Preferred amount of output", enum: %w(all written silent), default: "written", type: :string
14
14
  def build
15
- ENV["MUNGE_ENV"] ||= "production"
15
+ production!
16
16
 
17
17
  Commands::Build.new(bootloader, **symbolized_options, build_root: ENV["BUILD_ROOT"]).call
18
18
  end
@@ -21,23 +21,34 @@ module Munge
21
21
  method_option :port, aliases: "-p", desc: "Set port", default: 7000, type: :numeric
22
22
  method_option :host, aliases: "-h", desc: "Set host", default: "0.0.0.0", type: :string
23
23
  def view
24
- ENV["MUNGE_ENV"] ||= "production"
24
+ production!
25
25
 
26
26
  Commands::View.new(bootloader, **symbolized_options, build_root: ENV["BUILD_ROOT"]).call
27
27
  end
28
28
 
29
29
  desc "server", "Run the development server"
30
30
  method_option :livereload, desc: "Reload browser on update", default: Gem.loaded_specs.key?("reel"), type: :boolean
31
+ method_option :port, aliases: "-p", desc: "Set port", default: 7000, type: :numeric
32
+ method_option :host, aliases: "-h", desc: "Set host", default: "0.0.0.0", type: :string
31
33
  def server
32
- ENV["MUNGE_ENV"] ||= "development"
33
- ENV["BUILD_ROOT"] ||= "tmp/development-build"
34
+ development!
34
35
 
35
36
  Commands::Server.new(bootloader, **symbolized_options).call
36
37
  end
37
38
 
39
+ desc "clean", "Remove old built files (generally unnecessary)"
40
+ method_option :reporter, desc: "Set reporting formatter", default: "Default", type: :string
41
+ method_option :dry_run, desc: "Run without writing files", default: false, type: :boolean
42
+ method_option :verbosity, aliases: "-v", desc: "Preferred amount of output", enum: %w(all written silent), default: "written", type: :string
43
+ def clean
44
+ production!
45
+
46
+ Commands::Clean.new(bootloader, **symbolized_options, build_root: ENV["BUILD_ROOT"]).call
47
+ end
48
+
38
49
  desc "update", "Use with caution: override local configs with pristine version (useful after bumping version in Gemfile)"
39
50
  def update
40
- ENV["MUNGE_ENV"] ||= "development"
51
+ development!
41
52
 
42
53
  Commands::Update.new(bootloader, current_working_directory).call
43
54
  end
@@ -64,6 +75,15 @@ module Munge
64
75
  def symbolized_options
65
76
  Munge::Util::SymbolHash.deep_convert(options)
66
77
  end
78
+
79
+ def production!
80
+ ENV["MUNGE_ENV"] ||= "production"
81
+ end
82
+
83
+ def development!
84
+ ENV["MUNGE_ENV"] ||= "development"
85
+ ENV["BUILD_ROOT"] ||= "tmp/development-build"
86
+ end
67
87
  end
68
88
  end
69
89
  end
data/lib/munge/cli.rb CHANGED
@@ -5,8 +5,10 @@ require "munge/cli/commands/init"
5
5
  require "munge/cli/commands/build"
6
6
  require "munge/cli/commands/view"
7
7
  require "munge/cli/commands/server"
8
+ require "munge/cli/commands/clean"
8
9
  require "munge/cli/commands/update"
9
10
  require "munge/cli/dispatch"
10
11
 
11
12
  require "munge/formatters/default"
12
13
  require "munge/formatters/dots"
14
+ require "munge/formatters/silent"
data/lib/munge/config.rb CHANGED
@@ -10,7 +10,7 @@ module Munge
10
10
  if @configs.key?(sym_key)
11
11
  @configs[sym_key]
12
12
  else
13
- raise Munge::Errors::ConfigKeyNotFound, sym_key
13
+ raise Errors::ConfigKeyNotFound, sym_key
14
14
  end
15
15
  end
16
16
 
@@ -28,7 +28,7 @@ module Munge
28
28
  elsif key?(method_name)
29
29
  self[method_name]
30
30
  else
31
- super
31
+ raise Errors::ConfigKeyNotFound, method_name
32
32
  end
33
33
  end
34
34
 
@@ -10,13 +10,15 @@ module Munge
10
10
  end
11
11
 
12
12
  def notify_reload(changed_files)
13
- @sockets.each do |socket|
13
+ @sockets.select! do |socket|
14
14
  begin
15
15
  changed_files.each do |file|
16
16
  socket << @messaging.reload(file)
17
17
  end
18
+
19
+ true
18
20
  rescue Reel::SocketError
19
- print_error("error pushing livereload notification to browser")
21
+ false
20
22
  end
21
23
  end
22
24
  end
@@ -2,10 +2,10 @@ module Munge
2
2
  module Formatters
3
3
  class Default
4
4
  def initialize
5
- @new_count = 0
6
- @changed_count = 0
5
+ @new_count = 0
6
+ @changed_count = 0
7
7
  @identical_count = 0
8
- @reported_count = 0
8
+ @reported_count = 0
9
9
  end
10
10
 
11
11
  def call(_item, relpath, write_status, should_print)
@@ -0,0 +1,14 @@
1
+ module Munge
2
+ module Formatters
3
+ class Silent
4
+ def call(_item, _relpath, _write_status, _should_print)
5
+ end
6
+
7
+ def start
8
+ end
9
+
10
+ def done
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,25 +1,4 @@
1
1
  module Sass::Script::Functions
2
- def stringify_string(stringish)
3
- if stringish.instance_of?(::String)
4
- stringish
5
- else
6
- stringish.value
7
- end
8
- end
9
-
10
- def asset_route_helper(root, basename)
11
- basename_string = stringify_string(basename)
12
-
13
- item = system.items["#{root}/#{basename_string}"]
14
- r = system.router.route(item)
15
-
16
- quoted_string(r)
17
- end
18
-
19
- def font_route(basename)
20
- asset_route_helper(fonts_root, basename)
21
- end
22
-
23
2
  def font_url(basename)
24
3
  basename_string = stringify_string(basename)
25
4
 
@@ -27,7 +6,7 @@ module Sass::Script::Functions
27
6
  basename_parts = basename_string.split("?")
28
7
 
29
8
  base = "#{basename_parts[0]}"
30
- qs = "?#{basename_parts[1]}"
9
+ qs = "?#{basename_parts[1]}"
31
10
 
32
11
  path_to_font = quoted_string(font_route(base).value + qs)
33
12
 
@@ -41,4 +20,27 @@ module Sass::Script::Functions
41
20
  img_route = asset_route_helper(images_root, basename)
42
21
  unquoted_string("url(#{img_route})")
43
22
  end
23
+
24
+ private
25
+
26
+ def stringify_string(stringish)
27
+ if stringish.instance_of?(::String)
28
+ stringish
29
+ else
30
+ stringish.value
31
+ end
32
+ end
33
+
34
+ def asset_route_helper(root, basename)
35
+ basename_string = stringify_string(basename)
36
+
37
+ item = system.items["#{root}/#{basename_string}"]
38
+ r = system.router.route(item)
39
+
40
+ quoted_string(r)
41
+ end
42
+
43
+ def font_route(basename)
44
+ asset_route_helper(fonts_root, basename)
45
+ end
44
46
  end
@@ -2,7 +2,7 @@ module Munge
2
2
  module Helpers
3
3
  module AssetTags
4
4
  def stylesheet_tag(basename, options = {})
5
- options[:rel] ||= "stylesheet"
5
+ options[:rel] ||= "stylesheet"
6
6
  options[:href] ||= stylesheet_path(basename)
7
7
 
8
8
  empty_tag(:link, options)
@@ -10,7 +10,7 @@ module Munge
10
10
 
11
11
  def javascript_tag(basename, options = {})
12
12
  options[:type] ||= "text/javascript"
13
- options[:src] ||= javascript_path(basename)
13
+ options[:src] ||= javascript_path(basename)
14
14
 
15
15
  content_tag(:script, options)
16
16
  end
@@ -2,9 +2,9 @@ module Munge
2
2
  module Helpers
3
3
  module Rendering
4
4
  def render(item, engines: nil, data: {}, content_override: nil)
5
- content = content_override || item.content
5
+ content = content_override || item.content
6
6
  renderers = tilt_renderer_list(item, engines)
7
- mdata = merged_data(item.frontmatter, data, self_item: item)
7
+ mdata = merged_data(item.frontmatter, data, self_item: item)
8
8
  item_path = item.relpath
9
9
 
10
10
  render_string(content, data: mdata, engines: renderers, template_name: item_path)
@@ -12,8 +12,8 @@ module Munge
12
12
 
13
13
  def layout(item_or_string, data: {}, &block)
14
14
  layout_item = resolve_layout(item_or_string)
15
- renderers = tilt_renderer_list(layout_item, nil)
16
- mdata = merged_data(layout_item.frontmatter, data, self_layout: layout_item)
15
+ renderers = tilt_renderer_list(layout_item, nil)
16
+ mdata = merged_data(layout_item.frontmatter, data, self_layout: layout_item)
17
17
  layout_path = "(layout) #{layout_item.relpath}"
18
18
 
19
19
  render_string(layout_item.content, data: mdata, engines: renderers, template_name: layout_path, &block)
@@ -28,7 +28,7 @@ module Munge
28
28
  output =
29
29
  engines
30
30
  .reduce(content) do |memoized_content, engine|
31
- options = tilt_options[engine]
31
+ options = tilt_options[engine]
32
32
  template = engine.new(template_name, options) { memoized_content }
33
33
 
34
34
  template.render(self, data) { inner }
data/lib/munge/init.rb CHANGED
@@ -9,10 +9,10 @@ module Munge
9
9
  config:,
10
10
  setup_path:,
11
11
  rules_path:)
12
- @root_path = root_path
12
+ @root_path = root_path
13
13
  @setup_path = setup_path
14
14
  @rules_path = rules_path
15
- @binding = binding
15
+ @binding = binding
16
16
 
17
17
  system = Munge::System.new(root_path, config)
18
18
 
@@ -0,0 +1,31 @@
1
+ module Munge
2
+ module Io
3
+ # NoOp driver for writing files. This is used to compute dry-runs.
4
+ class DryRun
5
+ def initialize(driver)
6
+ @driver = driver
7
+ end
8
+
9
+ # Pretends to write, but actually does nothing
10
+ #
11
+ # @param _abspath [String]
12
+ # @param _content [String]
13
+ def write(_abspath, _content)
14
+ end
15
+
16
+ def exist?(path)
17
+ @driver.exist?(path)
18
+ end
19
+
20
+ def read(path)
21
+ @driver.read(path)
22
+ end
23
+
24
+ def rm(_path)
25
+ end
26
+
27
+ def rmdir(_path)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  module Munge
2
- module Writers
2
+ module Io
3
3
  # Filesystem driver for writing files. These drivers can be defined however
4
4
  # you wish, as long as the `#write` method accepts an abspath and content.
5
5
  class Filesystem
@@ -13,6 +13,26 @@ module Munge
13
13
 
14
14
  File.write(abspath, content)
15
15
  end
16
+
17
+ def exist?(path)
18
+ File.exist?(path)
19
+ end
20
+
21
+ def read(path)
22
+ File.read(path)
23
+ end
24
+
25
+ def rm(path)
26
+ File.delete(path)
27
+ end
28
+
29
+ def rmdir(path)
30
+ contents = Dir.entries(path) - %w(. ..)
31
+
32
+ if contents.empty?
33
+ Dir.rmdir(path)
34
+ end
35
+ end
16
36
  end
17
37
  end
18
38
  end
@@ -1,5 +1,5 @@
1
1
  module Munge
2
- module Writers
2
+ module Io
3
3
  # NoOp driver for writing files. This is used to compute dry-runs.
4
4
  class Noop
5
5
  # Pretends to write, but actually does nothing
@@ -8,6 +8,20 @@ module Munge
8
8
  # @param _content [String]
9
9
  def write(_abspath, _content)
10
10
  end
11
+
12
+ def exist?(_path)
13
+ false
14
+ end
15
+
16
+ def read(_path)
17
+ ""
18
+ end
19
+
20
+ def rm(_path)
21
+ end
22
+
23
+ def rmdir(_path)
24
+ end
11
25
  end
12
26
  end
13
27
  end
data/lib/munge/item.rb CHANGED
@@ -7,19 +7,18 @@ module Munge
7
7
  content: nil,
8
8
  frontmatter: {},
9
9
  stat: nil)
10
- @type = type
11
- @relpath = relpath
12
- @id = id
13
- @content = content
10
+ @type = type
11
+ @relpath = relpath
12
+ @id = id
13
+ @content = content
14
14
  @frontmatter = frontmatter
15
- @stat = stat
15
+ @stat = stat
16
16
 
17
- @route = nil
18
- @layout = nil
17
+ @route = nil
18
+ @layout = nil
19
19
  @transforms = []
20
20
  end
21
21
 
22
- attr_reader :type
23
22
  attr_reader :relpath, :id
24
23
  attr_reader :content, :frontmatter
25
24
  attr_reader :stat
@@ -77,6 +76,18 @@ module Munge
77
76
  end
78
77
  end
79
78
 
79
+ # @return [true, false] whether or not this item is a text type
80
+ # (determined by extension)
81
+ def text?
82
+ @type == :text
83
+ end
84
+
85
+ # @return [true, false] whether or not this item is a binary type
86
+ # (determined by extension)
87
+ def binary?
88
+ @type == :binary
89
+ end
90
+
80
91
  # Runs a regex match to see if item was found in the specified directory.
81
92
  # Do not query with any slashes. Each argument will automatically be joined
82
93
  # by slashes. Note though that the string will be converted into a regex.
@@ -21,7 +21,7 @@ module Munge
21
21
 
22
22
  def add_extension(initial_route, item)
23
23
  intersection = item.extensions & @keep_extensions
24
- extension = intersection[0]
24
+ extension = intersection[0]
25
25
 
26
26
  "#{initial_route}.#{extension}"
27
27
  end
@@ -4,7 +4,7 @@ module Munge
4
4
  def initialize(extensions:,
5
5
  separator:)
6
6
  @extensions = extensions
7
- @separator = separator
7
+ @separator = separator
8
8
  end
9
9
 
10
10
  def type
@@ -29,7 +29,7 @@ module Munge
29
29
 
30
30
  def generate_link(initial_route, content)
31
31
  pre, extension = disassemble(initial_route)
32
- asset_hash = hash(content)
32
+ asset_hash = hash(content)
33
33
 
34
34
  if extension == ""
35
35
  "#{pre}#{@separator}#{asset_hash}"
@@ -43,7 +43,7 @@ module Munge
43
43
  end
44
44
 
45
45
  def disassemble(path)
46
- extension = Util::Path.extname(path)
46
+ extension = Util::Path.extname(path)
47
47
  path_without_extension = Util::Path.path_no_extension(path)
48
48
 
49
49
  [
data/lib/munge/runner.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  module Munge
2
2
  class Runner
3
- def initialize(items:, router:, processor:, writer:, formatter:, verbosity:, destination:)
4
- @items = items
5
- @router = router
6
- @processor = processor
7
- @writer = writer
8
- @reporter = Munge::Reporter.new(formatter: formatter, verbosity: verbosity)
9
- @write_manager = Munge::WriteManager.new(driver: File)
10
- @destination = destination
11
- @written_items = []
3
+ def initialize(items:, router:, processor:, io:, reporter:, destination:, manager:)
4
+ @items = items
5
+ @router = router
6
+ @processor = processor
7
+ @io = io
8
+ @reporter = reporter
9
+ @destination = destination
10
+ @manager = manager
11
+ @written_paths = []
12
12
  end
13
13
 
14
14
  def write
@@ -16,11 +16,11 @@ module Munge
16
16
 
17
17
  @items
18
18
  .reject { |item| item.route.nil? }
19
- .each { |item| render_and_write(item) }
19
+ .each { |item| render_and_write(item) }
20
20
 
21
21
  @reporter.done
22
22
 
23
- @written_items
23
+ @manager.written_routes
24
24
  end
25
25
 
26
26
  private
@@ -31,17 +31,38 @@ module Munge
31
31
  route = @router.route(item)
32
32
  content = @processor.transform(item)
33
33
 
34
- write_status = @write_manager.status(abspath, content)
34
+ write_status = status(abspath, content)
35
35
 
36
36
  case write_status
37
- when :new, :changed
38
- @writer.write(abspath, content)
39
- @written_items.push(route)
37
+ when :new
38
+ @manager.on_new(route, abspath, content)
39
+ when :changed
40
+ @manager.on_changed(route, abspath, content)
41
+ when :identical
42
+ @manager.on_identical(route, abspath, content)
40
43
  when :double_write_error
41
44
  raise Errors::DoubleWriteError, item.route
42
45
  end
43
46
 
44
47
  @reporter.call(item, relpath, write_status)
45
48
  end
49
+
50
+ def status(path, content)
51
+ if @written_paths.include?(path)
52
+ return :double_write_error
53
+ end
54
+
55
+ @written_paths.push(path)
56
+
57
+ if !@io.exist?(path)
58
+ return :new
59
+ end
60
+
61
+ if @io.read(path) == content
62
+ return :identical
63
+ end
64
+
65
+ :changed
66
+ end
46
67
  end
47
68
  end
@@ -23,7 +23,7 @@ module Munge
23
23
  # @param frontmatter [Hash]
24
24
  # @param stat [File::Stat]
25
25
  def build(**args)
26
- @item_factory.build(**prune_args(args))
26
+ @item_factory.build(**args)
27
27
  end
28
28
 
29
29
  # @see System::ItemFactory#parse
@@ -31,7 +31,7 @@ module Munge
31
31
  # @param content [String]
32
32
  # @param stat [File::Stat]
33
33
  def parse(**args)
34
- @item_factory.parse(**prune_args(args))
34
+ @item_factory.parse(**args)
35
35
  end
36
36
 
37
37
  # @yield [Item]
@@ -69,12 +69,6 @@ module Munge
69
69
 
70
70
  super
71
71
  end
72
-
73
- private
74
-
75
- def prune_args(args)
76
- args.select { |k, _| %i(relpath content frontmatter stat).include?(k) }
77
- end
78
72
  end
79
73
  end
80
74
  end
@@ -7,13 +7,13 @@ module Munge
7
7
  end
8
8
 
9
9
  def call(relpath)
10
- dirname = Munge::Util::Path.ensure_relpath(Munge::Util::Path.dirname(relpath))
11
- basename = Munge::Util::Path.basename_no_extension(relpath)
10
+ dirname = Munge::Util::Path.ensure_relpath(Munge::Util::Path.dirname(relpath))
11
+ basename = Munge::Util::Path.basename_no_extension(relpath)
12
12
  extensions = Munge::Util::Path.extnames(relpath)
13
13
 
14
14
  filtered_extensions =
15
15
  extensions
16
- .map { |ext| @remove_extension_regex.match(ext) || ext }
16
+ .map { |ext| @remove_extension_regex.match(ext) || ext }
17
17
  .select { |ext| ext.is_a?(String) }
18
18
 
19
19
  new_basename =
@@ -38,7 +38,7 @@ module Munge
38
38
 
39
39
  def compute_relpath(abspath)
40
40
  folder = Pathname.new(@source_path)
41
- file = Pathname.new(abspath)
41
+ file = Pathname.new(abspath)
42
42
 
43
43
  file.relative_path_from(folder).to_s
44
44
  end
@@ -5,7 +5,7 @@ module Munge
5
5
  extend Forwardable
6
6
 
7
7
  def initialize(item, processor)
8
- @item = item
8
+ @item = item
9
9
  @processor = processor
10
10
  end
11
11
 
data/lib/munge/system.rb CHANGED
@@ -5,20 +5,22 @@ module Munge
5
5
  @config = config
6
6
  end
7
7
 
8
- def items
9
- return @items if @items
10
-
11
- source_path = File.expand_path(@config[:source_path], @root_path)
12
-
13
- source_item_factory =
8
+ def item_factory
9
+ @item_factory ||=
14
10
  ItemFactory.new(
15
11
  text_extensions: @config[:items_text_extensions],
16
12
  ignore_extensions: @config[:items_ignore_extensions]
17
13
  )
14
+ end
15
+
16
+ def items
17
+ return @items if @items
18
+
19
+ source_path = File.expand_path(@config[:source_path], @root_path)
18
20
 
19
21
  @items =
20
22
  Collection.new(
21
- item_factory: source_item_factory,
23
+ item_factory: item_factory,
22
24
  items: Readers::Filesystem.new(source_path)
23
25
  )
24
26
  end
@@ -28,15 +30,9 @@ module Munge
28
30
 
29
31
  layouts_path = File.expand_path(@config[:layouts_path], @root_path)
30
32
 
31
- layouts_item_factory =
32
- ItemFactory.new(
33
- text_extensions: @config[:layouts_text_extensions],
34
- ignore_extensions: %w(.+)
35
- )
36
-
37
33
  @layouts ||=
38
34
  Collection.new(
39
- item_factory: layouts_item_factory,
35
+ item_factory: item_factory,
40
36
  items: Readers::Filesystem.new(layouts_path)
41
37
  )
42
38
  end
data/lib/munge/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Munge
2
- VERSION = "0.17.0".freeze
2
+ VERSION = "0.18.0".freeze
3
3
  end
@@ -0,0 +1,27 @@
1
+ module Munge
2
+ module WriteManager
3
+ class All
4
+ def initialize(io)
5
+ @io = io
6
+ @written_routes = []
7
+ end
8
+
9
+ attr_reader :written_routes
10
+
11
+ def on_new(route, abspath, content)
12
+ @io.write(abspath, content)
13
+ @written_routes.push(abspath)
14
+ end
15
+
16
+ def on_changed(route, abspath, content)
17
+ @io.write(abspath, content)
18
+ @written_routes.push(abspath)
19
+ end
20
+
21
+ def on_identical(route, abspath, content)
22
+ @io.write(abspath, content)
23
+ @written_routes.push(abspath)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ module Munge
2
+ module WriteManager
3
+ class OnlyNeeded
4
+ def initialize(io)
5
+ @io = io
6
+ @written_routes = []
7
+ end
8
+
9
+ attr_reader :written_routes
10
+
11
+ def on_new(route, abspath, content)
12
+ @io.write(abspath, content)
13
+ @written_routes.push(abspath)
14
+ end
15
+
16
+ def on_changed(route, abspath, content)
17
+ @io.write(abspath, content)
18
+ @written_routes.push(abspath)
19
+ end
20
+
21
+ def on_identical(_route, _abspath, _content)
22
+ end
23
+ end
24
+ end
25
+ end
data/lib/munge.rb CHANGED
@@ -29,13 +29,16 @@ require "munge/system/collection"
29
29
  require "munge/system/readers/filesystem"
30
30
  require "munge/system/processor"
31
31
  require "munge/system"
32
- require "munge/writers/filesystem"
33
- require "munge/writers/noop"
34
- require "munge/write_manager"
32
+ require "munge/io/dry_run"
33
+ require "munge/io/filesystem"
34
+ require "munge/io/noop"
35
+ require "munge/write_manager/all"
36
+ require "munge/write_manager/only_needed"
35
37
  require "munge/application"
36
38
  require "munge/config"
37
39
  require "munge/runner"
38
40
  require "munge/reporter"
41
+ require "munge/cleaner"
39
42
  require "munge/pre_init"
40
43
  require "munge/init"
41
44
  require "munge/bootloader"
data/seeds/config.rb CHANGED
@@ -9,10 +9,9 @@ config.output_path = "dest"
9
9
  # Path to global data file
10
10
  config.data_path = "data.yml"
11
11
 
12
- # Determines `item.type` for items and layouts
12
+ # Determines `item.text?` and `item.binary?` for items and layouts
13
13
  # This can be useful avoid applying a transformation to an image
14
14
  config.items_text_extensions = yml["text_extensions"] + yml["bintext_extensions"]
15
- config.layouts_text_extensions = yml["text_extensions"] + yml["bintext_extensions"]
16
15
 
17
16
  # Specify which extensions shouldn't be included as a part of `item.id`
18
17
  config.items_ignore_extensions = yml["dynamic_extensions"]
@@ -1,4 +1,4 @@
1
- <% layout("default") do %>
1
+ <% layout("default.html") do %>
2
2
  <h1>Blog</h1>
3
3
 
4
4
  <%= yield %>
@@ -1,4 +1,4 @@
1
- <% layout("blog") do %>
1
+ <% layout("blog.html") do %>
2
2
  <ul>
3
3
  <% posts.each do |post| %>
4
4
  <li><a href="<%= path_to(post) %>"><%= post.basename %></a></li>
@@ -1,4 +1,4 @@
1
- <% layout("blog") do %>
1
+ <% layout("blog.html") do %>
2
2
  <% posts.each do |post| %>
3
3
  <%= render(post) %>
4
4
  <%= link_to(post, "Permalink") %>
@@ -1,3 +1,3 @@
1
- <% layout("blog") do %>
1
+ <% layout("blog.html") do %>
2
2
  <%= yield %>
3
3
  <% end %>
data/seeds/rules.rb CHANGED
@@ -4,37 +4,36 @@ transform = -> (item) { item.transform }
4
4
  # Blog rules
5
5
  blog_items =
6
6
  app.nonrouted
7
- .select { |item| item.relpath?("blog") }
8
- .sort_by { |item| item.basename }
9
- .each { |item| item[:hide] = item.extensions.include?("draft") }
10
- .each { |item| item[:text] = item.content.valid_encoding? }
11
- .each { |item| item.route = "blog/#{item.basename}" }
7
+ .select { |item| item.relpath?("blog") }
8
+ .each { |item| item[:hide] = item.extensions.include?("draft") }
9
+ .each { |item| item.route = "blog/#{item.basename}" }
10
+ .sort_by(&:basename)
12
11
  .reverse
13
12
 
14
- blog_public_items = blog_items.select { |i| !i[:hide] && i[:text] }
13
+ blog_public_items = blog_items.select { |item| !item[:hide] && item.text? }
15
14
  blog_index_items = blog_public_items[0..7]
16
15
 
17
16
  blog_items
18
- .select { |item| item[:text] }
19
- .each { |item| item.layout = "blog_show" }
17
+ .select(&:text?)
18
+ .each { |item| item.layout = "blog_show.html" }
20
19
  .each(&transform)
21
20
 
22
21
  app.create("blog-index.html.erb", "", posts: blog_index_items)
23
- .each { |item| item.route = "blog" }
24
- .each { |item| item.layout = "blog_index" }
22
+ .each { |item| item.route = "blog" }
23
+ .each { |item| item.layout = "blog_index.html" }
25
24
  .each(&transform)
26
25
 
27
26
  app.create("blog-archive.html.erb", "", posts: blog_public_items)
28
- .each { |item| item.route = "blog/archives" }
29
- .each { |item| item.layout = "blog_archives" }
27
+ .each { |item| item.route = "blog/archives" }
28
+ .each { |item| item.layout = "blog_archives.html" }
30
29
  .each(&transform)
31
30
 
32
31
  # Home page rules
33
32
  app.nonrouted
34
33
  .select { |item| item.relpath?("home") }
35
- .select { |item| item.type == :text }
36
- .each { |item| item.route = "#{item.basepath.sub(%r{^home/}, "")}" }
37
- .each { |item| item.layout = "default" }
34
+ .select(&:text?)
35
+ .each { |item| item.route = "#{item.basepath.sub(%r{^home/}, "")}" }
36
+ .each { |item| item.layout = "default.html" }
38
37
  .each(&transform)
39
38
 
40
39
  # Asset route helpers
@@ -65,8 +64,8 @@ app_asset("stylesheets")
65
64
  # Sitemap
66
65
  html_pages =
67
66
  app.routed
68
- .reject { |item| item.route.nil? }
69
- .select { |item| item.extensions.include?("html") }
70
- .sort_by { |item| item.route }
67
+ .reject { |item| item.route.nil? }
68
+ .select { |item| item.extensions.include?("html") }
69
+ .sort_by(&:route)
71
70
 
72
71
  system.global_data[:sitemap_pages] = html_pages
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: munge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Ahn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-18 00:00:00.000000000 Z
11
+ date: 2017-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -302,7 +302,7 @@ dependencies:
302
302
  - - "~>"
303
303
  - !ruby/object:Gem::Version
304
304
  version: '0.6'
305
- description: Documentation for this release is located in https://github.com/zachahn/munge/blob/v0.17.0/README.md
305
+ description: Documentation for this release is located in https://github.com/zachahn/munge/blob/v0.18.0/README.md
306
306
  email:
307
307
  - zach.ahn@gmail.com
308
308
  executables:
@@ -317,8 +317,10 @@ files:
317
317
  - lib/munge.rb
318
318
  - lib/munge/application.rb
319
319
  - lib/munge/bootloader.rb
320
+ - lib/munge/cleaner.rb
320
321
  - lib/munge/cli.rb
321
322
  - lib/munge/cli/commands/build.rb
323
+ - lib/munge/cli/commands/clean.rb
322
324
  - lib/munge/cli/commands/init.rb
323
325
  - lib/munge/cli/commands/server.rb
324
326
  - lib/munge/cli/commands/update.rb
@@ -334,6 +336,7 @@ files:
334
336
  - lib/munge/extras/livereload/vendor/livereload.js
335
337
  - lib/munge/formatters/default.rb
336
338
  - lib/munge/formatters/dots.rb
339
+ - lib/munge/formatters/silent.rb
337
340
  - lib/munge/go/sass.rb
338
341
  - lib/munge/go/sass/asset_urls.rb
339
342
  - lib/munge/helpers/asset_paths.rb
@@ -345,6 +348,9 @@ files:
345
348
  - lib/munge/helpers/rendering.rb
346
349
  - lib/munge/helpers/tag.rb
347
350
  - lib/munge/init.rb
351
+ - lib/munge/io/dry_run.rb
352
+ - lib/munge/io/filesystem.rb
353
+ - lib/munge/io/noop.rb
348
354
  - lib/munge/item.rb
349
355
  - lib/munge/pre_init.rb
350
356
  - lib/munge/reporter.rb
@@ -368,9 +374,8 @@ files:
368
374
  - lib/munge/util/path.rb
369
375
  - lib/munge/util/symbol_hash.rb
370
376
  - lib/munge/version.rb
371
- - lib/munge/write_manager.rb
372
- - lib/munge/writers/filesystem.rb
373
- - lib/munge/writers/noop.rb
377
+ - lib/munge/write_manager/all.rb
378
+ - lib/munge/write_manager/only_needed.rb
374
379
  - munge.gemspec
375
380
  - seeds/.gitignore
376
381
  - seeds/Gemfile.tt
@@ -418,7 +423,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
418
423
  version: '0'
419
424
  requirements: []
420
425
  rubyforge_project:
421
- rubygems_version: 2.5.2
426
+ rubygems_version: 2.6.8
422
427
  signing_key:
423
428
  specification_version: 4
424
429
  summary: Static site generator aiming to simplify complex build rules
@@ -1,31 +0,0 @@
1
- module Munge
2
- # This class decides whether an item needs to be written.
3
- class WriteManager
4
- # @param driver [#exist?, #read]
5
- def initialize(driver:)
6
- @driver = driver
7
- @write_paths = []
8
- end
9
-
10
- # @param path [String] absolute path to file
11
- # @param content [String] new content of file
12
- # @return [Symbol] `:double_write_error`, `:identical`, `:different`
13
- def status(path, content)
14
- if @write_paths.include?(path)
15
- return :double_write_error
16
- end
17
-
18
- @write_paths.push(path)
19
-
20
- if !@driver.exist?(path)
21
- return :new
22
- end
23
-
24
- if @driver.read(path) == content
25
- return :identical
26
- end
27
-
28
- :changed
29
- end
30
- end
31
- end