mint 0.8.0 → 0.10.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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -26
  3. data/README.md +138 -95
  4. data/bin/mint +2 -81
  5. data/config/templates/base/navigation.css +136 -0
  6. data/config/templates/base/print.css +152 -0
  7. data/config/templates/{reset.css → base/reset.css} +1 -1
  8. data/config/templates/base/style.css +117 -137
  9. data/config/templates/base/utilities.css +136 -0
  10. data/config/templates/base/variables.css +124 -0
  11. data/config/templates/basic/style.css +151 -0
  12. data/config/templates/default/layout.erb +33 -3
  13. data/config/templates/default/style.css +95 -164
  14. data/config/templates/magazine/style.css +383 -0
  15. data/config/templates/nord/style.css +105 -220
  16. data/config/templates/nord-dark/style.css +82 -263
  17. data/lib/mint/commandline/parse.rb +144 -0
  18. data/lib/mint/commandline/publish.rb +46 -0
  19. data/lib/mint/commandline/run.rb +30 -0
  20. data/lib/mint/config.rb +162 -0
  21. data/lib/mint/{css.rb → css_dsl.rb} +9 -9
  22. data/lib/mint/css_parser.rb +96 -0
  23. data/lib/mint/document.rb +251 -348
  24. data/lib/mint/document_tree.rb +163 -0
  25. data/lib/mint/exceptions.rb +2 -3
  26. data/lib/mint/helpers.rb +23 -180
  27. data/lib/mint/layout.rb +26 -9
  28. data/lib/mint/renderers/css_renderer.rb +32 -0
  29. data/lib/mint/renderers/erb_renderer.rb +11 -0
  30. data/lib/mint/renderers/markdown_renderer.rb +45 -0
  31. data/lib/mint/style.rb +21 -31
  32. data/lib/mint/template.rb +30 -0
  33. data/lib/mint/version.rb +1 -1
  34. data/lib/mint/workspace.rb +171 -0
  35. data/lib/mint.rb +44 -12
  36. data/man/mint.1 +88 -47
  37. data/spec/cli/README.md +13 -13
  38. data/spec/cli/argument_parsing_spec.rb +103 -131
  39. data/spec/cli/bin_integration_spec.rb +23 -243
  40. data/spec/cli/full_workflow_integration_spec.rb +99 -442
  41. data/spec/cli/original_style_integration_spec.rb +58 -0
  42. data/spec/cli/publish_workflow_spec.rb +72 -70
  43. data/spec/commandline_path_integration_spec.rb +230 -0
  44. data/spec/config_file_integration_spec.rb +362 -0
  45. data/spec/{css_spec.rb → css_dsl_spec.rb} +7 -3
  46. data/spec/css_parser_spec.rb +207 -0
  47. data/spec/document_spec.rb +37 -242
  48. data/spec/flattened_path_spec.rb +150 -0
  49. data/spec/layout_spec.rb +42 -3
  50. data/spec/mint_spec.rb +22 -217
  51. data/spec/path_handling_spec.rb +237 -0
  52. data/spec/run_cli_tests.rb +1 -1
  53. data/spec/spec_helper.rb +3 -10
  54. data/spec/style_spec.rb +31 -56
  55. data/spec/support/cli_helpers.rb +7 -10
  56. data/spec/support/matchers.rb +1 -1
  57. data/spec/template_spec.rb +31 -0
  58. data/spec/workspace_spec.rb +177 -0
  59. metadata +78 -93
  60. data/bin/mint-epub +0 -20
  61. data/config/templates/default/css/style.css +0 -205
  62. data/config/templates/garden/layout.erb +0 -38
  63. data/config/templates/garden/style.css +0 -303
  64. data/config/templates/newspaper/layout.erb +0 -16
  65. data/config/templates/nord/layout.erb +0 -11
  66. data/config/templates/nord-dark/layout.erb +0 -11
  67. data/config/templates/protocol/layout.erb +0 -9
  68. data/config/templates/protocol/style.css +0 -25
  69. data/config/templates/zen/layout.erb +0 -11
  70. data/config/templates/zen/style.css +0 -114
  71. data/lib/mint/command_line.rb +0 -360
  72. data/lib/mint/css_template.rb +0 -37
  73. data/lib/mint/markdown_template.rb +0 -47
  74. data/lib/mint/mint.rb +0 -313
  75. data/lib/mint/plugin.rb +0 -136
  76. data/lib/mint/plugins/epub.rb +0 -293
  77. data/lib/mint/resource.rb +0 -101
  78. data/plugins/templates/epub/layouts/container.haml +0 -5
  79. data/plugins/templates/epub/layouts/content.haml +0 -35
  80. data/plugins/templates/epub/layouts/layout.haml +0 -6
  81. data/plugins/templates/epub/layouts/title.haml +0 -11
  82. data/plugins/templates/epub/layouts/toc.haml +0 -26
  83. data/spec/cli/configuration_management_spec.rb +0 -363
  84. data/spec/cli/template_management_spec.rb +0 -300
  85. data/spec/helpers_spec.rb +0 -249
  86. data/spec/plugin_spec.rb +0 -449
  87. data/spec/resource_spec.rb +0 -135
data/lib/mint/mint.rb DELETED
@@ -1,313 +0,0 @@
1
-
2
- require "pathname"
3
- require "fileutils"
4
- require "yaml"
5
- require "tilt"
6
- require "tilt/mapping"
7
- require "active_support/core_ext/hash/slice"
8
- require "active_support/core_ext/string/output_safety"
9
- require "mint/css_template"
10
- require "mint/markdown_template"
11
-
12
- module Mint
13
- ROOT = (Pathname.new(__FILE__).realpath.dirname + "../..").to_s
14
- MARKDOWN_EXTENSIONS = %w[md markdown mkd].freeze
15
- LOCAL_SCOPE = Pathname.new(".mint")
16
- USER_SCOPE = Pathname.new("~/.config/mint").expand_path
17
- GLOBAL_SCOPE = Pathname.new("#{ROOT}/config").expand_path
18
- SCOPES = { local: LOCAL_SCOPE, user: USER_SCOPE, global: GLOBAL_SCOPE }
19
- SCOPE_NAMES = SCOPES.keys
20
- CONFIG_FILE = "config.yaml"
21
- TEMPLATES_DIRECTORY = "templates"
22
-
23
- def self.default_options
24
- {
25
- root: Dir.getwd,
26
- destination: nil,
27
- style_mode: :inline,
28
- style_destination: nil,
29
- output_file: '#{basename}.#{new_extension}',
30
- layout_or_style_or_template: [:template, 'default'],
31
- scope: :local,
32
- recursive: false,
33
- verbose: false
34
- }
35
- end
36
-
37
- def self.mapping
38
- if @mapping
39
- @mapping
40
- else
41
- @mapping = Tilt::Mapping.new.tap do |m|
42
- m.register Mint::CSSTemplate, 'css' # Inline Css @imports, creating a single file
43
- m.register Mint::MarkdownTemplate, 'txt' # Process Txt as Markdown
44
- m.register Mint::MarkdownTemplate, *MARKDOWN_EXTENSIONS
45
- m.register Tilt::ScssTemplate, 'scss'
46
- m.register Tilt::SassTemplate, 'sass'
47
- m.register Tilt::ERBTemplate, 'erb', 'html' # Allow for Erb inside HTML
48
- m.register Tilt::HamlTemplate, 'haml'
49
- end
50
- end
51
- end
52
-
53
- # Returns an array with the Mint template path for the named scope
54
- # or scopes. This path is used to lookup templates and configuration options.
55
- #
56
- # @param [Array] scopes a list of scopes to include
57
- # @return [Array] the Mint path as an Array of Pathnames
58
- def self.path(scopes = SCOPE_NAMES)
59
- SCOPES.slice(*scopes).values
60
- end
61
-
62
- # Returns the base directory for Mint configuration at the specified scope.
63
- #
64
- # @param [Symbol] scope the scope we want to find the path for
65
- # @return [Pathname] the Mint path for +scope+ as a Pathname
66
- def self.path_for_scope(scope = :local)
67
- SCOPES[scope]
68
- end
69
-
70
- # @return [Array] all file extensions that Tilt will render
71
- def self.formats
72
- mapping.template_map.keys
73
- end
74
-
75
- # @return [Array] CSS formats, for source -> destination
76
- # name guessing/conversion only.
77
- def self.css_formats
78
- ["css", "sass", "scss", "less"]
79
- end
80
-
81
-
82
- # Returns a hash of all active options specified by file (for all scopes).
83
- # That is, if you specify file as "defaults.yaml", this will return the aggregate
84
- # of all defaults.yaml-specified options in the Mint path, where more local
85
- # members of the path take precedence over more global ones.
86
- #
87
- # @param [String] file a filename pointing to a Mint configuration file
88
- # @return [Hash] a structured set of configuration options
89
- def self.configuration(opts={})
90
- opts = { scopes: SCOPE_NAMES }.merge(opts)
91
-
92
- # Merge config options from all config files on the Mint path,
93
- # where more local options take precedence over more global
94
- # options
95
- configuration = Mint.path(opts[:scopes]).
96
- map {|p| p + Mint::CONFIG_FILE }.
97
- select(&:exist?).
98
- map do |p|
99
- begin
100
- YAML.load_file p
101
- rescue Psych::SyntaxError, StandardError => e
102
- {}
103
- end
104
- end.
105
- reverse.
106
- reduce(Mint.default_options) {|r,p| r.merge p }
107
-
108
- Helpers.symbolize_keys configuration
109
- end
110
-
111
- # Returns all configuration options (as specified by the aggregate
112
- # of all config files), along with opts, where opts take precedence.
113
- #
114
- # @param [Hash] additional options to add to the current configuration
115
- # @return [Hash] a structured set of configuration options with opts
116
- # overriding any options from config files
117
- def self.configuration_with(opts)
118
- scopes = if opts[:local] || opts[:user] || opts[:global]
119
- if opts[:local]
120
- [:local]
121
- elsif opts[:user]
122
- [:user]
123
- elsif opts[:global]
124
- [:global]
125
- end
126
- else
127
- SCOPE_NAMES
128
- end
129
-
130
- processed_opts = opts.dup
131
- if processed_opts[:layout_or_style_or_template]
132
- option_type, option_value = processed_opts.delete(:layout_or_style_or_template)
133
- case option_type
134
- when :template
135
- processed_opts[:template] = option_value
136
- when :layout
137
- processed_opts[:layout] = option_value
138
- when :style
139
- processed_opts[:style] = option_value
140
- end
141
- end
142
-
143
- configuration(scopes: scopes).merge processed_opts
144
- end
145
-
146
- # @return [Array] the full path for each known template in the Mint path
147
- def self.templates(scope = :local)
148
- Mint.path([scope]).
149
- map {|p| p + TEMPLATES_DIRECTORY }.
150
- select(&:exist?).
151
- map {|p| p.children.select(&:directory?).map(&:to_s) }.
152
- flatten.
153
- sort
154
- end
155
-
156
- # Returns the template directory for the given template name
157
- #
158
- # @param [String, File, #to_s] name_or_file a name or template file
159
- # to look up
160
- # @param [Symbol] type the resource type to look up
161
- # @return [File] the named, typed template file
162
- def self.lookup_template(name_or_file, type=:layout)
163
- name = name_or_file.to_s
164
-
165
- # Only treat as a direct file if it's an actual file (not directory)
166
- if File.file?(name) && formats.include?(File.extname(name)[1..-1])
167
- Pathname.new(name).dirname
168
- else
169
- Pathname.new(find_template_directory(name))
170
- end
171
- end
172
-
173
- # Returns the layout file for the given template name
174
- #
175
- # @param [String] name the template name to look up
176
- # @return [String] path to the layout file
177
- def self.lookup_layout(name)
178
- find_template(name, :layout)
179
- end
180
-
181
- # Returns the style file for the given template name
182
- #
183
- # @param [String] name the template name to look up
184
- # @return [String] path to the style file
185
- def self.lookup_style(name)
186
- find_template(name, :style)
187
- end
188
-
189
- # Finds a template named `name` in the Mint path. If `type` is :layout,
190
- # will look for `MINT_PATH/templates/template_name/layout.*`. If it is :style, will
191
- # look for `MINT_PATH/templates/template_name/style.*`. Mint assumes
192
- # that a named template will hold only one layout and one style template.
193
- # It does not know how to decide between style.css and style.less, for
194
- # example. For predictable results, only include one template file
195
- # called `layout.*` in the `template_name` directory. Returns nil if
196
- # it cannot find a template.
197
- #
198
- # @param [String, #to_s] name the name of a template to find
199
- # @param [Symbol] type the resource type to find
200
- #
201
- # @return [File] the named, typed template file
202
- def self.find_template(name, type)
203
- file_name = lambda {|x| x + Mint::TEMPLATES_DIRECTORY + name + type.to_s }
204
- find_files = lambda {|x| Pathname.glob "#{x.to_s}.*" }
205
- acceptable = lambda {|x|
206
- ext = File.extname(x.to_s)[1..-1]
207
- return false unless ext
208
- case type
209
- when :layout
210
- formats.include?(ext)
211
- when :style
212
- css_formats.include?(ext)
213
- else
214
- false
215
- end
216
- }
217
-
218
- template_file = Mint.path.
219
- map(&file_name).
220
- map(&find_files).
221
- flatten.
222
- select(&acceptable).
223
- select(&:exist?).
224
- first
225
-
226
- unless template_file
227
- template_dirs = Mint.path.map {|p| p + Mint::TEMPLATES_DIRECTORY + name }.select(&:exist?)
228
- if template_dirs.any?
229
- expected_exts = case type
230
- when :layout then formats.join(', ')
231
- when :style then css_formats.join(', ')
232
- end
233
- raise TemplateNotFoundException, "Template '#{name}' exists but has no valid #{type} file. Expected #{type}.{#{expected_exts}}"
234
- else
235
- raise TemplateNotFoundException, "Template '#{name}' does not exist."
236
- end
237
- end
238
-
239
- template_file.to_s
240
- end
241
-
242
- # Finds a template directory by name
243
- #
244
- # @param [String] name the template name to find
245
- # @return [String] path to the template directory
246
- def self.find_template_directory(name)
247
- template_dir = Mint.path.
248
- map {|p| p + Mint::TEMPLATES_DIRECTORY + name }.
249
- select(&:exist?).
250
- first
251
-
252
- unless template_dir
253
- raise TemplateNotFoundException, "Template '#{name}' does not exist."
254
- end
255
-
256
- template_dir.to_s
257
- end
258
-
259
- # Finds a specific template file by name and type
260
- #
261
- # @param [String] name the template name to find
262
- # @param [Symbol] type :layout or :style
263
- # @return [String] path to the template file
264
- def self.find_template_file(name, type)
265
- find_template(name, type)
266
- end
267
-
268
- # Returns the template directory for the given scope, if found
269
- def self.template_path(name, scope)
270
- Mint.path_for_scope(scope) + "templates/#{name}"
271
- end
272
-
273
- # Checks (non-rigorously) to see if the file is somewhere on the
274
- # MINT_PATH
275
- #
276
- # @param [String, File, #to_s] file the file to look up
277
- # @return [Boolean] true if template file is found in Mint path
278
- def self.template?(file)
279
- paths = Mint.path.map {|f| File.expand_path f }
280
- file_path = Pathname.new(file)
281
- file_path.exist? and
282
- file_path.dirname.expand_path.to_s =~ /#{paths.map(&:to_s).join("|")}/
283
- end
284
-
285
- # Guesses an appropriate name for the resource output file based on
286
- # its source file's base name
287
- #
288
- # @param [String] name source file name
289
- # @return [String] probably output file name
290
- def self.guess_name_from(name)
291
- name = Pathname(name).basename if name
292
- css = Mint.css_formats.join "|"
293
- name.to_s.
294
- gsub(/\.(#{css})$/, ".css").
295
- gsub(/(\.(?!css).*)$/, ".html")
296
- end
297
-
298
- # Transforms a path into a template that will render the file specified
299
- # at that path
300
- #
301
- # @param [Path, File, String, #to_s] path the file to render
302
- def self.renderer(path)
303
- mapping.new path.to_s
304
- end
305
-
306
- # Publishes a Document object according to its internal specifications.
307
- #
308
- # @param [Document] document a Mint document
309
- # @return [void]
310
- def self.publish!(document, opts={})
311
- document.publish! opts
312
- end
313
- end
data/lib/mint/plugin.rb DELETED
@@ -1,136 +0,0 @@
1
- require "set"
2
- require "mint/document"
3
-
4
- module Mint
5
- def self.plugins
6
- @@plugins ||= Set.new
7
- @@plugins.to_a
8
- end
9
-
10
- def self.activated_plugins
11
- @@activated_plugins ||= Set.new
12
- @@activated_plugins.to_a
13
- end
14
-
15
- def self.register_plugin!(plugin)
16
- @@plugins ||= Set.new
17
- @@plugins << plugin
18
- end
19
-
20
- def self.activate_plugin!(plugin)
21
- @@activated_plugins ||= Set.new
22
- @@activated_plugins << plugin
23
- end
24
-
25
- def self.clear_plugins!
26
- defined?(@@plugins) && @@plugins.clear
27
- defined?(@@activated_plugins) && @@activated_plugins.clear
28
- end
29
-
30
- def self.template_directory(plugin)
31
- Mint::ROOT + "/plugins/templates/" + plugin.underscore
32
- end
33
-
34
- def self.config_directory(plugin)
35
- Mint::ROOT + "/plugins/config/" + plugin.underscore
36
- end
37
-
38
- def self.commandline_options_file(plugin)
39
- plugin.config_directory + "/syntax.yml"
40
- end
41
-
42
- def self.commandline_name(plugin)
43
- plugin.underscore
44
- end
45
-
46
- def self.before_render(plain_text, opts={})
47
- active_plugins = opts[:plugins] || Mint.activated_plugins
48
- active_plugins.reduce(plain_text) do |intermediate, plugin|
49
- plugin.before_render(intermediate)
50
- end
51
- end
52
-
53
- def self.after_render(html_text, opts={})
54
- active_plugins = opts[:plugins] || Mint.activated_plugins
55
- active_plugins.reduce(html_text) do |intermediate, plugin|
56
- plugin.after_render(intermediate)
57
- end
58
- end
59
-
60
- def self.after_publish(document, opts={})
61
- active_plugins = opts[:plugins] || Mint.activated_plugins
62
- active_plugins.each do |plugin|
63
- plugin.after_publish(document)
64
- end
65
- end
66
-
67
- class Plugin
68
- def self.inherited(plugin)
69
- Mint.register_plugin! plugin
70
- end
71
-
72
- def self.underscore(opts={})
73
- opts[:ignore_prefix] ||= true
74
- Helpers.underscore self.name, :ignore_prefix => opts[:ignore_prefix]
75
- end
76
-
77
- def self.template_directory
78
- Mint.template_directory(self)
79
- end
80
-
81
- def self.config_directory
82
- Mint.config_directory(self)
83
- end
84
-
85
- def self.commandline_options_file
86
- Mint.commandline_options_file(self)
87
- end
88
-
89
- def self.commandline_name
90
- Mint.commandline_name(self)
91
- end
92
-
93
- # Supports:
94
- # - Change raw text
95
- #
96
- # Use cases:
97
- # - Add footnote syntax on top of Markdown
98
- # - Perform text analysis for use in later callbacks (?)
99
- def self.before_render(text_document)
100
- text_document
101
- end
102
-
103
- # Supports:
104
- # - Change preview HTML
105
- #
106
- # Use cases:
107
- # - Transform elements based on position or other HTML attributes
108
- # For example: Add a class to the first paragraph of a document if it is
109
- # italicized
110
- #
111
- # Questions:
112
- # - Could I allow jQuery use here?
113
- def self.after_render(html_document)
114
- html_document
115
- end
116
-
117
- # Supports:
118
- # - Change file, filesystem once written
119
- # - Automatic cleanup of intermediate files, including all edge cases
120
- # currently covered by transformation library. (For example, if I generated
121
- # a CSS file but am ultimately generating a PDF, I would want to have
122
- # an automatic way to delete that CSS file.)
123
- #
124
- # Use cases:
125
- # - Zip set of documents into ePub and create manifest
126
- # - Change file extension
127
- # - Generate PDF from emitted HTML and get rid of intermediate files
128
- # - Generate .doc (or any other OO UNO format) and get rid of intermediate files
129
- #
130
- # NOTE: Unlike the other two callbacks, this doesn't use the result of
131
- # the callback expression for anything. This callback is purely for
132
- # side effects like rearranging the file system.
133
- def self.after_publish(document)
134
- end
135
- end
136
- end