mint 0.1.1 → 0.1.3
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.
- data/README.md +175 -228
- data/bin/mint +141 -57
- data/lib/mint.rb +2 -433
- data/lib/mint/helpers.rb +31 -0
- data/lib/mint/mint.rb +309 -0
- metadata +20 -11
- data/templates/default/layout.haml +0 -7
- data/templates/default/style.sass +0 -21
data/lib/mint/helpers.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Mint
|
6
|
+
module Helpers
|
7
|
+
# Returns the relative path to dir1 from dir2.
|
8
|
+
def self.normalize_path(dir1, dir2)
|
9
|
+
path = case dir1
|
10
|
+
when String
|
11
|
+
Pathname.new dir1
|
12
|
+
when Pathname
|
13
|
+
dir1
|
14
|
+
end
|
15
|
+
|
16
|
+
path.expand_path.relative_path_from(dir2.expand_path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.ensure_directory(dir)
|
20
|
+
FileUtils.mkdir_p dir
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.update_yaml(new_opts, file)
|
24
|
+
curr_opts = file.exist? ? YAML.load_file(file) : {}
|
25
|
+
|
26
|
+
File.open file, 'w' do |f|
|
27
|
+
YAML.dump curr_opts.merge(new_opts), f
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/mint/mint.rb
ADDED
@@ -0,0 +1,309 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tilt'
|
4
|
+
require 'helpers'
|
5
|
+
|
6
|
+
module Mint
|
7
|
+
VERSION = '0.1.3'
|
8
|
+
MINT_DIR = Pathname.new(__FILE__).realpath.dirname + '..'
|
9
|
+
|
10
|
+
# Assume that someone using an Html template has formatted it
|
11
|
+
# in Erb and that a Css stylesheet will pass untouched through
|
12
|
+
# a Less parser.
|
13
|
+
Tilt.register 'html', Tilt::ERBTemplate
|
14
|
+
Tilt.register 'css', Tilt::LessTemplate
|
15
|
+
|
16
|
+
# Return the an array with the Mint template path. Will first look
|
17
|
+
# for MINT_PATH environment variable. Otherwise will use smart defaults.
|
18
|
+
# Either way, earlier/higher paths take precedence.
|
19
|
+
def self.path
|
20
|
+
mint_path = ENV['MINT_PATH'] || "#{Dir.getwd}/.mint:~/.mint:#{MINT_DIR}"
|
21
|
+
path = mint_path.split(':').map {|p| Pathname.new(p).expand_path }
|
22
|
+
end
|
23
|
+
|
24
|
+
# I want to refactor this so that Mint.path is always a Hash...
|
25
|
+
# should take care of this in the Mint.path=() method.
|
26
|
+
# Right now, this is a hack. It assumes a sane MINT_PATH, where the
|
27
|
+
# first entry is most local and the last entry is most global.
|
28
|
+
def self.path_for_scope(scope=:local)
|
29
|
+
case Mint.path
|
30
|
+
when Array
|
31
|
+
index = { local: 0, user: 1, global: 2 }[scope]
|
32
|
+
Mint.path[index]
|
33
|
+
when Hash
|
34
|
+
Mint.path[scope]
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a hash with key Mint directories
|
41
|
+
def self.directories
|
42
|
+
{ templates: 'templates' }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns a hash with key Mint files
|
46
|
+
def self.files
|
47
|
+
{ config: 'config.yaml' }
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.default_options
|
51
|
+
{
|
52
|
+
# Do not set default `template`--will override style and
|
53
|
+
# layout when already specified -- causes tricky bugs
|
54
|
+
layout: 'default', # default layout
|
55
|
+
style: 'default', # default style
|
56
|
+
destination: nil, # do not create a subdirectory
|
57
|
+
style_destination: nil # do not copy style to root
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns a list of all file extensions that Tilt will render
|
62
|
+
def self.formats
|
63
|
+
Tilt.mappings.keys
|
64
|
+
end
|
65
|
+
|
66
|
+
# Registered Css formats, for source -> destination
|
67
|
+
# name guessing/conversion only.
|
68
|
+
def self.css_formats
|
69
|
+
css_formats = ['.css', '.sass', '.scss', '.less']
|
70
|
+
end
|
71
|
+
|
72
|
+
# Decides whether the template specified by `name_or_file` is a real
|
73
|
+
# file or the name of a template. If it is a real file, Mint will
|
74
|
+
# return a that file. Otherwise, Mint will look for a file with that
|
75
|
+
# name in the Mint path. The `type` argument indicates whether the
|
76
|
+
# template we are looking for is a layout or a style and will affect
|
77
|
+
# which type of template is returned for a given template name. For
|
78
|
+
# example, `lookup_template :normal` might return a layout template
|
79
|
+
# referring to the file ~/.mint/templates/normal/layout.erb.
|
80
|
+
# Adding :style as a second argument returns
|
81
|
+
# ~/.mint/templates/normal/style.css.
|
82
|
+
def self.lookup_template(name_or_file, type=:layout)
|
83
|
+
name = name_or_file.to_s
|
84
|
+
File.exist?(name) ? Pathname.new(name) : find_template(name, type)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Finds a template named `name` in the Mint path. If `type` # is :layout,
|
88
|
+
# will look for `${MINT_PATH}/templates/layout.*`. If it is :style, will
|
89
|
+
# look for `${MINT_PATH}/templates/template_name/style.*`. Mint assumes
|
90
|
+
# that a named template will hold only one layout and one style template.
|
91
|
+
# It does not know how to decide between style.css and style.less, for
|
92
|
+
# example. For predictable results, only include one template file
|
93
|
+
# called `layout.*` in the `template_name` directory. Returns nil if
|
94
|
+
# it cannot find a template.
|
95
|
+
def self.find_template(name, type)
|
96
|
+
templates_dir = Mint.directories[:templates]
|
97
|
+
|
98
|
+
file_name = lambda {|x| x + templates_dir + name + type.to_s }
|
99
|
+
find_files = lambda {|x| Pathname.glob "#{x.to_s}.*" }
|
100
|
+
acceptable = lambda {|x| x.to_s =~ /#{Mint.formats.join '|'}/ }
|
101
|
+
|
102
|
+
Mint.path.
|
103
|
+
map(&file_name).map(&find_files).flatten.
|
104
|
+
select(&acceptable).select(&:exist?).
|
105
|
+
first
|
106
|
+
end
|
107
|
+
|
108
|
+
# Guesses an appropriate name for the resource output file based on
|
109
|
+
# its source file's base name
|
110
|
+
def self.guess_name_from(name)
|
111
|
+
css = Mint.css_formats.join '|'
|
112
|
+
name.basename.to_s.
|
113
|
+
gsub(/(#{css})$/, '.css').
|
114
|
+
gsub(/(\.[^css]+)$/, '.html')
|
115
|
+
end
|
116
|
+
|
117
|
+
# Transforms a path into a template that will render the file specified
|
118
|
+
# at that path
|
119
|
+
def self.renderer(path)
|
120
|
+
Tilt.new path.to_s, :smart => true
|
121
|
+
end
|
122
|
+
|
123
|
+
class Resource
|
124
|
+
attr_accessor :type
|
125
|
+
|
126
|
+
attr_reader :source
|
127
|
+
def source=(source)
|
128
|
+
@source = Pathname.new(source) if source
|
129
|
+
end
|
130
|
+
|
131
|
+
# I haven't tested this - moved empty string from
|
132
|
+
# default options into this method, so that default options
|
133
|
+
# can be uniform - i.e., style_destination and destination
|
134
|
+
# can each be nil to indicate that any rendering will be
|
135
|
+
# done in the same folder the file is already in. I need
|
136
|
+
# to make sure that adding the empty string here actually
|
137
|
+
# keeps us in the current working directory
|
138
|
+
attr_reader :destination
|
139
|
+
def destination=(destination)
|
140
|
+
@destination = Pathname.new(destination || '')
|
141
|
+
end
|
142
|
+
|
143
|
+
attr_reader :name
|
144
|
+
def name=(name)
|
145
|
+
@name = name
|
146
|
+
end
|
147
|
+
|
148
|
+
def renderer=(renderer)
|
149
|
+
@renderer = renderer
|
150
|
+
end
|
151
|
+
|
152
|
+
def initialize(source, type=:resource, options={})
|
153
|
+
return nil unless source
|
154
|
+
|
155
|
+
self.source = source
|
156
|
+
self.type = type
|
157
|
+
self.destination = options[:destination]
|
158
|
+
self.name = Mint.guess_name_from source
|
159
|
+
self.renderer = Mint.renderer source
|
160
|
+
end
|
161
|
+
|
162
|
+
def equal?(other)
|
163
|
+
destination + name == other.destination + other.name
|
164
|
+
end
|
165
|
+
alias_method :==, :equal?
|
166
|
+
|
167
|
+
def render(context=Object.new, args={})
|
168
|
+
# see Tilt TEMPLATES.md for more info
|
169
|
+
@renderer.render context, args
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Layout describes a resource whose type is `:layout`. Beyond its type,
|
174
|
+
# it is a simple resource. However, its type helps decide which template
|
175
|
+
# file to use when a template name is specified.
|
176
|
+
class Layout < Resource
|
177
|
+
def initialize(source, opts=Mint.default_options)
|
178
|
+
super(source, :layout, opts)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Style describes a resource whose type is `:style`. Beyond its type,
|
183
|
+
# it is a simple resource. However, its type helps decide which template
|
184
|
+
# file to use when a template name is specified.
|
185
|
+
class Style < Resource
|
186
|
+
def initialize(source, opts=Mint.default_options)
|
187
|
+
super(source, :style, opts)
|
188
|
+
end
|
189
|
+
|
190
|
+
def needs_rendering?
|
191
|
+
source.extname !~ /\.css$/
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
class Document < Resource
|
196
|
+
include Helpers
|
197
|
+
|
198
|
+
# The following provide reader/accessor methods for the objects's
|
199
|
+
# important attributes. Each implicit reader is paired with an
|
200
|
+
# explicit assignment method that processes a variety of input to a
|
201
|
+
# standardized state.
|
202
|
+
|
203
|
+
# When you set content, you are giving the document a renderer based
|
204
|
+
# on the content file and are processing the templated content into
|
205
|
+
# Html, which you can then access using via the content reader.
|
206
|
+
attr_reader :content
|
207
|
+
def content=(content)
|
208
|
+
meta, body = src.split "\n\n"
|
209
|
+
@inline_style = YAML.load meta
|
210
|
+
@renderer = Mint.renderer body
|
211
|
+
@content = @renderer.render
|
212
|
+
rescue
|
213
|
+
# I want to dry up this part of the code - and maybe look up which
|
214
|
+
# error Yaml will throw if it can't parse the first paragraph
|
215
|
+
# in the content
|
216
|
+
@renderer = Mint.renderer content
|
217
|
+
@content = @renderer.render
|
218
|
+
end
|
219
|
+
|
220
|
+
# The explicit assignment method allows you to pass the document an existing
|
221
|
+
# layout or the name of a layout template in the Mint path or an
|
222
|
+
# existing layout file.
|
223
|
+
attr_reader :layout
|
224
|
+
def layout=(layout)
|
225
|
+
@layout =
|
226
|
+
if layout.respond_to? :render
|
227
|
+
layout
|
228
|
+
else
|
229
|
+
layout_file = Mint.lookup_template layout, :layout
|
230
|
+
Layout.new layout_file
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# The explicit assignment method allows you to pass the document an existing
|
235
|
+
# style or the name of a style template in the Mint path or an
|
236
|
+
# existing style file.
|
237
|
+
attr_reader :style
|
238
|
+
def style=(style)
|
239
|
+
@style =
|
240
|
+
if style.respond_to? :render
|
241
|
+
style
|
242
|
+
else
|
243
|
+
style_file = Mint.lookup_template style, :style
|
244
|
+
Style.new style_file, :destination => destination
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def template=(template)
|
249
|
+
layout, style = template, template if template
|
250
|
+
end
|
251
|
+
|
252
|
+
def initialize(source, opts={})
|
253
|
+
options = Mint.default_options.merge opts
|
254
|
+
super(source, :document, options)
|
255
|
+
|
256
|
+
# Each of these should invoke explicitly defined method
|
257
|
+
self.content = source
|
258
|
+
self.layout = options[:layout]
|
259
|
+
self.style = options[:style]
|
260
|
+
|
261
|
+
# The template option takes precedence over the other two
|
262
|
+
self.template = options[:template]
|
263
|
+
|
264
|
+
self.style.destination =
|
265
|
+
options[:style_destination] || self.style.source.dirname.expand_path
|
266
|
+
end
|
267
|
+
|
268
|
+
def render(args={})
|
269
|
+
layout.render self, args
|
270
|
+
end
|
271
|
+
|
272
|
+
def mint(root=Dir.getwd, render_style=true)
|
273
|
+
root = Pathname.new root
|
274
|
+
|
275
|
+
# Only render style if a) it's specified by the options path and
|
276
|
+
# b) it actually needs rendering (i.e., it's in template form and
|
277
|
+
# not raw, browser-parseable CSS).
|
278
|
+
render_style &&= style.needs_rendering?
|
279
|
+
|
280
|
+
resources = [self]
|
281
|
+
resources << style if render_style
|
282
|
+
|
283
|
+
resources.compact.each do |r|
|
284
|
+
dest = root + r.destination + r.name
|
285
|
+
FileUtils.mkdir_p dest.dirname
|
286
|
+
|
287
|
+
dest.open 'w+' do |f|
|
288
|
+
f << r.render
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
# Convenience methods for views
|
294
|
+
|
295
|
+
# Returns any inline document style that was parsed from the
|
296
|
+
# content file, in the header. For use in view where we want
|
297
|
+
# document-specific Css modifications.
|
298
|
+
def inline_style
|
299
|
+
@inline_style
|
300
|
+
end
|
301
|
+
|
302
|
+
# Returns a relative path from the document to its stylesheet. Can
|
303
|
+
# be called directly from inside a layout template.
|
304
|
+
def stylesheet
|
305
|
+
Helpers.normalize_path(style.destination.expand_path, destination) +
|
306
|
+
style.name.to_s
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 25
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
8
|
+
- 3
|
9
|
+
version: 0.1.3
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- David Jacobs
|
@@ -15,10 +14,22 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date:
|
17
|
+
date: 2011-02-01 00:00:00 -05:00
|
19
18
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: tilt
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
22
33
|
description:
|
23
34
|
email: david@allthingsprogress.com
|
24
35
|
executables:
|
@@ -31,10 +42,10 @@ files:
|
|
31
42
|
- README.md
|
32
43
|
- bin/mint
|
33
44
|
- lib/mint.rb
|
34
|
-
-
|
35
|
-
-
|
45
|
+
- lib/mint/mint.rb
|
46
|
+
- lib/mint/helpers.rb
|
36
47
|
has_rdoc: true
|
37
|
-
homepage: http://github.com/davejacobs/mint
|
48
|
+
homepage: http://github.com/davejacobs/mint
|
38
49
|
licenses: []
|
39
50
|
|
40
51
|
post_install_message:
|
@@ -47,7 +58,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
58
|
requirements:
|
48
59
|
- - ">="
|
49
60
|
- !ruby/object:Gem::Version
|
50
|
-
hash: 3
|
51
61
|
segments:
|
52
62
|
- 0
|
53
63
|
version: "0"
|
@@ -56,7 +66,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
66
|
requirements:
|
57
67
|
- - ">="
|
58
68
|
- !ruby/object:Gem::Version
|
59
|
-
hash: 23
|
60
69
|
segments:
|
61
70
|
- 1
|
62
71
|
- 3
|
@@ -1,21 +0,0 @@
|
|
1
|
-
body
|
2
|
-
font-family: 'Hoefler Text', Georgia, Garamond, serif
|
3
|
-
|
4
|
-
code
|
5
|
-
font-family: Monaco, 'Lucida Console', Consolas, Monotype, mono
|
6
|
-
|
7
|
-
@media screen
|
8
|
-
body
|
9
|
-
font-size: 16px
|
10
|
-
|
11
|
-
#container
|
12
|
-
display: block
|
13
|
-
margin: 1em auto
|
14
|
-
|
15
|
-
@media print
|
16
|
-
body
|
17
|
-
font-size: 12pt
|
18
|
-
margin: 1in 1.25in
|
19
|
-
|
20
|
-
img
|
21
|
-
display: block
|