munge 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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