munge 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/README.md +22 -5
- data/lib/munge.rb +7 -4
- data/lib/munge/application.rb +47 -18
- data/lib/munge/cli.rb +31 -3
- data/lib/munge/core/config.rb +23 -0
- data/lib/munge/core/router.rb +63 -0
- data/lib/munge/core/source.rb +17 -4
- data/lib/munge/core/source/item_factory.rb +94 -15
- data/lib/munge/core/transform.rb +9 -9
- data/lib/munge/core/transform_scope_factory.rb +11 -11
- data/lib/munge/core/write.rb +2 -14
- data/lib/munge/helper/link.rb +29 -0
- data/lib/munge/helper/rendering.rb +72 -56
- data/lib/munge/item.rb +102 -0
- data/lib/munge/transformer/tilt.rb +1 -7
- data/lib/munge/transformer/tilt/scope.rb +8 -10
- data/lib/munge/version.rb +1 -1
- data/munge.gemspec +2 -0
- data/seeds/config.yml +12 -0
- metadata +21 -7
- data/lib/munge/item/base.rb +0 -85
- data/lib/munge/item/binary.rb +0 -9
- data/lib/munge/item/text.rb +0 -9
- data/lib/munge/item/virtual.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a6fdef4a9e19d71e01f67961124f1bc0ca14d46
|
4
|
+
data.tar.gz: 1abf979491cce35a858f227f800402f7899d7efa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14a64e75bf2ac7044816052bb9742819c1561c49335305f2ade3583ef9dfaeb4e685655bcb82440d4a40a5aa2766cee8409f0f090800d82ea11953c619775857
|
7
|
+
data.tar.gz: b9152a9873565d2575137bd9e3c644af6c13fa3f1b937572d76d4e2a73e571fb843579211ed51a0c09ba1b93b3784bacb873f9e631b8db1a62ad993b4a1f95eb
|
data/README.md
CHANGED
@@ -11,6 +11,20 @@ Until then,
|
|
11
11
|
the API should be considered experimental.
|
12
12
|
|
13
13
|
|
14
|
+
## Features
|
15
|
+
|
16
|
+
- No metaprogramming
|
17
|
+
- Suitable for large, complex sites (e.g., multiple blogs with different templates, a single blog with multiple data sources)
|
18
|
+
- Concise rule definition
|
19
|
+
- Rules defined by iterating through arrays and modifying objects
|
20
|
+
|
21
|
+
|
22
|
+
## Caveats
|
23
|
+
|
24
|
+
- Not optimized (Pull requests welcome, gradual optimizations preferred)
|
25
|
+
- Rules can seem pretty dense (because of its conciseness)
|
26
|
+
|
27
|
+
|
14
28
|
## Installation
|
15
29
|
|
16
30
|
Add this line to your application's Gemfile:
|
@@ -32,8 +46,11 @@ Or install it yourself as:
|
|
32
46
|
|
33
47
|
After installing your gem, you can start a project using the command line client.
|
34
48
|
|
35
|
-
```
|
36
|
-
munge init path/to/project
|
49
|
+
```bash
|
50
|
+
munge init path/to/project # create a barebones project
|
51
|
+
cd path/to/project
|
52
|
+
munge build # compiles your project
|
53
|
+
munge view # open http://localhost:3000/ to see output
|
37
54
|
```
|
38
55
|
|
39
56
|
The three main files of your application are `config.yml`, `data.yml`, and `rules.rb`.
|
@@ -51,7 +68,7 @@ app.source
|
|
51
68
|
|
52
69
|
# blog posts
|
53
70
|
app.source
|
54
|
-
.select { |item| item.relpath
|
71
|
+
.select { |item| item.relpath?("posts") } # looks for items in "src/posts/**/*"
|
55
72
|
.each { |item| item.route = "blog/#{item.basename}" } # sets output file to "/blog/#{basename}/index.html"
|
56
73
|
.each { |item| item.layout = "post" }
|
57
74
|
.each { |item| item.transform } # sets transform to Tilt (default)
|
@@ -59,8 +76,8 @@ app.source
|
|
59
76
|
# blog index
|
60
77
|
posts_for_index =
|
61
78
|
app.source
|
62
|
-
.
|
63
|
-
.sort_by
|
79
|
+
.select { |item| item.route?("blog") }
|
80
|
+
.sort_by { |item| item.route }
|
64
81
|
.reverse
|
65
82
|
|
66
83
|
app.create("blog/index.html.erb", "", posts: posts_for_index) do |item|
|
data/lib/munge.rb
CHANGED
@@ -1,21 +1,24 @@
|
|
1
1
|
require "fileutils"
|
2
2
|
require "pathname"
|
3
|
+
require "set"
|
3
4
|
require "yaml"
|
4
5
|
|
6
|
+
require "adsf"
|
7
|
+
require "rack"
|
5
8
|
require "tilt"
|
6
9
|
|
7
10
|
require "munge/version"
|
8
11
|
require "munge/attribute/content"
|
9
12
|
require "munge/attribute/metadata"
|
10
13
|
require "munge/attribute/path"
|
11
|
-
require "munge/item
|
12
|
-
require "munge/item/binary"
|
13
|
-
require "munge/item/text"
|
14
|
-
require "munge/item/virtual"
|
14
|
+
require "munge/item"
|
15
15
|
require "munge/helper"
|
16
16
|
require "munge/helper/find"
|
17
|
+
require "munge/helper/link"
|
17
18
|
require "munge/helper/rendering"
|
18
19
|
require "munge/transformer/tilt"
|
20
|
+
require "munge/core/config"
|
21
|
+
require "munge/core/router"
|
19
22
|
require "munge/core/source"
|
20
23
|
require "munge/core/transform"
|
21
24
|
require "munge/core/transform_scope_factory"
|
data/lib/munge/application.rb
CHANGED
@@ -2,24 +2,50 @@ module Munge
|
|
2
2
|
class Application
|
3
3
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
4
4
|
def initialize(config_path)
|
5
|
-
config =
|
5
|
+
config = Core::Config.new(config_path)
|
6
6
|
|
7
7
|
root_path = File.dirname(File.expand_path(config_path))
|
8
|
-
source_path = File.expand_path(config[
|
9
|
-
layouts_path = File.expand_path(config[
|
10
|
-
output_path = File.expand_path(config[
|
11
|
-
data_path = File.expand_path(config[
|
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
12
|
|
13
13
|
global_data = YAML.load_file(data_path) || {}
|
14
14
|
|
15
|
-
@source =
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
@source =
|
16
|
+
Core::Source.new(
|
17
|
+
source_abspath: source_path,
|
18
|
+
binary_extensions: config[:binary_extensions],
|
19
|
+
location: :fs_memory,
|
20
|
+
ignored_basenames: config[:ignored_basenames]
|
21
|
+
)
|
22
|
+
|
23
|
+
@layouts =
|
24
|
+
Core::Source.new(
|
25
|
+
source_abspath: layouts_path,
|
26
|
+
binary_extensions: [],
|
27
|
+
location: :fs_memory,
|
28
|
+
ignored_basenames: []
|
29
|
+
)
|
30
|
+
|
31
|
+
@router =
|
32
|
+
Core::Router.new(
|
33
|
+
index: config[:index],
|
34
|
+
keep_extensions: config[:keep_extensions]
|
35
|
+
)
|
36
|
+
|
37
|
+
@transform =
|
38
|
+
Core::Transform.new(
|
39
|
+
global_data: global_data,
|
40
|
+
layouts: @layouts,
|
41
|
+
source: @source,
|
42
|
+
router: @router
|
43
|
+
)
|
44
|
+
|
45
|
+
@writer =
|
46
|
+
Core::Write.new(
|
47
|
+
output: output_path
|
48
|
+
)
|
23
49
|
end
|
24
50
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
25
51
|
|
@@ -31,12 +57,12 @@ module Munge
|
|
31
57
|
.each { |item| render_and_write(item, &block) }
|
32
58
|
end
|
33
59
|
|
34
|
-
def
|
35
|
-
|
60
|
+
def build_virtual_item(*args)
|
61
|
+
@source.build_virtual_item(*args)
|
36
62
|
end
|
37
63
|
|
38
64
|
def create(*args, &block)
|
39
|
-
item =
|
65
|
+
item = build_virtual_item(*args)
|
40
66
|
yield item if block_given?
|
41
67
|
@source.push(item)
|
42
68
|
end
|
@@ -44,9 +70,12 @@ module Munge
|
|
44
70
|
private
|
45
71
|
|
46
72
|
def render_and_write(item, &block)
|
47
|
-
|
73
|
+
relpath = @router.filepath(item)
|
74
|
+
|
75
|
+
write_status = @writer.write(relpath, @transform.call(item))
|
76
|
+
|
48
77
|
if block_given?
|
49
|
-
block.call(item,
|
78
|
+
block.call(item, write_status)
|
50
79
|
end
|
51
80
|
end
|
52
81
|
end
|
data/lib/munge/cli.rb
CHANGED
@@ -15,15 +15,43 @@ module Munge
|
|
15
15
|
|
16
16
|
desc "build", "Build in current directory"
|
17
17
|
def build
|
18
|
-
config_path = File.join(destination_root, "config.yml")
|
19
|
-
rules_path = File.join(destination_root, "rules.rb")
|
20
|
-
|
21
18
|
Munge::Runner.write(config_path, rules_path)
|
22
19
|
end
|
23
20
|
|
21
|
+
desc "view", "View built files"
|
22
|
+
method_option :port, aliases: "-p", desc: "Set port", default: 3000, type: :numeric
|
23
|
+
method_option :host, aliases: "-h", desc: "Set host", default: "0.0.0.0", type: :string
|
24
|
+
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)
|
40
|
+
end
|
41
|
+
|
24
42
|
desc "version", "Print version"
|
25
43
|
def version
|
26
44
|
puts "munge #{Munge::VERSION}"
|
27
45
|
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def config_path
|
50
|
+
File.join(destination_root, "config.yml")
|
51
|
+
end
|
52
|
+
|
53
|
+
def rules_path
|
54
|
+
File.join(destination_root, "rules.rb")
|
55
|
+
end
|
28
56
|
end
|
29
57
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Munge
|
2
|
+
module Core
|
3
|
+
class Config
|
4
|
+
def initialize(path)
|
5
|
+
abspath = File.expand_path(path)
|
6
|
+
@datastore =
|
7
|
+
read_yaml(abspath)
|
8
|
+
.map { |key, value| [key.to_sym, value] }
|
9
|
+
.to_h
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
@datastore[key]
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def read_yaml(abspath)
|
19
|
+
YAML.load_file(abspath) || {}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Munge
|
2
|
+
module Core
|
3
|
+
class Router
|
4
|
+
def initialize(index:, keep_extensions:)
|
5
|
+
@index = index
|
6
|
+
@keep_extensions = keep_extensions
|
7
|
+
end
|
8
|
+
|
9
|
+
def route(item)
|
10
|
+
fail "item has no route" unless item.route
|
11
|
+
|
12
|
+
if keep_extension?(item)
|
13
|
+
"/#{filepath(item)}"
|
14
|
+
else
|
15
|
+
item.route
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
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
|
32
|
+
|
33
|
+
relativeize(path)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def relativeize(path)
|
39
|
+
while path[0] == "/"
|
40
|
+
path = path[1..-1]
|
41
|
+
end
|
42
|
+
|
43
|
+
path
|
44
|
+
end
|
45
|
+
|
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)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/munge/core/source.rb
CHANGED
@@ -5,18 +5,31 @@ module Munge
|
|
5
5
|
class Source
|
6
6
|
include Enumerable
|
7
7
|
|
8
|
-
def initialize(source_abspath
|
9
|
-
|
10
|
-
|
8
|
+
def initialize(source_abspath:,
|
9
|
+
binary_extensions:,
|
10
|
+
location:,
|
11
|
+
ignored_basenames:)
|
12
|
+
@item_factory =
|
13
|
+
ItemFactory.new(
|
14
|
+
source_path: source_abspath,
|
15
|
+
binary_extensions: binary_extensions,
|
16
|
+
location: location,
|
17
|
+
ignored_basenames: ignored_basenames
|
18
|
+
)
|
19
|
+
pattern = File.join(source_abspath, "**", "*")
|
11
20
|
|
12
21
|
@items =
|
13
22
|
Dir.glob(pattern)
|
14
23
|
.reject { |item_path| File.directory?(item_path) }
|
15
|
-
.map { |item_path| item_factory.
|
24
|
+
.map { |item_path| @item_factory.read(item_path) }
|
16
25
|
.map { |item| [item.id, item] }
|
17
26
|
.to_h
|
18
27
|
end
|
19
28
|
|
29
|
+
def build_virtual_item(*args)
|
30
|
+
@item_factory.build_virtual(*args)
|
31
|
+
end
|
32
|
+
|
20
33
|
def each
|
21
34
|
return enum_for(:each) unless block_given?
|
22
35
|
|
@@ -1,30 +1,109 @@
|
|
1
1
|
module Munge
|
2
2
|
class ItemFactory
|
3
|
-
def initialize(
|
4
|
-
|
5
|
-
|
3
|
+
def initialize(source_path:,
|
4
|
+
binary_extensions:,
|
5
|
+
location:,
|
6
|
+
ignored_basenames:)
|
7
|
+
@source_path = source_path
|
8
|
+
@binary_extensions = Set.new(binary_extensions)
|
9
|
+
@location = location
|
10
|
+
@ignored_basenames = ignored_basenames
|
6
11
|
end
|
7
12
|
|
8
|
-
def
|
9
|
-
|
10
|
-
content = Munge::Attribute::Content.new(File.read(path.absolute))
|
11
|
-
stat = Munge::Attribute::Metadata.new(filepath)
|
13
|
+
def read(abspath)
|
14
|
+
content, frontmatter = compute_content_and_frontmatter(abspath)
|
12
15
|
|
13
|
-
|
14
|
-
|
16
|
+
relpath = compute_relpath(abspath)
|
17
|
+
|
18
|
+
Munge::Item.new(
|
19
|
+
type: compute_file_type(abspath),
|
20
|
+
location: @location,
|
21
|
+
abspath: abspath,
|
22
|
+
relpath: relpath,
|
23
|
+
id: compute_id(relpath),
|
24
|
+
content: content,
|
25
|
+
frontmatter: frontmatter,
|
26
|
+
stat: compute_stat(abspath)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_virtual(relpath, content, frontmatter, type: :text)
|
31
|
+
Munge::Item.new(
|
32
|
+
type: type,
|
33
|
+
location: :virtual,
|
34
|
+
abspath: nil,
|
35
|
+
relpath: relpath,
|
36
|
+
id: compute_id(relpath),
|
37
|
+
content: content,
|
38
|
+
frontmatter: frontmatter,
|
39
|
+
stat: nil
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def compute_content_and_frontmatter(abspath)
|
46
|
+
case @location
|
47
|
+
when :fs_memory
|
48
|
+
content = Munge::Attribute::Content.new(File.read(abspath))
|
49
|
+
[content.content, content.frontmatter]
|
50
|
+
when :fs, :virtual
|
51
|
+
["", {}]
|
15
52
|
else
|
16
|
-
|
53
|
+
fail "invalid @location `#{@location}`"
|
17
54
|
end
|
18
55
|
end
|
19
56
|
|
20
|
-
|
57
|
+
def file_extensions(filepath)
|
58
|
+
extensions = File.basename(filepath).split(".")[1..-1]
|
59
|
+
Set.new(extensions)
|
60
|
+
end
|
61
|
+
|
62
|
+
def compute_file_type(abspath)
|
63
|
+
exts = file_extensions(abspath)
|
64
|
+
|
65
|
+
if exts.intersect?(@binary_extensions)
|
66
|
+
:binary
|
67
|
+
else
|
68
|
+
:text
|
69
|
+
end
|
70
|
+
end
|
21
71
|
|
22
|
-
def
|
23
|
-
|
72
|
+
def compute_relpath(abspath)
|
73
|
+
folder = Pathname.new(@source_path)
|
74
|
+
file = Pathname.new(abspath)
|
24
75
|
|
25
|
-
|
76
|
+
file.relative_path_from(folder).to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
def compute_stat(abspath)
|
80
|
+
File.stat(abspath)
|
81
|
+
end
|
82
|
+
|
83
|
+
def compute_id(relpath)
|
84
|
+
dirname = compute_dirname(relpath)
|
85
|
+
basename = compute_basename(relpath)
|
86
|
+
|
87
|
+
id = []
|
88
|
+
|
89
|
+
unless dirname == "."
|
90
|
+
id.push(dirname)
|
91
|
+
end
|
92
|
+
|
93
|
+
unless @ignored_basenames.include?(basename)
|
94
|
+
id.push(basename)
|
95
|
+
end
|
96
|
+
|
97
|
+
id.join("/")
|
98
|
+
end
|
99
|
+
|
100
|
+
def compute_dirname(relpath)
|
101
|
+
dirname = File.dirname(relpath)
|
102
|
+
end
|
26
103
|
|
27
|
-
|
104
|
+
def compute_basename(relpath)
|
105
|
+
filename = File.basename(relpath)
|
106
|
+
filename.split(".").first
|
28
107
|
end
|
29
108
|
end
|
30
109
|
end
|
data/lib/munge/core/transform.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
module Munge
|
2
2
|
module Core
|
3
3
|
class Transform
|
4
|
-
def initialize(
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
def initialize(layouts:,
|
5
|
+
global_data:,
|
6
|
+
source:,
|
7
|
+
router:)
|
8
8
|
@scope_factory = Core::TransformScopeFactory.new(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
layouts: layouts,
|
10
|
+
global_data: global_data,
|
11
|
+
source: source,
|
12
|
+
helper_container: Munge::Helper,
|
13
|
+
router: router
|
14
14
|
)
|
15
15
|
end
|
16
16
|
|
@@ -1,24 +1,24 @@
|
|
1
1
|
module Munge
|
2
2
|
module Core
|
3
3
|
class TransformScopeFactory
|
4
|
-
def initialize(
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@
|
10
|
-
@layouts_path = layouts_path
|
4
|
+
def initialize(layouts:,
|
5
|
+
global_data:,
|
6
|
+
source:,
|
7
|
+
helper_container:,
|
8
|
+
router:)
|
9
|
+
@layouts = layouts
|
11
10
|
@global_data = global_data
|
12
11
|
@source = source
|
13
12
|
@helper_container = helper_container
|
13
|
+
@router = router
|
14
14
|
end
|
15
15
|
|
16
16
|
def create(load_helpers = true)
|
17
17
|
scope = Munge::Transformer::Tilt::Scope.new(
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@
|
18
|
+
layouts: @layouts,
|
19
|
+
global_data: @global_data,
|
20
|
+
source: @source,
|
21
|
+
router: @router
|
22
22
|
)
|
23
23
|
|
24
24
|
if load_helpers
|
data/lib/munge/core/write.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
module Munge
|
2
2
|
module Core
|
3
3
|
class Write
|
4
|
-
def initialize(output
|
4
|
+
def initialize(output:)
|
5
5
|
@output = output
|
6
|
-
@index = index
|
7
6
|
end
|
8
7
|
|
9
|
-
def write(
|
10
|
-
relpath = resolve_filepath(route)
|
8
|
+
def write(relpath, content)
|
11
9
|
abspath = File.join(@output, relpath)
|
12
10
|
|
13
11
|
FileUtils.mkdir_p(File.dirname(abspath))
|
@@ -19,16 +17,6 @@ module Munge
|
|
19
17
|
true
|
20
18
|
end
|
21
19
|
end
|
22
|
-
|
23
|
-
def resolve_filepath(preferred_filename)
|
24
|
-
basename = File.basename(preferred_filename)
|
25
|
-
|
26
|
-
if basename.include?(".")
|
27
|
-
preferred_filename
|
28
|
-
else
|
29
|
-
"#{preferred_filename}/#{@index}"
|
30
|
-
end
|
31
|
-
end
|
32
20
|
end
|
33
21
|
end
|
34
22
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Munge
|
2
|
+
module Helper
|
3
|
+
module Link
|
4
|
+
def url_for(item)
|
5
|
+
@router.route(item)
|
6
|
+
end
|
7
|
+
|
8
|
+
def link_to(item, text = nil, **opts)
|
9
|
+
link = url_for(item)
|
10
|
+
|
11
|
+
optstr = opts.map { |key, val| %(#{key}="#{val}") }
|
12
|
+
|
13
|
+
parts =
|
14
|
+
[
|
15
|
+
[
|
16
|
+
"<a",
|
17
|
+
%(href="#{link}"),
|
18
|
+
optstr
|
19
|
+
].flatten.join(" "),
|
20
|
+
">",
|
21
|
+
text || link,
|
22
|
+
"</a>"
|
23
|
+
]
|
24
|
+
|
25
|
+
parts.join
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,49 +1,40 @@
|
|
1
1
|
module Munge
|
2
2
|
module Helper
|
3
3
|
module Rendering
|
4
|
-
def render(item,
|
5
|
-
content =
|
6
|
-
renderers =
|
7
|
-
|
4
|
+
def render(item, engines: nil, data: {}, content_override: nil)
|
5
|
+
content = content_override || item.content
|
6
|
+
renderers = tilt_renderer_list(item, engines)
|
7
|
+
mdata = merged_data(item.frontmatter, data)
|
8
8
|
|
9
|
-
renderers
|
10
|
-
.inject(content) do |output, engine|
|
11
|
-
template = engine.new { output }
|
12
|
-
template.render(self, data)
|
13
|
-
end
|
9
|
+
manual_render(content, mdata, renderers)
|
14
10
|
end
|
15
11
|
|
16
|
-
def layout(
|
17
|
-
|
12
|
+
def layout(item_or_string, data: {}, &block)
|
13
|
+
layout_item = resolve_layout(item_or_string)
|
14
|
+
mdata = merged_data(layout_item.frontmatter, data)
|
18
15
|
|
19
16
|
if block_given?
|
20
17
|
if block.binding.local_variable_defined?(:_erbout)
|
21
|
-
layout_within_template(
|
18
|
+
layout_within_template(layout_item, mdata, &block)
|
22
19
|
else
|
23
|
-
layout_outside_template(
|
20
|
+
layout_outside_template(layout_item, mdata, &block)
|
24
21
|
end
|
25
22
|
else
|
26
|
-
layout_without_block(
|
23
|
+
layout_without_block(layout_item, mdata)
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
30
|
-
def render_with_layout(item,
|
31
|
-
|
32
|
-
merged_data(item.frontmatter, additional_data)
|
27
|
+
def render_with_layout(item, content_engines: nil, data: {}, content_override: nil)
|
28
|
+
mdata = merged_data(item.frontmatter, data)
|
33
29
|
|
34
|
-
inner =
|
35
|
-
if block_given?
|
36
|
-
render(item, manual_engine, **data, &content_block)
|
37
|
-
else
|
38
|
-
render(item, manual_engine, **data)
|
39
|
-
end
|
30
|
+
inner = render(item, engines: content_engines, data: mdata, content_override: content_override)
|
40
31
|
|
41
|
-
if item.layout
|
42
|
-
|
43
|
-
else
|
44
|
-
layout(item.layout, data) do
|
32
|
+
if item.layout
|
33
|
+
layout(item.layout, data: mdata) do
|
45
34
|
inner
|
46
35
|
end
|
36
|
+
else
|
37
|
+
inner
|
47
38
|
end
|
48
39
|
end
|
49
40
|
|
@@ -61,22 +52,26 @@ module Munge
|
|
61
52
|
end
|
62
53
|
end
|
63
54
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
55
|
+
def resolve_layout(item_or_string)
|
56
|
+
if item_or_string.is_a?(String)
|
57
|
+
@layouts[item_or_string]
|
58
|
+
else
|
59
|
+
item_or_string
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def layout_outside_template(layout_item, mdata, &block)
|
64
|
+
engine_list = tilt_renderer_list(layout_item, nil)
|
65
|
+
|
66
|
+
manual_render(layout_item.content, mdata, engine_list, &block)
|
67
67
|
end
|
68
68
|
|
69
|
-
def layout_within_template(
|
69
|
+
def layout_within_template(layout_item, mdata, &block)
|
70
70
|
original_erbout = block.binding.local_variable_get(:_erbout)
|
71
71
|
|
72
72
|
block.binding.local_variable_set(:_erbout, "")
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
template = ::Tilt.new(actual_layout)
|
77
|
-
result = template.render(self, merged_data(additional_data)) do
|
78
|
-
inside
|
79
|
-
end
|
74
|
+
result = layout_outside_template(layout_item, mdata) { block.call }
|
80
75
|
|
81
76
|
final = original_erbout + result
|
82
77
|
|
@@ -85,32 +80,53 @@ module Munge
|
|
85
80
|
""
|
86
81
|
end
|
87
82
|
|
88
|
-
def
|
89
|
-
|
90
|
-
template.render(self, merged_data(additional_data)) do
|
91
|
-
block.call
|
92
|
-
end
|
93
|
-
end
|
83
|
+
def layout_without_block(layout_item, mdata)
|
84
|
+
engine_list = tilt_renderer_list(layout_item, nil)
|
94
85
|
|
95
|
-
|
96
|
-
template = ::Tilt.new(actual_layout)
|
97
|
-
template.render(self, merged_data(additional_data))
|
86
|
+
manual_render(layout_item.content, mdata, engine_list)
|
98
87
|
end
|
99
88
|
|
100
|
-
def
|
101
|
-
if
|
102
|
-
|
89
|
+
def tilt_renderer_list(item, preferred_engine)
|
90
|
+
if preferred_engine
|
91
|
+
tilt_renderers_from_preferred(preferred_engine)
|
103
92
|
else
|
104
|
-
item.
|
93
|
+
tilt_renderers_from_path(item.relpath)
|
105
94
|
end
|
106
95
|
end
|
107
96
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
97
|
+
def tilt_renderers_from_path(path)
|
98
|
+
::Tilt.templates_for(path)
|
99
|
+
end
|
100
|
+
|
101
|
+
def tilt_renderers_from_preferred(preferred_engines)
|
102
|
+
preferred =
|
103
|
+
if preferred_engines.is_a?(Array)
|
104
|
+
preferred_engines.flatten.join(".")
|
105
|
+
else
|
106
|
+
preferred_engines
|
107
|
+
end
|
108
|
+
|
109
|
+
::Tilt.templates_for(preferred)
|
110
|
+
end
|
111
|
+
|
112
|
+
def manual_render(content, data, engine_list, &block)
|
113
|
+
inner =
|
114
|
+
if block_given?
|
115
|
+
block.call
|
116
|
+
else
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
|
120
|
+
engine_list
|
121
|
+
.inject(content) do |output, engine|
|
122
|
+
template = engine.new { output }
|
123
|
+
|
124
|
+
if inner
|
125
|
+
template.render(self, data) { inner }
|
126
|
+
else
|
127
|
+
template.render(self, data)
|
128
|
+
end
|
129
|
+
end
|
114
130
|
end
|
115
131
|
end
|
116
132
|
end
|
data/lib/munge/item.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module Munge
|
2
|
+
class Item
|
3
|
+
def initialize(type:,
|
4
|
+
location:,
|
5
|
+
abspath:,
|
6
|
+
relpath:,
|
7
|
+
id:,
|
8
|
+
content: nil,
|
9
|
+
frontmatter: {},
|
10
|
+
stat: nil)
|
11
|
+
@type = type
|
12
|
+
@location = location
|
13
|
+
@abspath = abspath
|
14
|
+
@relpath = relpath
|
15
|
+
@id = id
|
16
|
+
@content = content
|
17
|
+
@frontmatter = frontmatter
|
18
|
+
@stat = stat
|
19
|
+
|
20
|
+
@route = nil
|
21
|
+
@layout = nil
|
22
|
+
@transforms = []
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :type, :location
|
26
|
+
attr_reader :abspath, :relpath, :id
|
27
|
+
attr_reader :content, :frontmatter
|
28
|
+
attr_reader :stat
|
29
|
+
|
30
|
+
attr_reader :layout, :transforms
|
31
|
+
|
32
|
+
def dirname
|
33
|
+
if File.dirname(@relpath) == "."
|
34
|
+
""
|
35
|
+
else
|
36
|
+
File.dirname(@relpath)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def filename
|
41
|
+
File.basename(@relpath)
|
42
|
+
end
|
43
|
+
|
44
|
+
def basename
|
45
|
+
filename.split(".").first
|
46
|
+
end
|
47
|
+
|
48
|
+
def extensions
|
49
|
+
filename.split(".")[1..-1]
|
50
|
+
end
|
51
|
+
|
52
|
+
def [](key)
|
53
|
+
@frontmatter[key]
|
54
|
+
end
|
55
|
+
|
56
|
+
def []=(key, value)
|
57
|
+
@frontmatter[key] = value
|
58
|
+
end
|
59
|
+
|
60
|
+
def route=(new_route)
|
61
|
+
@route = remove_surrounding_slashes(new_route)
|
62
|
+
end
|
63
|
+
|
64
|
+
def route
|
65
|
+
if @route
|
66
|
+
"/#{@route}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def relpath?(*subdir_patterns)
|
71
|
+
regexp = generate_regex(subdir_patterns)
|
72
|
+
regexp === @relpath
|
73
|
+
end
|
74
|
+
|
75
|
+
# do not query with slashes
|
76
|
+
def route?(*subdir_patterns)
|
77
|
+
regexp = generate_regex(subdir_patterns)
|
78
|
+
regexp === @route
|
79
|
+
end
|
80
|
+
|
81
|
+
def layout=(new_layout)
|
82
|
+
@layout = remove_surrounding_slashes(new_layout)
|
83
|
+
end
|
84
|
+
|
85
|
+
def transform(transformer = :Tilt, *args)
|
86
|
+
@transforms.push([transformer, args])
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def generate_regex(pattern_list)
|
92
|
+
joined_pattern = pattern_list.join("/")
|
93
|
+
Regexp.new("^#{joined_pattern}")
|
94
|
+
end
|
95
|
+
|
96
|
+
def remove_surrounding_slashes(string)
|
97
|
+
string
|
98
|
+
.sub(%r(^/+), "")
|
99
|
+
.sub(%r(/+$), "")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -8,13 +8,7 @@ module Munge
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(item, content = nil, renderer = nil)
|
11
|
-
|
12
|
-
@scope.render_with_layout(item, renderer)
|
13
|
-
else
|
14
|
-
@scope.render_with_layout(item, renderer) do
|
15
|
-
content
|
16
|
-
end
|
17
|
-
end
|
11
|
+
@scope.render_with_layout(item, content_engines: renderer, content_override: content)
|
18
12
|
end
|
19
13
|
end
|
20
14
|
end
|
@@ -2,16 +2,14 @@ module Munge
|
|
2
2
|
module Transformer
|
3
3
|
class Tilt
|
4
4
|
class Scope
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@global_data = global_data
|
14
|
-
@source = source
|
5
|
+
def initialize(layouts:,
|
6
|
+
global_data:,
|
7
|
+
source:,
|
8
|
+
router:)
|
9
|
+
@global_data = global_data
|
10
|
+
@layouts = layouts
|
11
|
+
@source = source
|
12
|
+
@router = router
|
15
13
|
end
|
16
14
|
end
|
17
15
|
end
|
data/lib/munge/version.rb
CHANGED
data/munge.gemspec
CHANGED
@@ -10,6 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["zach.ahn@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = "Static site generator aiming to simplify complex build rules"
|
13
|
+
spec.description = "Documentation for this release is located in https://github.com/zachahn/munge/blob/v#{Munge::VERSION}/README.md"
|
13
14
|
spec.homepage = "https://github.com/zachahn/munge"
|
14
15
|
spec.license = "MIT"
|
15
16
|
|
@@ -30,6 +31,7 @@ Gem::Specification.new do |spec|
|
|
30
31
|
spec.add_development_dependency "codeclimate-test-reporter", "~> 0.4"
|
31
32
|
spec.add_development_dependency "simplecov", "~> 0.10"
|
32
33
|
|
34
|
+
spec.add_runtime_dependency "adsf", "~> 1.2"
|
33
35
|
spec.add_runtime_dependency "image_optim", "~> 0.21"
|
34
36
|
spec.add_runtime_dependency "image_optim_pack", "~> 0.2"
|
35
37
|
spec.add_runtime_dependency "thor", "~> 0.19"
|
data/seeds/config.yml
CHANGED
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.
|
4
|
+
version: 0.3.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: 2015-10-
|
11
|
+
date: 2015-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.10'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: adsf
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.2'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1.2'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: image_optim
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,7 +192,7 @@ dependencies:
|
|
178
192
|
- - "~>"
|
179
193
|
- !ruby/object:Gem::Version
|
180
194
|
version: '2.0'
|
181
|
-
description:
|
195
|
+
description: Documentation for this release is located in https://github.com/zachahn/munge/blob/v0.3.0/README.md
|
182
196
|
email:
|
183
197
|
- zach.ahn@gmail.com
|
184
198
|
executables:
|
@@ -201,6 +215,8 @@ files:
|
|
201
215
|
- lib/munge/attribute/metadata.rb
|
202
216
|
- lib/munge/attribute/path.rb
|
203
217
|
- lib/munge/cli.rb
|
218
|
+
- lib/munge/core/config.rb
|
219
|
+
- lib/munge/core/router.rb
|
204
220
|
- lib/munge/core/source.rb
|
205
221
|
- lib/munge/core/source/item_factory.rb
|
206
222
|
- lib/munge/core/transform.rb
|
@@ -208,11 +224,9 @@ files:
|
|
208
224
|
- lib/munge/core/write.rb
|
209
225
|
- lib/munge/helper.rb
|
210
226
|
- lib/munge/helper/find.rb
|
227
|
+
- lib/munge/helper/link.rb
|
211
228
|
- lib/munge/helper/rendering.rb
|
212
|
-
- lib/munge/item
|
213
|
-
- lib/munge/item/binary.rb
|
214
|
-
- lib/munge/item/text.rb
|
215
|
-
- lib/munge/item/virtual.rb
|
229
|
+
- lib/munge/item.rb
|
216
230
|
- lib/munge/runner.rb
|
217
231
|
- lib/munge/transformer/image_optim.rb
|
218
232
|
- lib/munge/transformer/tilt.rb
|
data/lib/munge/item/base.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
module Munge
|
2
|
-
module Item
|
3
|
-
class Base
|
4
|
-
def initialize(path = nil, content = nil, info = nil)
|
5
|
-
@path = path
|
6
|
-
@content = content
|
7
|
-
@info = info
|
8
|
-
@layout = nil
|
9
|
-
@route = nil
|
10
|
-
@transforms = []
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :transforms
|
14
|
-
attr_accessor :route, :layout
|
15
|
-
|
16
|
-
def id
|
17
|
-
if dirname == ""
|
18
|
-
basename
|
19
|
-
else
|
20
|
-
"#{dirname}/#{basename}"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def relpath
|
25
|
-
@path.relative
|
26
|
-
end
|
27
|
-
|
28
|
-
def dirname
|
29
|
-
if File.dirname(relpath) == "."
|
30
|
-
""
|
31
|
-
else
|
32
|
-
File.dirname(relpath)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def filename
|
37
|
-
File.basename(relpath)
|
38
|
-
end
|
39
|
-
|
40
|
-
def basename
|
41
|
-
filename.split(".").first
|
42
|
-
end
|
43
|
-
|
44
|
-
def content
|
45
|
-
@content.content
|
46
|
-
end
|
47
|
-
|
48
|
-
def frontmatter
|
49
|
-
@content.frontmatter
|
50
|
-
end
|
51
|
-
|
52
|
-
def stat
|
53
|
-
@info.stat
|
54
|
-
end
|
55
|
-
|
56
|
-
def virtual?
|
57
|
-
false
|
58
|
-
end
|
59
|
-
|
60
|
-
def binary?
|
61
|
-
false
|
62
|
-
end
|
63
|
-
|
64
|
-
def text?
|
65
|
-
false
|
66
|
-
end
|
67
|
-
|
68
|
-
def transform(transformer = :tilt, *args)
|
69
|
-
@transforms.push([transformer, args])
|
70
|
-
end
|
71
|
-
|
72
|
-
def [](key)
|
73
|
-
frontmatter[key]
|
74
|
-
end
|
75
|
-
|
76
|
-
def []=(key, value)
|
77
|
-
frontmatter[key] = value
|
78
|
-
end
|
79
|
-
|
80
|
-
def to_s
|
81
|
-
"#{super} #{relpath} #{route}"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
data/lib/munge/item/binary.rb
DELETED
data/lib/munge/item/text.rb
DELETED
data/lib/munge/item/virtual.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
module Munge
|
2
|
-
module Item
|
3
|
-
class Virtual < Base
|
4
|
-
def initialize(relpath, kontent, frontmatter = nil)
|
5
|
-
content =
|
6
|
-
if kontent.is_a?(String)
|
7
|
-
Munge::Attribute::Content.new(kontent, frontmatter)
|
8
|
-
else
|
9
|
-
kontent
|
10
|
-
end
|
11
|
-
|
12
|
-
super(relpath, content)
|
13
|
-
end
|
14
|
-
|
15
|
-
def relpath
|
16
|
-
@path
|
17
|
-
end
|
18
|
-
|
19
|
-
def virtual?
|
20
|
-
true
|
21
|
-
end
|
22
|
-
|
23
|
-
def text?
|
24
|
-
true
|
25
|
-
end
|
26
|
-
|
27
|
-
def content=(new_content)
|
28
|
-
@content.content = new_content
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|