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