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