deplot 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/LICENSE +1 -1
  2. data/README.md +142 -36
  3. data/bin/deplot +298 -525
  4. data/deplot.gemspec +8 -4
  5. metadata +60 -61
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 Cyril Nusko
1
+ Copyright (c) 2013 Cyril Nusko
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
data/README.md CHANGED
@@ -1,63 +1,169 @@
1
- deplot
2
- ======
1
+ # deplot
3
2
 
4
- Deplot is a static web site generator with a ruby DSL.
3
+ Deplot is a lightweight and very extensible static web site generator written in ruby.
5
4
 
6
- Intention
7
- ---------
5
+ ## Intention
8
6
 
9
- Deplot is intended to simplify the progress of creating and maintaining a static web site. Its main advantages are:
7
+ Deplot is intended to simplify the process of creating and maintaining a static web site. Its simple DSL makes it easy to describe and understand the structure of a web site, while giving you power over every part of the building process.
10
8
 
11
- * Separating content from markup with layout (template) files
12
- * Independency from specific markup languages by using [tilt][tilt] in both layout and content files
13
- * Simplifying the design/development workflow with a pre-built Guardfile that allows [guard][guard] to recompile any asset or the whole project if a source file changes.
14
- * Easy deployment with a folder structure ready for [git-ftp][git-ftp]
9
+ ## Using deplot
15
10
 
16
- Installation and usage
17
- -----
11
+ ### Installing
18
12
 
19
- Install the deplot gem via rubygems.org: `gem install deplot`. Or build it directly from the sources with `gem build deplot.gemspec; gem install deplot-0.0.x.gem` in the cloned repo. For both `gem install` commands, admin rights may be required.
13
+ The current deplot gem is published on rubygems.org, so you only need to type the following command into your favorite shell (`sudo` may be necessary, depending on your setup):
20
14
 
21
- If the deplot gem is installed, calling `deplot new <project_name>` will create a project directory with all the files and directories needed to get a new site started. You can also use an existing skeleton with `deplot new <project_name> <git_url>`, which will clone the specified git repo. Deplot's built upon a custom DSL that's used to describe your site's pages (in the `Deplotfile`):
15
+ ```
16
+ $ gem install deplot
17
+ ```
18
+
19
+ ### The structure of a deplot project
20
+
21
+ A standard deplot project consists of a folder (the *root folder*) with the following structure:
22
+
23
+ ```
24
+ - assets/
25
+ - Deplotfile
26
+ - documents/
27
+ - media/
28
+ - modules/
29
+ ```
30
+
31
+ Only the Deplotfile is necessary for deplot to run without errors; but in order to build a website, you probably need some content. By default, all output goes to this *root* directory: as soon as you build the project, the root folder will contain a lot more folders and files.
32
+
33
+ ### A simple example
34
+
35
+ The core of a deplot project, the `Deplotfile`, uses the mentioned DSL that makes it easy to understand the different processes to build the website.
36
+
37
+ For example, if you were to set up a blog with one page per blog post and a collection of posts on the front page, you could write this simple code:
38
+
39
+ ```
40
+ documents_in "posts" do
41
+ collect_in "index.html"
42
+ output_to "posts"
43
+ end
44
+ ```
45
+
46
+ Now every post in `documents/posts/` is first being collected in `index.html` and then rendered into its single page, `posts/<filename>.html`.
47
+
48
+ To make this work, you first need to install the deplot gem and invoke deplot like this:
49
+
50
+ ```
51
+ $ deplot make
52
+ ```
53
+
54
+ Deplot uses [tilt][tilt] to render all content and layout files and is therefore able to process almost anything from ERB to Markdown.
55
+
56
+ ### Command reference
57
+
58
+ #### Render blocks
59
+
60
+ The top-level **render blocks** are built using the two methods `documents_in` (as seen in the previous example) and `media_in`. They are called with two arguments: the path to the folder containing the source files (relative to `documents/` and `media/`, respectively) and a block that contains all the instructions for rendering the sources. At the moment, `media_in` is currently only able to filter and copy files:
61
+
62
+ ```
63
+ media_in "images" do
64
+ filter :only => [/.*.png$/]
65
+ copy_to "img"
66
+ end
67
+ ```
68
+
69
+ #### Inline render blocks
70
+
71
+ There are situations in which you may want to render multiple sets of files to different parts of your website (a newsticker in the sidebar, for example). The two commands `output_documents_in` and `collect_documents_in` will take care of this by returning the rendered content as array and string, respectively. In the following example, both layout and content files could then make use of the variable "@news":
22
72
 
23
- ```ruby
24
- path "/" do
25
- render "index.markdown"
73
+ ```
74
+ documents_in "pages" do
75
+ @news = collect_documents_in "news"
76
+ output_to "/"
26
77
  end
27
78
  ```
28
79
 
29
- You can create multiple pages from multiple source files with `render_all` (the `#` is replaced by the file name with `.html` extension):
80
+ #### copy_to (media only)
81
+
82
+ `copy_to` does exactly what you would expect of it: it copies the source files into the specified directory.
83
+
84
+ #### output_to (documents only)
85
+
86
+ `output_to` is the equivalent to `copy_to` in that it renders every source into a single file in the given directory. Unlike `copy_to`, it is able to take a block as last argument that can be used for instructions *specific to this output directory*.
87
+
88
+ #### collect_in (documents only)
89
+
90
+ `collect_in` concatenates all the rendered files and writes them to a single file. Like `output_to`, it can be called with a block (the `apply` example makes use of this feature).
91
+
92
+ #### filter
93
+
94
+ The `filter` command is available for both media and document renderers and is used to filter out files from the specified sources. It can be used in two ways:
95
+
96
+ ```
97
+ filter :only => [/.*.markdown$/]
98
+ filter :exclude => [/.*.erb$/]
99
+ ```
100
+
101
+ #### apply
102
+
103
+ The mightiest of all commands, `apply`, can be used to execute custom code (so-called *modules*) in the context of the current set of sources. Modules are searched for in the `modules/` folder of your project and need to be included in the Deplotfle (`use :teaser` for `teaser.rb`). For our basic blog, we may want to shorten the text displayed on the front page and display a link to the post page:
30
104
 
31
- ```ruby
32
- path "/blog/#" do # will create /blog/<file_name>.html
33
- render_all "blog/"
105
+ ```
106
+ class Teaser < DeplotPreprocessor
107
+ def preprocess source, arguments
108
+ link = "posts/" + File.basename(source[:filename]).gsub(/\.md/, ".html")
109
+ source[:content] = "#{source[:content][0..40]}… <a href=\"#{link}\">Read on &raquo;</a>"
110
+ end
34
111
  end
35
112
  ```
36
113
 
37
- or create an index file from multiple sources:
114
+ Now we can include this preprocessor to be used for `index.html` as follows:
115
+
116
+ ```
117
+ use :teaser
38
118
 
39
- ```ruby
40
- path "/blog/" do # will create /blog/index.html
41
- render_all "blog/"
119
+ documents_in "posts" do
120
+ collect_in "index.html" do
121
+ apply :teaser
122
+ end
123
+ output_to "posts"
42
124
  end
43
125
  ```
44
126
 
45
- Deplot uses [tilt][tilt] to render the source and layout file/s, so it can be used with almost every markup language and template engine.
127
+ There are three types of modules: the filter, the preprocessor, the processor modules.
128
+
129
+ * **Filter modules** are used to sort out files and can be applied everywhere.
130
+ * **Preprocessor modules** (documents only) alter the *source code* of the documents (text written in markdown, for example). They cause deplot to read the source files and can't be executed after processor modules.
131
+ * **Processor modules** (documents only) are used to alter *rendered code* (HTML, for now). They cause deplot to read *and* render the source files and need to be executed after preprocessor modules.
132
+
133
+ #### layout (documents only)
134
+
135
+ `layout` is used to specify a template file which is rendered just before the files is written to disk. This file can be used to link to css and javascript files or display content that stays the same over multiple pages:
136
+
137
+ ```
138
+ <html>
139
+ <head>
140
+ <link rel="stylesheet" href="style.css" />
141
+ </head>
142
+ <body>
143
+ <h1>Page title</h1>
144
+ <div class="wrapper">
145
+ <%= yield %>
146
+ </div>
147
+ </body>
148
+ </html>
149
+ ```
46
150
 
47
- Assets like `LESS`, `SASS` or `CoffeeScript` files are compiled by [guard][guard], which will also call deplot if any content or layout changes. Take a look at the default `Guardfile`, which has usable default settings. Or just run `guard` and press `enter` to compile everything.
48
151
 
49
- Since all files are compiled into the root directory of the project, you can deploy your site with [git-ftp][git-ftp] - the project's page has details on how to deploy a git repo with git-ftp.
152
+ ## Planned features
50
153
 
51
- Development
52
- -----------
154
+ * Ability to use custom renderer code (block and module)
155
+ * Non-media asset processing (compiling, compressing, concatenating) for files written in LESS, SASS, CoffeScript etc.
156
+ * Filter: keep or discard file when one or more, but not necessarily all conditions are met (considered bug)
157
+ * Automatic rebuilding using [guard][guard]
158
+ * Media resizing and conversion
159
+ * Partials (for more modular layouts)
160
+ * Ability to sort source files
53
161
 
54
- To use the latest version, you will need to manually build and install the gem. A `gem build deplot.gemspec; sudo gem install deplot-0.0.x.x.gem` in the cloned repo will suffice.
162
+ Please submit feature requests and bugfixes in the issue tracker.
55
163
 
56
- License
57
- -------
164
+ ## License
58
165
 
59
166
  See LICENSE file.
60
167
 
61
- [tilt]: https://github.com/rtomayko/tilt
62
- [guard]: https://github.com/guard/guard
63
- [git-ftp]: https://github.com/resmo/git-ftp
168
+ [tilt]: https://github.com/rtomayko/ti
169
+ [guard]: https://github.com/guard/guardlt
data/bin/deplot CHANGED
@@ -1,575 +1,348 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ VERSION = "0.1.0"
4
+
3
5
  require 'thor'
4
6
  require 'fileutils'
5
7
  require 'tilt'
8
+ require 'colorize'
6
9
 
7
- # Deplot DSL
8
-
9
- $assets_dir = Dir.pwd+"/assets"
10
- $content_dir = Dir.pwd+"/content"
11
- $root_dir = Dir.pwd
10
+ =begin
12
11
 
13
- $is_currently_rendering = false
12
+ This file, and Deplot itself, consist/s of three major parts:
14
13
 
15
- $template_arguments = {}
16
- $global_variables = {}
17
- $variables = {}
14
+ 1. The 'DeplotRenderer' class
15
+ contains all the logic of deplot and the rendering process
16
+ 2. Base classes for modules
17
+ that can be used to build modules for custom behaviour
18
+ 3. The DSL methods
19
+ are the 'interface' to deplot, accessible via the Deplotfile
20
+ 4. The 'Deplot' CLI class
21
+ provides all command line methods to Thor
18
22
 
19
- $tasks = []
20
- $render_type = ""
21
- $current_source = ""
22
- $layout = ""
23
- $options = {}
23
+ This seemed the least complex way to do it; if you can think
24
+ of any simplifications or suggestions for alternative designs,
25
+ please submit them to the issue tracker. Thanks!
24
26
 
25
- $errors_occured = 0
27
+ =end
26
28
 
27
- # helper methods
28
- def puts_alert text
29
- puts "#{Thor::Shell::Color::RED}#{text}#{Thor::Shell::Color::CLEAR}"
30
- $errors_occured += 1
31
- end
32
- def puts_success text
33
- puts "#{Thor::Shell::Color::GREEN}#{text}#{Thor::Shell::Color::CLEAR}"
34
- end
35
-
36
- # dsl methods for page specification
37
- def assets_dir dir
38
- $assets_dir = $root_dir + "/" + dir.gsub(/^\//, "").gsub(/\/$/, "")
39
- end
40
- def content_dir dir
41
- $content_dir = $root_dir + "/" + dir.gsub(/^\//, "").gsub(/\/$/, "")
42
- end
43
- def variables vars
44
- if $is_currently_rendering
45
- $variables.merge! vars
46
- else
47
- $global_variables.merge! vars
48
- end
49
- end
50
- def layout file
51
- $layout = file
52
- end
53
- def render file
54
- $render_type = "render-single"
55
- $current_source = file
56
- end
57
- def render_each base = "", paths = []
58
- $render_type = "render-all"
59
- unless base.is_a? Array
60
- $current_source = [base, paths]
61
- else
62
- $current_source = ["./", base]
63
- end
64
- end
65
- def render_all path
66
- $render_type = "render-all"
67
- $current_source = path
68
- end
29
+ #
30
+ # DeplotRenderer and subclasses, containing the render logic
31
+ #
69
32
 
70
- # base of route specification
71
- def path path, &block
72
- # reset
73
- $render_type = ""
74
- $current_source = ""
75
- $layout = "layout.erb"
76
- $options = {}
77
- $variables = {}
78
- $is_currently_rendering = true
79
-
80
- # set
81
- block.call
82
-
83
- $is_currently_rendering = false
33
+ # Base class
34
+ class DeplotRenderer
35
+ attr_accessor :layout
36
+ attr_accessor :context
84
37
 
85
- # remember
86
- if $render_type == "render-all"
87
- $render_type = (/\#/ =~ path) ? "render-all" : "render-all-one-file"
88
- $tasks << [$render_type, path, $current_source, $layout, $options, $variables]
89
- else
90
- $tasks << [$render_type, path, $current_source, $layout, $options, $variables]
38
+ def alert s
39
+ puts " ---->#{s}".yellow
40
+ end
41
+
42
+ def initialize base_dir
43
+ @rendered = false
44
+ @read = false
45
+ @sources = (Dir.glob(base_dir + "*") - [".", "..", ".DS_STORE"]).collect { |file| {:filename => file} }
46
+ @base_dir = base_dir
47
+ @layout = ""
48
+ end
49
+
50
+ # Filter out sources based on file name
51
+ def filter options
52
+ if options.has_key? :only or options.has_key? :exclude
53
+ filter_type = (options.has_key? :only) ? :only : :exclude
54
+ options[filter_type].each do |filter|
55
+ @sources.send (filter_type == :only ? :keep_if : :delete_if) do |source|
56
+ file = source[:filename]
57
+ if filter.is_a? Regexp
58
+ filter =~ file
59
+ else
60
+ filter == file || @base_dir + filter == file
61
+ end
62
+ end
63
+ end
64
+ else
65
+ alert "filter: No valid argument/s found."
66
+ end
91
67
  end
92
68
  end
93
69
 
94
- # set options
95
- def reverse_order
96
- $options[:reverse_order] = true
97
- end
98
- def extension ext
99
- $options[:extension] = ext
100
- end
101
-
102
- # methods for partials
103
- def partial name, options = {}
104
- begin
105
- source_tilt = Tilt.new($assets_dir+"/"+name)
106
- rescue Exception => e
107
- puts "- ERROR creating tilt instance (possibly missing source file for partial)."
108
- return ""
109
- end
110
- if options.has_key? :layout
111
- begin
112
- layout_tilt = Tilt.new(options[:layout])
113
- rescue Exception => e
114
- puts "- ERROR creating tilt instance (possibly missing layout file for partial)."
115
- return ""
116
- end
117
- return layout_tilt.render(Object.new, $template_arguments) do
118
- source_tilt.render(Object.new, $template_arguments)
119
- end
120
- else
121
- return source_tilt.render(Object.new, $template_arguments)
122
- end
70
+ # Media renderer
71
+ class DeplotMediaRenderer < DeplotRenderer
72
+ def initialize base_dir
73
+ puts "Media renderer initialized.".green
74
+ super
75
+ end
76
+
77
+ def copy_to output_dir
78
+ puts "Copying files..."
79
+ FileUtils.mkdir_p(output_dir)
80
+ @sources.each do |source|
81
+ FileUtils.cp(source[:filename], output_dir)
82
+ puts " Copied '#{source[:filename]}'."
83
+ end
84
+ end
85
+
86
+ def apply module_name, *args
87
+ begin
88
+ module_const = module_name.to_s.split("_").collect { |s| s.capitalize }.join()
89
+ the_module = Kernel.const_get(module_const).new
90
+ rescue
91
+ raise "'#{module_name}' not defined! Maybe not 'use'd?"
92
+ end
93
+ if the_module.is_a? DeplotFilter
94
+ @sources.each do |source|
95
+ the_module.filter source, args
96
+ end
97
+ else
98
+ raise "Only filter modules can be applied within media renderers! (#{module_name})"
99
+ end
100
+ end
123
101
  end
124
102
 
125
- # publishing methods
126
- def check_directories?
127
- [$assets_dir, $content_dir].each do |dir|
128
- unless File.exists?(dir) and File.directory?(dir)
129
- return false
130
- end
131
- end
132
- return true
133
- end
134
- def publish
135
- puts "Publishing site..."
136
- $tasks.each do |task|
137
- action, path, source, $layout, options, variables = task
138
- unless path == "/"
139
- path = "/" + path.gsub(/^\//, "")
140
- end
141
- variables.merge! $global_variables
142
- content = ""
143
- $template_arguments = {:path => "", :source => "", :file_name => "", :depth => 0}
144
- $template_arguments.merge! variables
145
- options[:extension] = (options[:extension].nil?) ? "html" : options[:extension]
146
- unless check_directories?
147
- puts "- ERROR: content or assets directory does't exist. Exiting..."
148
- return
149
- end
150
-
151
- if action == "render-single"
152
-
153
- ## R E N D E R S I N G L E
154
- # Destination
155
- destination_dir = File.dirname path
156
- destination_base = File.basename path
157
- if /\/$/ =~ path
158
- destination_dir = path.gsub /\/$/, ""
159
- destination_base = "index.#{options[:extension]}"
160
- end
161
- $template_arguments.merge! :path => "#{destination_dir}/#{destination_base}"
162
- $template_arguments.merge! :file_name => destination_base
163
- $template_arguments.merge! :source => source
164
- $template_arguments.merge! :depth => (destination_dir.count "/")
165
-
166
- puts "Rendering path '"+destination_dir.gsub(/\/$/, "")+"/#{destination_base}'"
167
- # make path
168
- FileUtils.mkdir_p "."+destination_dir
169
- unless File.directory? "."+destination_dir
170
- puts " Path '"+path+"' could not be created. Skipping..."
171
- next
172
- end
173
-
174
- # Read source
175
- Dir.chdir $content_dir do
176
- unless File.exist? source
177
- puts " Source file could not be found. Skipping..."
178
- next
179
- end
180
- content = File.read source
181
- end
182
- puts " Read source file."
183
-
184
- # Create tilt instances
185
- layout_tilt = nil
186
- Dir.chdir $assets_dir do
187
- begin
188
- layout_tilt = Tilt.new($layout)
189
- rescue Exception => e
190
- puts_alert "- ERROR creating tilt instance (possibly missing layout file)."
191
- layout_tilt = nil
192
- end
193
- end
194
- if layout_tilt.nil?
195
- puts " Layout could not be found or rendered. Skipping..."
196
- next
197
- end
198
- source_tilt = nil
199
- Dir.chdir $content_dir do
200
- begin
201
- source_tilt = Tilt.new(source)
202
- rescue Exception => e
203
- puts_alert "- ERROR creating tilt instance (possibly missing source file)."
204
- source_tilt = nil
205
- end
206
- end
207
- if source_tilt.nil?
208
- puts " Source file could not be rendered. Skipping..."
209
- next
210
- end
211
- puts " Created tilt instances."
212
-
213
- # Render and write
214
- Dir.chdir "."+destination_dir do
215
- File.open destination_base, "w" do |file|
216
- file.puts layout_tilt.render(Object.new, $template_arguments){
217
- source_tilt.render(Object.new, $template_arguments)
218
- }
219
- end
220
- end
221
- puts " Wrote to file."
222
- elsif action == "render-all"
223
-
224
- ## R E N D E R A L L
225
- # Destination
226
- destination_dir = File.dirname path
227
- destination_base = File.basename path
228
- if /\/$/ =~ path
229
- destination_dir = path.gsub /\/$/, ""
230
- destination_base = "index.#{options[:extension]}"
231
- end
232
-
233
- puts "Rendering path/s '"+destination_dir+"/...'"
234
- # make path
235
- FileUtils.mkdir_p "."+destination_dir
236
- unless File.directory? "."+destination_dir
237
- next
103
+ # Document renderer
104
+ class DeplotDocumentRenderer < DeplotRenderer
105
+ def initialize base_dir
106
+ puts "Documents renderer initialized.".green
107
+ super
108
+ end
109
+
110
+ def read
111
+ puts "Reading files..."
112
+ @sources.each do |source|
113
+ source[:content] = File.read source[:filename]
114
+ puts " Read '#{source[:filename]}'."
115
+ end
116
+ @read = true
117
+ end
118
+
119
+ def render
120
+ read if @read == false
121
+ puts "Rendering..."
122
+ @rendered = true
123
+ @sources.each do |source|
124
+ renderer = Tilt[source[:filename]]
125
+ unless renderer.nil?
126
+ source[:content] = renderer.new do
127
+ source[:content]
128
+ end.render context
129
+ else
130
+ alert "No Tilt renderer found for '#{source[:filename]}', falling back to echo."
238
131
  end
239
-
240
- # Read source
241
- Dir.chdir $content_dir do
242
- paths = []
243
- if source.is_a? Array
244
- source, paths = source
245
- end
246
- source.gsub!(/\/$/, "")
247
- Dir.chdir source do
248
- # Create layout tilt instance
249
- layout_tilt = nil
250
- Dir.chdir $assets_dir do
251
- begin
252
- layout_tilt = Tilt.new($layout)
253
- rescue Exception => e
254
- puts_alert "- ERROR creating tilt instance (possibly missing layout file)."
255
- layout_tilt = nil
256
- end
257
- end
258
- if layout_tilt.nil?
259
- puts " Layout could not be found or rendered. Skipping..."
260
- next
261
- end
262
- (paths == [] ? Dir.glob("*") : paths).each do |content_file|
263
- puts " Read source file #{source}/#{content_file}"
264
- $template_arguments.merge! :source => "#{source}/#{content_file}"
265
-
266
- # Create tilt instances
267
- source_tilt = nil
268
- begin
269
- source_tilt = Tilt.new(content_file)
270
- rescue Exception => e
271
- puts_alert "- ERROR creating tilt instance (possibly missing source file)."
272
- source_tilt = nil
273
- end
274
- if source_tilt.nil?
275
- puts " Source file could not be rendered. Skipping..."
276
- next
277
- end
278
-
279
- # Render and write
280
- Dir.chdir $root_dir+destination_dir do
281
- file_name = File.basename(content_file).gsub(File.extname(content_file), ".#{options[:extension]}")
282
- $template_arguments.merge! :path => "#{destination_dir}/#{file_name}"
283
- $template_arguments.merge! :file_name => file_name
284
- $template_arguments.merge! :depth => (destination_dir.count "/")
285
- File.open destination_base.gsub("#", file_name), "w" do |file|
286
- file.puts layout_tilt.render(Object.new, $template_arguments){
287
- source_tilt.render(Object.new, $template_arguments)
288
- }
289
- end
290
- puts " Wrote to file: " + file_name
291
- end
292
- end
132
+ end
133
+ end
134
+
135
+ def output
136
+ render if @rendered == false
137
+ output = []
138
+ @sources.each do |source|
139
+ unless @layout == ""
140
+ output.push Tilt.new("assets/#{@layout}").render context do
141
+ source[:content]
293
142
  end
143
+ else
144
+ output.push source[:content]
294
145
  end
295
- elsif action == "render-all-one-file"
296
-
297
- ## R E N D E R A L L O N E F I L E
298
- # Destination
299
- destination_dir = File.dirname path
300
- destination_base = File.basename path
301
- if /\/$/ =~ path
302
- destination_dir = path.gsub /\/$/, ""
303
- destination_base = "index.#{options[:extension]}"
304
- end
305
-
306
- $template_arguments.merge! :path => "#{destination_dir}/#{destination_base}"
307
- $template_arguments.merge! :file_name => destination_base
308
- $template_arguments.merge! :depth => (destination_dir.count "/")
309
-
310
- puts "Rendering path '#{destination_dir}/#{destination_base}'"
311
- # make path
312
- FileUtils.mkdir_p "."+destination_dir
313
- unless File.directory? "."+destination_dir
314
- puts " Path '"+path+"' could not be created. Skipping..."
315
- next
146
+ end
147
+ output
148
+ end
149
+
150
+ def output_to output_dir
151
+ render if @rendered == false
152
+ puts "Writing files..."
153
+ @sources.each do |source|
154
+ output_dir += "/" unless output_dir =~ /\/$/
155
+ output_path = output_dir + source[:filename].gsub(/^#{@base_dir}/, '')
156
+ extname = File.extname(output_path)
157
+ if extname == ""
158
+ output_path += ".html"
159
+ else
160
+ output_path.gsub! /#{extname}$/, ".html"
316
161
  end
317
-
318
- sources_rendered = []
319
- # Read source/s
320
- Dir.chdir $content_dir do
321
- paths = []
322
- if source.is_a? Array
323
- source, paths = source
324
- end
325
- Dir.chdir source do
326
- paths = (paths == [] ? Dir.glob("*") : paths)
327
- if options.has_key? :reverse_order and options[:reverse_order] == true
328
- paths.reverse!
329
- end
330
- paths.each do |content_file|
331
- #content = File.read content_file
332
- puts " Read source file #{source}#{content_file}"
333
- $template_arguments.merge! :source => "#{source}#{content_file}"
334
-
335
- # Create tilt instance
336
- source_tilt = nil
337
- begin
338
- source_tilt = Tilt.new(content_file)
339
- rescue Exception => e
340
- puts_alert "- ERROR creating tilt instance (possibly missing source file)."
341
- source_tilt = nil
342
- end
343
- if source_tilt.nil?
344
- puts " Source file could not be rendered. Skipping..."
345
- next
346
- end
347
- sources_rendered << {:content => source_tilt.render(Object.new, $template_arguments)}.merge($template_arguments)
348
- end
162
+ FileUtils.mkdir_p(File.dirname(output_path))
163
+ File.open(output_path, "w") do |file|
164
+ if @layout == ""
165
+ file.write source[:content]
166
+ else
167
+ file.write (Tilt.new("assets/#{@layout}").render context do
168
+ source[:content]
169
+ end)
349
170
  end
350
- end
351
-
352
- # Create layout tilt instance
353
- layout_tilt = nil
354
- Dir.chdir $assets_dir do
355
- begin
356
- layout_tilt = Tilt.new($layout)
357
- rescue Exception => e
358
- puts_alert "- ERROR creating tilt instance (possibly missing layout file)."
359
- layout_tilt = nil
360
- end
361
- end
362
- if layout_tilt.nil?
363
- puts " Layout could not be found or rendered. Skipping..."
364
- next
365
- end
366
- # Render and write
367
- Dir.chdir "."+destination_dir do
368
- File.open destination_base, "w" do |file|
369
- file.puts layout_tilt.render(Object.new, {:items => sources_rendered}.merge($template_arguments))
370
- end
371
- end
372
- puts " Wrote to file."
373
- end # End of action switching
171
+ end
172
+ puts " Wrote to file '#{output_path}'."
173
+ end
374
174
  end
375
- if $errors_occured == 0
376
- puts_success "Successfully created all pages."
377
- elsif $errors_occured == 1
378
- puts_alert "#{$errors_occured} error occurred!"
379
- else
380
- puts_alert "#{$errors_occured} errors occurred!"
381
- end
382
- end
383
-
384
- # Thor: Deplot CLI
385
-
386
- class Deplot < Thor
387
175
 
388
- desc "init", "Create a new deplot project in the current directory"
389
- def init
390
- # Content directory
391
- puts " Making directory '"+$content_dir+"'..."
392
- FileUtils.mkdir $content_dir
393
- # Assets directory
394
- puts " Making directory '"+$assets_dir+"'..."
395
- FileUtils.mkdir $assets_dir
396
- # Basic Layout
397
- Dir.chdir $assets_dir do
398
- File.open "layout.erb", "w" do |file|
399
- file.write <<-EOF
400
- <html>
401
- <head>
402
- <title>Deplot Project</title>
403
- <link rel="stylesheet" href="style.css" />
404
- </head>
405
- <body>
406
- <div id="wrapper">
407
- <%= yield %>
408
- </div>
409
- </body>
410
- </html>
411
- EOF
412
- end
413
- File.open "style.less", "w" do |file|
414
- file.write <<-EOF
415
- body {
416
- margin: 0;
417
- font-family: "Helvetica", sans-serif;
418
- background-color: #EEE;
419
- }
420
- #wrapper {
421
- width: 500px;
422
- padding: 10px;
423
- margin: 10px auto;
424
- background-color: #FFF;
425
- border: 3px solid #DDD;
426
- }
427
- p {
428
- color: #444;
429
- }
430
- h1 {
431
- margin-bottom: 20px;
432
- padding-bottom: 8px;
433
- border-bottom: 1px solid #EEE;
434
- }
435
-
436
- EOF
176
+ def collect
177
+ render if @rendered == false
178
+ puts "Collecting documents..."
179
+ content = @sources.collect{ |source| source[:content] }.join
180
+ unless @layout == ""
181
+ return Tilt.new("assets/#{@layout}").render context do
182
+ content
437
183
  end
184
+ else
185
+ return content
438
186
  end
439
- # Deplotfile
440
- puts " Creating Deplotfile..."
441
- File.open "Deplotfile", "w" do |file|
442
- file.write <<-EOF
443
- path '/' do
444
- render "index.markdown"
445
- end
446
- EOF
187
+ end
188
+
189
+ def collect_in output_file
190
+ puts "Writing file..."
191
+ sources_contents = collect
192
+ FileUtils.mkdir_p(File.dirname(output_file))
193
+ File.open(output_file, "w") do |file|
194
+ file.write sources_contents
195
+ end
196
+ puts " Wrote to file '#{output_file}'."
197
+ end
198
+
199
+ # Apply a user module (located in modules/)
200
+ def apply module_name, *args
201
+ begin
202
+ module_const = module_name.to_s.split("_").collect { |s| s.capitalize }.join()
203
+ the_module = Kernel.const_get(module_const).new
204
+ rescue
205
+ raise "'#{module_name}' not defined! Maybe not 'use'd?"
447
206
  end
448
- # Guardfile
449
- puts " Creating Guardfile..."
450
- File.open "Guardfile", "w" do |file|
451
- file.write <<-EOF
452
- # CoffeeScript
453
- guard :coffeescript, :input => 'assets', :output => '.'
454
-
455
- # CSS <- LESS, SASS
456
- guard :sass, :input => 'assets', :output => '.'
457
- guard :less, :output => '.' do
458
- watch(/^assets\\/(.+\.less)$/)
207
+ puts "Applying '#{module_name}'..."
208
+ # Prepare module
209
+ module_type = nil
210
+ if the_module.is_a? DeplotPreprocessor
211
+ raise "Cannot preprocess if already rendered! (module '#{module_name}')" if @rendered == true
212
+ read if @read == false
213
+ module_type = :preprocess
214
+ elsif the_module.is_a? DeplotProcessor
215
+ read if @read == false # No preprocessors
216
+ render if @rendered == false
217
+ module_type = :process
218
+ elsif the_module.is_a? DeplotFilter
219
+ module_type = :filter
220
+ else
221
+ raise "'#{module_name}' is not a deplot module!"
222
+ end
223
+ # Apply to each source
224
+ @sources.each do |source|
225
+ the_module.send module_type, source, args
226
+ end
227
+ end
459
228
  end
460
229
 
461
- # Invoke deplot
462
- guard :shell do
463
- watch(/(assets|content)\\/(.*)/) do |m|
464
- `echo ""; echo "File '\#{m[2]}' changed."; deplot make`
465
- end
466
- end
467
- EOF
468
- end
469
- # .git-ftp-ignore
470
- puts " Creating .git-ftp-ignore..."
471
- File.open ".git-ftp-ignore", "w" do |file|
472
- file.write <<-EOF
473
- .gitignore
474
- .git-ftp-ignore
475
- Deplotfile
476
- Guardfile
477
- assets/.*
478
- content/.*
479
- EOF
480
- end
481
- # Example content
482
- Dir.chdir $content_dir do
483
- File.open "index.markdown", "w" do |file|
484
- file.write <<-EOF
485
- # New deplot project
230
+ $current_instance = nil
486
231
 
487
- This is the default page of your new project. Change the Deplotfile in the project
488
- directory to add new routes (see examples below) or change the contents of this file
489
- by editing `content/index.markdown`. Remember to call `deplot make` to build the
490
- project or, better, run `guard` to recompile if anything changes.
232
+ #
233
+ # Base classes for user modules
234
+ #
491
235
 
492
- ## Editing the Deplotfile
236
+ class DeplotFilter
237
+ def filter sources, arguments
238
+ raise "Module error: 'filter' method is not defined!"
239
+ end
240
+ end
241
+ class DeplotPreprocessor
242
+ def preprocess sources, arguments
243
+ raise "Module error: 'preprocess' method is not defined!"
244
+ end
245
+ end
246
+ class DeplotProcessor
247
+ def process sources, arguments
248
+ raise "Module error: 'process' method is not defined!"
249
+ end
250
+ end
493
251
 
494
- The basic syntax to describe a page of your site is to call `path` with the page location
495
- as a string and with a block containing the specific instructions, like the `render`
496
- method:
252
+ #
253
+ # Deplot DSL, the language of the Deplotfile
254
+ #
497
255
 
498
- path '/' do
499
- render "index.markdown"
500
- end
256
+ def use module_name
257
+ puts "Loading '#{module_name}'..."
258
+ require "./modules/#{module_name}.rb"
259
+ end
501
260
 
502
- This is, by the way, also the code that is used to generate this introduction page.
503
- To render more than one file, for example all files in a directory called `blog/`,
504
- you can use `render_all`:
261
+ # Assign methods
262
+ ["layout"].each do |variable_name|
263
+ self.class.send :define_method, variable_name do |*args|
264
+ unless $current_instance.nil?
265
+ $current_instance.send("#{variable_name}=", *args)
266
+ end
267
+ end
268
+ end
505
269
 
506
- path '/blog/#'
507
- render_all "blog/"
508
- end
270
+ # Basic methods
271
+ ["filter", "apply", "copy_to"].each do |method_name|
272
+ self.class.send :define_method, method_name do |*args|
273
+ unless $current_instance.nil?
274
+ $current_instance.context = binding.eval("self")
275
+ $current_instance.send(method_name, *args)
276
+ end
277
+ end
278
+ end
509
279
 
510
- The symbol `#` will then be replaced by the name of the source file (without its
511
- extension and with `.html` at the end). Omitting the symbol will cause deplot to render
512
- all source files into one single file. The code below will produce an index file
513
- `blog/index.html` that uses another layout (`layout_index.erb`).
280
+ # Output methods
281
+ ["output_to", "collect_in"].each do |method_name|
282
+ self.class.send :define_method, method_name do |path, &block|
283
+ unless $current_instance.nil?
284
+ backup = Marshal.load(Marshal.dump($current_instance))
285
+ block.call unless block.nil?
286
+ @output_path = path
287
+ @depth = path.count("/")
288
+ @depth += 1 if File.directory?(path) && path[-1] != "/"
289
+ $current_instance.context = (block.nil? ? binding : block.binding).eval("self")
290
+ $current_instance.send(method_name, path)
291
+ $current_instance = backup
292
+ end
293
+ end
294
+ end
514
295
 
515
- path '/blog/'
516
- layout "layout_index.erb"
517
- render_all "blog/"
518
- end
296
+ # Render blocks
297
+ ["media", "documents"].each do |type|
298
+ self.class.send :define_method, "#{type}_in" do |dir, &block|
299
+ # Maybe run $current_instance's output_to, define default behaviour?
300
+ # If so, remember to output after 'load "Deplotfile" too.
301
+ base = "#{type}/#{dir}/"
302
+ if type == "media"
303
+ $current_instance = DeplotMediaRenderer.new(base)
304
+ else
305
+ $current_instance = DeplotDocumentRenderer.new(base)
306
+ end
307
+ block.call
308
+ end
309
+ end
519
310
 
520
- ## Editing content
311
+ # Inline document render blocks
312
+ ["collect", "output"].each do |method|
313
+ self.class.send :define_method, "#{method}_documents_in" do |dir, &block|
314
+ # Maybe run $current_instance's output_to, define default behaviour?
315
+ # If so, remember to output after 'load "Deplotfile" too.
316
+ base = "documents/#{dir}/"
317
+ $current_instance.context = nil
318
+ backup = Marshal.load(Marshal.dump($current_instance))
319
+ $current_instance = DeplotDocumentRenderer.new(base)
320
+ block.call unless block.nil?
321
+ $current_instance.context = (block.nil? ? binding : block.binding).eval("self")
322
+ output = $current_instance.send method
323
+ $current_instance = backup
324
+ return output
325
+ end
326
+ end
521
327
 
522
- All content is by default in the directory `content/` and can be written in any language
523
- that `tilt` understands. The directory in which deplot searches for the source files can
524
- be changed with a call to `content_dir`, and the directory for all assets (layouts,
525
- stylesheets) with `assets_dir`.
328
+ #
329
+ # Deplot Thor CLI, all the methods of the CLI
330
+ #
526
331
 
527
- EOF
528
- end
529
- end
530
- end
531
-
532
- desc "new <project_name> (<git_repo>)", "Create a new deplot project, if a git repo is specified by cloning an existing skeleton"
533
- def new(project_name, git_skeleton = "")
534
- if File.exist? project_name
535
- puts "Directory '"+project_name+"' already exists. Exiting..."
536
- return
537
- end
538
- puts "Creating project folder..."
539
- if git_skeleton == ""
540
- FileUtils.mkdir project_name
541
- $root_dir = Dir.pwd + "/" + project_name
542
- $assets_dir = $root_dir + "/assets"
543
- $content_dir = $root_dir + "/content"
544
- Dir.chdir project_name do
545
- init
546
- end
547
- puts "Finished creating '#{project_name}'- ready to build your site!"
548
- else
549
- `git clone #{git_skeleton} #{project_name}`
550
- if File.exist? project_name
551
- begin
552
- `rm -rf #{project_name}/.git`
553
- rescue
554
- puts "Unable to delete git references."
555
- end
556
- puts "Finished creating '#{project_name}' - ready to build your site! (If 'git clone' didn't fail.)"
557
- else
558
- puts "Git clone failed (see output above)."
559
- end
560
- end
332
+ class Deplot < Thor
333
+ desc "version", "Show the installed deplot gem's version."
334
+ def version
335
+ puts "Deplot version #{VERSION}."
561
336
  end
562
-
563
- desc "make", "Run deplot and build your project"
564
- def make()
565
- puts "Making project..."
337
+ desc "make", "Build the deplot project in the current directory"
338
+ def make
339
+ puts "Deplot #{VERSION} will re/build the project.".green
566
340
  unless File.exist? "Deplotfile"
567
- puts "Deplotfile not found. Exiting..."
341
+ puts "Deplotfile not found. Exiting...".red
568
342
  return
569
343
  end
570
344
  $LOAD_PATH.unshift(Dir.pwd)
571
345
  load "Deplotfile"
572
- publish
573
346
  end
574
347
  end
575
348
  Deplot.start
@@ -1,9 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'deplot'
3
- s.version = '0.0.4'
4
- s.date = '2012-04-29'
5
- s.description = "A ruby static web site generator"
6
- s.summary = s.description
3
+ s.version = '0.1.0'
4
+ s.date = '2013-03-01'
5
+ s.summary = "A lightweight and very extensible static web site generator"
6
+ s.description = %{
7
+ Deplot intends to simplify the process of creating and maintaining a static
8
+ web site and allows for modifications of every part of the building process.
9
+ }.delete "\n"
7
10
  s.authors = ["Cyril Nusko"]
8
11
  s.email = 'gitcdn@gmail.com'
9
12
  s.files = ["bin/deplot"]
@@ -18,4 +21,5 @@ Gem::Specification.new do |s|
18
21
  ]
19
22
  s.add_dependency 'thor', "~> 0.14.6"
20
23
  s.add_dependency 'tilt', "~> 1.3.3"
24
+ s.add_dependency 'colorize'
21
25
  end
metadata CHANGED
@@ -1,63 +1,72 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: deplot
3
- version: !ruby/object:Gem::Version
4
- hash: 23
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 4
10
- version: 0.0.4
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Cyril Nusko
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-04-29 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2013-03-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: thor
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
18
+ requirements:
26
19
  - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 43
29
- segments:
30
- - 0
31
- - 14
32
- - 6
20
+ - !ruby/object:Gem::Version
33
21
  version: 0.14.6
34
22
  type: :runtime
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.14.6
30
+ - !ruby/object:Gem::Dependency
37
31
  name: tilt
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.3.3
38
+ type: :runtime
38
39
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
40
41
  none: false
41
- requirements:
42
+ requirements:
42
43
  - - ~>
43
- - !ruby/object:Gem::Version
44
- hash: 29
45
- segments:
46
- - 1
47
- - 3
48
- - 3
44
+ - !ruby/object:Gem::Version
49
45
  version: 1.3.3
46
+ - !ruby/object:Gem::Dependency
47
+ name: colorize
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
50
54
  type: :runtime
51
- version_requirements: *id002
52
- description: A ruby static web site generator
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Deplot intends to simplify the process of creating and maintaining a
63
+ staticweb site and allows for modifications of every part of the building process.
53
64
  email: gitcdn@gmail.com
54
- executables:
65
+ executables:
55
66
  - deplot
56
67
  extensions: []
57
-
58
68
  extra_rdoc_files: []
59
-
60
- files:
69
+ files:
61
70
  - Gemfile
62
71
  - LICENSE
63
72
  - README.md
@@ -65,36 +74,26 @@ files:
65
74
  - deplot.gemspec
66
75
  homepage: http://www.github.com/cdn64/deplot
67
76
  licenses: []
68
-
69
77
  post_install_message:
70
78
  rdoc_options: []
71
-
72
- require_paths:
79
+ require_paths:
73
80
  - lib
74
- required_ruby_version: !ruby/object:Gem::Requirement
81
+ required_ruby_version: !ruby/object:Gem::Requirement
75
82
  none: false
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- hash: 3
80
- segments:
81
- - 0
82
- version: "0"
83
- required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
88
  none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
- version: "0"
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
92
93
  requirements: []
93
-
94
94
  rubyforge_project:
95
- rubygems_version: 1.8.4
95
+ rubygems_version: 1.8.24
96
96
  signing_key:
97
97
  specification_version: 3
98
- summary: A ruby static web site generator
98
+ summary: A lightweight and very extensible static web site generator
99
99
  test_files: []
100
-