mint 0.2 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  *The following is a **rough draft** of the current Mint design, along with my future plans for the library and tool. The templates are not all there yet (that's the next step) and my first plugins aren't quite there. That said, I'm excited about where this library is going to go.*
2
2
 
3
+ **Mint requires Ruby 1.9.**
4
+
3
5
  If I believed in slogans...
4
6
  ---------------------------
5
7
 
@@ -18,16 +20,6 @@ Mint manages your documents in a decentralized but consistent way. It frees you
18
20
 
19
21
  In a few more: *Mint processes words so you don't have to.*
20
22
 
21
- Table of contents
22
- -----------------
23
-
24
- I. Use cases
25
- II. The Mint library
26
- III. Designing a template
27
- IV. The Mint path
28
- V. The `mint` command
29
- VI. Future directions and tools
30
-
31
23
  I. Use cases
32
24
  ------------
33
25
 
@@ -37,6 +29,8 @@ I. Use cases
37
29
 
38
30
  3. Marina wants to convert all her proprietary processed documents to Markdown for future compatibility, but wants to share these documents with friends at work. Interoperability is important here. The friends should be able to easily view *and* edit *and* annotate all documents. Marina will be happiest if she has a simple GUI that can export documents to an open-source document format that's interoperable with word processors.
39
31
 
32
+ 4. Santosh stores his blog entries in Markdown and wants to see how they look using his blog engine's stylesheet. He doesn't want to upload his entry until he's finished with it, but he wants to preview it with that stylesheet along the way.
33
+
40
34
  II. The Mint library
41
35
  --------------------
42
36
 
@@ -46,12 +40,12 @@ This section discusses the Mint library API. This library encapsulates the idea
46
40
 
47
41
  Mint is loaded with smart defaults, so if you don't want to configure something--say, the basic HTML skeleton of your document or the output directory--you don't have to. You'll probably be surprised at how easy it is to use out of the box, and how configurable it is.
48
42
 
49
- document = Document.new '~/Documents/Minimalism.md'
43
+ document = Document.new 'Minimalism.md'
50
44
  document.mint
51
45
 
52
46
  And voilà, Minimalism.html will show up next to Minimalism.md.
53
47
 
54
- Opening Minimalism.html with your favorite web browser--[Firefox is best for typography][Firefox typography], but Webkit-based browsers (Chrome, Safari) work, too--will show what looks like a word processed document, complete with big bolded headers, italic emphasis, automatically indented and numbered lists, and bullets. If you're in a modern browser, you'll even see ligatures and proper kerning. The page will be on a white canvas that looks like a page, even though you are in a browser.
48
+ Opening Minimalism.html with your favorite web browser--[Firefox is best for typography][Firefox typography], but Webkit-based browsers (Chrome, Safari) work, too--will show what looks like a word-processed document, complete with big bold headers, italic emphasis, automatically indented and numbered lists, and bullets. If you're in a modern browser, you'll even see ligatures and proper kerning. The page will be on a white canvas that looks like a page, even though you are in a browser.
55
49
 
56
50
  Sending that page to a printer is as easy as clicking "Print" from your browser. What comes out of your printer will have a 12 pt base font, normal margins, and a not-too-cramped baseline. (Ah the wonder of print stylesheets.)
57
51
 
@@ -69,14 +63,14 @@ You can pass any of the following to a new document:
69
63
 
70
64
  Defaults:
71
65
 
72
- :template => 'default'
66
+ :template => 'default'
73
67
 
74
68
  Notes:
75
69
 
76
70
  1. If you specify a template name here, Mint will search its paths in order (see **The Mint Path** for more details) for a template with that name. A template file looks like the following:
77
71
 
78
- ${MINT_PATH}/templates/template_name/style.css
79
- ${MINT_PATH}/templates/template_name/layout.haml
72
+ ${MINT_PATH}/templates/template_name/style.css
73
+ ${MINT_PATH}/templates/template_name/layout.haml
80
74
 
81
75
  2. If you specify a template name that is also the name of an existing file in your working directory, Mint will use the file and not look for a template. (It is unlikely you'll have an extension-less file named 'normal' or 'default' in your working directory, so don't worry about this edge case.) If you do specify an existing file, the path/file will be resolved from the directory where you're calling Mint (the 'working directory'). To use Mint this way (and I don't see this as more than a temporary solution) you'll probably want to call Mint from within your source's directory. Alternatively, you can use [`Dir.chdir`][Dir::chdir method] for the same effect.
82
76
 
@@ -84,14 +78,14 @@ You can pass any of the following to a new document:
84
78
 
85
79
  Defaults:
86
80
 
87
- :destination => nil
88
- :style_destination => nil
81
+ :destination => nil
82
+ :style_destination => nil
89
83
 
90
84
  Notes:
91
85
 
92
86
  1. `:destination` *must* refer to a directory (existing or not) and not a file.
93
87
 
94
- 2. `:style_destination` is resolved relative to `:destination` so that packaging styles inside document directories is easy. (This supports the common case where you will want a subdirectory called 'styles' to hold your style files.) When `:style_destination` is nil (default), the stylesheet will not be copied anywhere. Instead, your document will link to the rendered stylesheet in place. If `:style_destination` is 'inline', your style will be included inline with your published document.
88
+ 2. `:style_destination` is resolved relative to `:destination` so that packaging styles inside document directories is easy. (This supports the common case where you will want a subdirectory called 'styles' to hold your style files.) When `:style_destination` is nil (default), the stylesheet will not be copied anywhere. Instead, your document will link to the rendered stylesheet in place. If it needs to be rendered, it will be rendered into a subdirectory called 'css' so that the rendered document isn't picked up the next time you specify the same style.
95
89
 
96
90
  ### Examples ###
97
91
 
@@ -100,21 +94,21 @@ At this point, a couple of examples may be useful.
100
94
  The following are possible:
101
95
 
102
96
  include Mint
103
- content = '~/Documents/Minimalism.md'
97
+ content = 'Minimalism.md'
104
98
 
105
99
  Document.new content
106
- Document.new content, :destination => 'directory', :style => 'serif-pro'
100
+ Document.new content, :destination => 'output',
101
+ :style => 'serif-pro'
107
102
  Document.new content, :style => Style.new(:normal)
108
103
 
109
104
  Style.new 'normal'
110
105
  Style.new :normal
111
- Style.new '~/Sites/Common Styles/normal.css', :destination => 'styles'
106
+ Style.new '~/Sites/Common Styles/normal.css',
107
+ :destination => 'styles'
112
108
  Style.new '~/Sites/Common Styles/normal.css',
113
109
  :style_destination => 'inline'
114
110
  Style.new 'Common Styles/normal.css'
115
111
 
116
- > Note: A style's destination is specified as `:destination` when passed directly to the file or as `:style_destination` when passed to a document or project
117
-
118
112
  If block-style initiation is your thing:
119
113
 
120
114
  Document.new content do |d|
@@ -122,27 +116,7 @@ If block-style initiation is your thing:
122
116
  d.template = 'resume'
123
117
  end
124
118
 
125
- > Note: Block-style indentation passes the block to you *after* initializing
126
- > the document with default values. So you do not need to worry about
127
- > specifying each argument. Anything you specify will override what
128
- > is already there.
129
-
130
- One warning: when you initialize a document via a block, do not try
131
- the following:
132
-
133
- Document.new content do |d|
134
- # The wrong way to block-initialize a style destination:
135
- d.style_destination = 'styles'
136
- end
137
-
138
- Because `:style_destination` translates internally to `:destination` (so that it can be passed to the style initializer), setting `:style_destination` is meaningless in a document block. Instead, you should do the following:
139
-
140
- Document.new content do |d|
141
- # The right way to block-initialize a style destination:
142
- d.style.destination = 'styles'
143
- end
144
-
145
- *(Should this change? Maybe I'll fix that.)*
119
+ Block-style indentation passes the block to you *after* initializing the document with default values. So you do not need to worry about specifying each argument. Anything you specify will override what is already there.
146
120
 
147
121
  [Dir::chdir method]: http://ruby-doc.org/core/classes/Dir.html#M002314 "You can change the current directory context with Dir::chdir(path)"
148
122
 
@@ -291,7 +265,7 @@ Other options have nothing to do with document configuration but are there for c
291
265
 
292
266
  Not all commandline arguments will be read as files. `mint` has a certain vocabulary that you can use, for example, to manipulate configuration options or edit layout files.
293
267
 
294
- Currently, the `mint` vocabulary consists of `set`, `edit`, and `config`.
268
+ Currently, the `mint` vocabulary consists of `set`, `edit`, and `config`. (Coming soon: `install` and `package`.)
295
269
 
296
270
  ### `mint` configuration ###
297
271
 
@@ -350,8 +324,8 @@ Inside of a directory, you can edit any stylesheet or document template that wou
350
324
 
351
325
  Mint will open the appropriate file in the editor specified by EDITOR. The same short forms listed earlier apply here:
352
326
 
353
- mint edit -L normal
354
- mint edit -S normal
327
+ mint edit -l normal
328
+ mint edit -s normal
355
329
 
356
330
  VI. The future of Mint
357
331
  ----------------------
@@ -366,4 +340,5 @@ Not everyone wants to code an entire stylesheet every time he wants a new look.
366
340
 
367
341
  Sometimes, it may be useful to "finalize" the design of a document, for example, with publications. The best way I can think of to do this is to package the document's output file with its style inline. To do so, simply add the package option:
368
342
 
343
+ # Note: I haven't implemented this yet
369
344
  mint package document.md
@@ -38,10 +38,10 @@ Feature: Mint document with varying options at the command line
38
38
  And the file "content.html" should contain "<style file>"
39
39
 
40
40
  Examples:
41
- | template | layout | style | style file |
42
- | | | | ../../templates/default/style.css |
43
- | -t pro | | | ../../templates/pro/style.css |
44
- | | -l pro | -s pro | ../../templates/pro/style.css |
41
+ | template | layout | style | style file |
42
+ | | | | ../../templates/default/css/style.css |
43
+ | -t pro | | | ../../templates/pro/css/style.css |
44
+ | | -l pro | -s pro | ../../templates/pro/css/style.css |
45
45
 
46
46
  Scenario: Mint document with non-existent template
47
47
  When I run "mint -t nonexistent content.md"
@@ -1,5 +1,10 @@
1
1
  require 'mint/helpers'
2
2
  require 'mint/mint'
3
+ require 'mint/resource'
4
+ require 'mint/layout'
5
+ require 'mint/style'
6
+ require 'mint/document'
3
7
  require 'mint/version'
4
8
  require 'mint/css'
5
9
  require 'mint/commandline'
10
+ require 'mint/exceptions'
@@ -41,7 +41,6 @@ module Mint
41
41
  # FileUtils.copy file, directory
42
42
  # end
43
43
 
44
-
45
44
  # If we get the edit command, will retrieve appropriate file
46
45
  # (probably a Mint template) and shell out that file to
47
46
  # the user's favorite editor.
@@ -58,7 +57,6 @@ module Mint
58
57
  Helpers.ensure_directory config_directory
59
58
  Helpers.update_yaml opts, config_file
60
59
  end
61
-
62
60
 
63
61
  # Try to set a config option (at the specified scope) per
64
62
  # the user's command.
@@ -4,8 +4,8 @@ module Mint
4
4
  'container'
5
5
  end
6
6
 
7
- # Mappings from "DSL" to actual CSS. The plan is to translate
8
- # this into something like:
7
+ # Mappings from "DSL" to actual CSS. This is not yet implemented, but
8
+ # the plan is to translate this into something like:
9
9
  #
10
10
  # #container {
11
11
  # font: (value specified and cleaned up)
@@ -0,0 +1,136 @@
1
+ require 'mint/resource'
2
+ require 'mint/layout'
3
+ require 'mint/style'
4
+
5
+ module Mint
6
+ class Document < Resource
7
+ # The following provide reader/accessor methods for the objects's
8
+ # important attributes. Each implicit reader is paired with an
9
+ # explicit assignment method that processes a variety of input to a
10
+ # standardized state.
11
+
12
+ # When you set content, you are giving the document a renderer based
13
+ # on the content file and are processing the templated content into
14
+ # Html, which you can then access using via the content reader.
15
+ attr_reader :content
16
+ def content=(content)
17
+ @renderer = Mint.renderer content
18
+ @content = @renderer.render
19
+ end
20
+
21
+ # The explicit assignment method allows you to pass the document an existing
22
+ # layout or the name of a layout template in the Mint path or an
23
+ # existing layout file.
24
+ attr_reader :layout
25
+ def layout=(layout)
26
+ @layout =
27
+ if layout.respond_to? :render
28
+ layout
29
+ else
30
+ layout_file = Mint.lookup_template layout, :layout
31
+ Layout.new layout_file
32
+ end
33
+ rescue TemplateNotFoundException
34
+ abort "Template '#{layout}' does not exist."
35
+ end
36
+
37
+ # The explicit assignment method allows you to pass the document an existing
38
+ # style or the name of a style template in the Mint path or an
39
+ # existing style file.
40
+ attr_reader :style
41
+ def style=(style)
42
+ @style =
43
+ if style.respond_to? :render
44
+ style
45
+ else
46
+ style_file = Mint.lookup_template style, :style
47
+ Style.new style_file
48
+ end
49
+ rescue TemplateNotFoundException
50
+ abort "Template '#{style}' does not exist."
51
+ end
52
+
53
+ # I'm going to maintain a document's official style_destination
54
+ # outside of its style object. If a document has no
55
+ # style_destination defined when it needs one, the document will
56
+ # use the style's source directory. This eliminates edge cases
57
+ # nicely and lets us maintain document-specific information
58
+ # separately. (Without this separation, funky things happen when
59
+ # you assign a new style template to an existing document -- if
60
+ # you had specified a custom style_destination before changing
61
+ # the template, that custom destination would be overridden.
62
+
63
+ attr_reader :style_destination
64
+ def style_destination=(style_destination)
65
+ @style_destination = style_destination
66
+ end
67
+
68
+ def template=(template)
69
+ if template
70
+ self.layout = template
71
+ self.style = template
72
+ end
73
+ end
74
+
75
+ def initialize(source, opts={})
76
+ options = Mint.default_options.merge opts
77
+ super(source, :document, options)
78
+
79
+ # Each of these should invoke explicitly defined method
80
+ self.content = source
81
+ self.layout = options[:layout]
82
+ self.style = options[:style]
83
+ self.style_destination = options[:style_destination]
84
+
85
+ # The template option will override layout and style choices
86
+ self.template = options[:template]
87
+
88
+ yield self if block_given?
89
+ end
90
+
91
+ def render(args={})
92
+ layout.render self, args
93
+ end
94
+
95
+ def mint(root=Dir.getwd, render_style=true)
96
+ root = Pathname.new root
97
+
98
+ # Only render style if a) it's specified by the options path and
99
+ # b) it actually needs rendering (i.e., it's in template form and
100
+ # not raw, browser-parseable CSS).
101
+ render_style &&= style.need_rendering?
102
+
103
+ document_file = root + (self.destination || '') + self.name
104
+ FileUtils.mkdir_p document_file.dirname
105
+ document_file.open 'w+' do |f|
106
+ f << self.render
107
+ end
108
+
109
+ if render_style
110
+ style_dest =
111
+ if style_destination
112
+ root + self.destination + style_destination
113
+ else
114
+ self.style.destination
115
+ end
116
+ style_file = style_dest + self.style.name
117
+ FileUtils.mkdir_p style_file.dirname
118
+
119
+ style_file.open 'w+' do |f|
120
+ f << self.style.render
121
+ end
122
+ end
123
+ end
124
+
125
+ # Convenience methods for views
126
+
127
+ # Returns a relative path from the document to its stylesheet. Can
128
+ # be called directly from inside a layout template.
129
+ def stylesheet
130
+ style_dest = self.style_destination || self.style.destination
131
+ destination = self.destination || ''
132
+ Helpers.normalize_path(style_dest, destination) +
133
+ style.name.to_s
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,12 @@
1
+ require 'mint/resource'
2
+
3
+ module Mint
4
+ # Layout describes a resource whose type is `:layout`. Beyond its type,
5
+ # it is a simple resource. However, its type helps decide which template
6
+ # file to use when a template name is specified.
7
+ class Layout < Resource
8
+ def initialize(source, opts=Mint.default_options)
9
+ super(source, :layout, opts)
10
+ end
11
+ end
12
+ end
@@ -3,8 +3,9 @@ require 'fileutils'
3
3
  require 'yaml'
4
4
  require 'tilt'
5
5
 
6
- module Mint
6
+ require 'mint/exceptions'
7
7
 
8
+ module Mint
8
9
  # Assume that someone using an Html template has formatted it
9
10
  # in Erb and that a Css stylesheet will pass untouched through
10
11
  # a Less parser.
@@ -89,7 +90,7 @@ module Mint
89
90
  File.exist?(name) ? Pathname.new(name) : find_template(name, type)
90
91
  end
91
92
 
92
- # Finds a template named `name` in the Mint path. If `type` # is :layout,
93
+ # Finds a template named `name` in the Mint path. If `type` is :layout,
93
94
  # will look for `${MINT_PATH}/templates/layout.*`. If it is :style, will
94
95
  # look for `${MINT_PATH}/templates/template_name/style.*`. Mint assumes
95
96
  # that a named template will hold only one layout and one style template.
@@ -104,10 +105,11 @@ module Mint
104
105
  find_files = lambda {|x| Pathname.glob "#{x.to_s}.*" }
105
106
  acceptable = lambda {|x| x.to_s =~ /#{Mint.formats.join '|'}/ }
106
107
 
107
- Mint.path.
108
- map(&file_name).map(&find_files).flatten.
109
- select(&acceptable).select(&:exist?).
110
- first
108
+ template = Mint.path.map(&file_name).map(&find_files).flatten.
109
+ select(&acceptable).select(&:exist?).first
110
+ raise TemplateNotFoundException unless template
111
+
112
+ template
111
113
  end
112
114
 
113
115
  # Guesses an appropriate name for the resource output file based on
@@ -123,195 +125,6 @@ module Mint
123
125
  # Transforms a path into a template that will render the file specified
124
126
  # at that path
125
127
  def self.renderer(path)
126
- Tilt.new path.to_s, :smart => true
127
- end
128
-
129
- class Resource
130
- attr_accessor :type
131
-
132
- attr_reader :source
133
- def source=(source)
134
- @source = Pathname.new(source) if source
135
- end
136
-
137
- # I haven't tested this - moved empty string from
138
- # default options into this method, so that default options
139
- # can be uniform - i.e., style_destination and destination
140
- # can each be nil to indicate that any rendering will be
141
- # done in the same folder the file is already in. I need
142
- # to make sure that adding the empty string here actually
143
- # keeps us in the current working directory
144
- attr_reader :destination
145
- def destination=(destination)
146
- @destination = Pathname.new(destination || '')
147
- end
148
-
149
- attr_reader :name
150
- def name=(name)
151
- @name = name
152
- end
153
-
154
- def renderer=(renderer)
155
- @renderer = renderer
156
- end
157
-
158
- def initialize(source, type=:resource, options={})
159
- return nil unless source
160
-
161
- self.source = source
162
- self.type = type
163
- self.destination = options[:destination]
164
- self.name = Mint.guess_name_from source
165
- self.renderer = Mint.renderer source
166
- end
167
-
168
- def equal?(other)
169
- destination + name == other.destination + other.name
170
- end
171
- alias_method :==, :equal?
172
-
173
- def render(context=Object.new, args={})
174
- # see Tilt TEMPLATES.md for more info
175
- @renderer.render context, args
176
- end
177
- end
178
-
179
- # Layout describes a resource whose type is `:layout`. Beyond its type,
180
- # it is a simple resource. However, its type helps decide which template
181
- # file to use when a template name is specified.
182
- class Layout < Resource
183
- def initialize(source, opts=Mint.default_options)
184
- super(source, :layout, opts)
185
- end
186
- end
187
-
188
- # Style describes a resource whose type is `:style`. Beyond its type,
189
- # it is a simple resource. However, its type helps decide which template
190
- # file to use when a template name is specified.
191
- class Style < Resource
192
- def initialize(source, opts=Mint.default_options)
193
- super(source, :style, opts)
194
- end
195
-
196
- def needs_rendering?
197
- source.extname !~ /\.css$/
198
- end
199
- end
200
-
201
- class Document < Resource
202
- # The following provide reader/accessor methods for the objects's
203
- # important attributes. Each implicit reader is paired with an
204
- # explicit assignment method that processes a variety of input to a
205
- # standardized state.
206
-
207
- # When you set content, you are giving the document a renderer based
208
- # on the content file and are processing the templated content into
209
- # Html, which you can then access using via the content reader.
210
- attr_reader :content
211
- def content=(content)
212
- @renderer = Mint.renderer content
213
- @content = @renderer.render
214
- end
215
-
216
- # The explicit assignment method allows you to pass the document an existing
217
- # layout or the name of a layout template in the Mint path or an
218
- # existing layout file.
219
- attr_reader :layout
220
- def layout=(layout)
221
- @layout =
222
- if layout.respond_to? :render
223
- layout
224
- else
225
- layout_file = Mint.lookup_template layout, :layout
226
- Layout.new layout_file
227
- end
228
- end
229
-
230
- # The explicit assignment method allows you to pass the document an existing
231
- # style or the name of a style template in the Mint path or an
232
- # existing style file.
233
- attr_reader :style
234
- def style=(style)
235
- # Before setting this document's style to a new one, save
236
- # the current style destination, if it exists
237
- destination = @style ? @style.destination : ''
238
-
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
- if template
250
- self.layout = template
251
- self.style = template
252
- end
253
- end
254
-
255
- # Convenience methods for reaching into a document's style
256
- # via a unified interface
257
- def style_destination=(style_destination)
258
- self.style.destination = style_destination if self.style
259
- end
260
-
261
- def style_destination
262
- self.style.destination
263
- end
264
-
265
- def initialize(source, opts={})
266
- options = Mint.default_options.merge opts
267
- super(source, :document, options)
268
-
269
- # Each of these should invoke explicitly defined method
270
- self.content = source
271
- self.layout = options[:layout]
272
- self.style = options[:style]
273
-
274
- # The template option will override layout and style choices
275
- self.template = options[:template]
276
-
277
- self.style_destination =
278
- options[:style_destination] || self.style.source.dirname.expand_path
279
-
280
- yield self if block_given?
281
- end
282
-
283
- def render(args={})
284
- layout.render self, args
285
- end
286
-
287
- def mint(root=Dir.getwd, render_style=true)
288
- root = Pathname.new root
289
-
290
- # Only render style if a) it's specified by the options path and
291
- # b) it actually needs rendering (i.e., it's in template form and
292
- # not raw, browser-parseable CSS).
293
- render_style &&= style.needs_rendering?
294
-
295
- resources = [self]
296
- resources << style if render_style
297
-
298
- resources.compact.each do |r|
299
- dest = root + r.destination + r.name
300
- FileUtils.mkdir_p dest.dirname
301
-
302
- dest.open 'w+' do |f|
303
- f << r.render
304
- end
305
- end
306
- end
307
-
308
- # Convenience methods for views
309
-
310
- # Returns a relative path from the document to its stylesheet. Can
311
- # be called directly from inside a layout template.
312
- def stylesheet
313
- Helpers.normalize_path(style.destination, destination) +
314
- style.name.to_s
315
- end
128
+ Tilt.new path.to_s, :smart => true, :ugly => true
316
129
  end
317
130
  end