smartgen 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog.md +4 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +61 -0
- data/README.md +119 -0
- data/Rakefile +8 -0
- data/bin/smartgen +25 -0
- data/lib/smartgen.rb +21 -0
- data/lib/smartgen/configuration.rb +17 -0
- data/lib/smartgen/engines.rb +3 -0
- data/lib/smartgen/engines/base.rb +45 -0
- data/lib/smartgen/engines/markdown.rb +16 -0
- data/lib/smartgen/engines/textile.rb +16 -0
- data/lib/smartgen/generator.rb +104 -0
- data/lib/smartgen/markup_file.rb +47 -0
- data/lib/smartgen/object_hash.rb +41 -0
- data/lib/smartgen/renderers.rb +1 -0
- data/lib/smartgen/renderers/erb.rb +12 -0
- data/lib/smartgen/resource.rb +32 -0
- data/lib/smartgen/version.rb +4 -0
- data/spec/fixtures/expectations/common/another_index.html +13 -0
- data/spec/fixtures/expectations/common/index.html +8 -0
- data/spec/fixtures/expectations/common/other_index.html +13 -0
- data/spec/fixtures/expectations/with_layout/index.html +12 -0
- data/spec/fixtures/expectations/with_layout/index_with_metadata.html +43 -0
- data/spec/fixtures/expectations/with_layout/index_with_specific_metadata.html +44 -0
- data/spec/fixtures/src/assets/images/image.gif +0 -0
- data/spec/fixtures/src/assets/javascripts/somelib.js +2 -0
- data/spec/fixtures/src/assets/stylesheets/style.css +2 -0
- data/spec/fixtures/src/common/another_index.md +12 -0
- data/spec/fixtures/src/common/index.textile +10 -0
- data/spec/fixtures/src/common/other_index.markdown +12 -0
- data/spec/fixtures/src/layout.html.erb +5 -0
- data/spec/fixtures/src/layout_with_metadata.html.erb +22 -0
- data/spec/fixtures/src/layout_with_specific_metadata.html.erb +23 -0
- data/spec/fixtures/src/metadata.yml +43 -0
- data/spec/fixtures/src/with_layout/index.textile +10 -0
- data/spec/fixtures/src/with_layout/index_with_specific_metadata.textile +10 -0
- data/spec/lib/smartgen/configuration_spec.rb +30 -0
- data/spec/lib/smartgen/engines/base_spec.rb +71 -0
- data/spec/lib/smartgen/engines/markdown_spec.rb +23 -0
- data/spec/lib/smartgen/engines/textile_spec.rb +19 -0
- data/spec/lib/smartgen/generator_spec.rb +166 -0
- data/spec/lib/smartgen/markup_file_spec.rb +128 -0
- data/spec/lib/smartgen/object_hash_spec.rb +54 -0
- data/spec/lib/smartgen/renderers/erb_spec.rb +32 -0
- data/spec/lib/smartgen/resource_spec.rb +60 -0
- data/spec/lib/smartgen_spec.rb +18 -0
- data/spec/sandbox/.gitkeep +0 -0
- data/spec/spec_helper.rb +37 -0
- metadata +240 -0
data/ChangeLog.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
smartgen (0.0.1)
|
5
|
+
RedCloth (>= 4.2.3)
|
6
|
+
activesupport (>= 2.3.5)
|
7
|
+
bluecloth (>= 2.0.9)
|
8
|
+
i18n (>= 0.5.0)
|
9
|
+
thor (>= 0.14.6)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: http://rubygems.org/
|
13
|
+
specs:
|
14
|
+
RedCloth (4.2.3)
|
15
|
+
activesupport (2.3.5)
|
16
|
+
archive-tar-minitar (0.5.2)
|
17
|
+
bluecloth (2.0.9)
|
18
|
+
columnize (0.3.2)
|
19
|
+
diff-lcs (1.1.2)
|
20
|
+
i18n (0.5.0)
|
21
|
+
linecache (0.43)
|
22
|
+
linecache19 (0.5.11)
|
23
|
+
ruby_core_source (>= 0.1.4)
|
24
|
+
rspec (2.3.0)
|
25
|
+
rspec-core (~> 2.3.0)
|
26
|
+
rspec-expectations (~> 2.3.0)
|
27
|
+
rspec-mocks (~> 2.3.0)
|
28
|
+
rspec-core (2.3.1)
|
29
|
+
rspec-expectations (2.3.0)
|
30
|
+
diff-lcs (~> 1.1.2)
|
31
|
+
rspec-mocks (2.3.0)
|
32
|
+
ruby-debug (0.10.4)
|
33
|
+
columnize (>= 0.1)
|
34
|
+
ruby-debug-base (~> 0.10.4.0)
|
35
|
+
ruby-debug-base (0.10.4)
|
36
|
+
linecache (>= 0.3)
|
37
|
+
ruby-debug-base19 (0.11.24)
|
38
|
+
columnize (>= 0.3.1)
|
39
|
+
linecache19 (>= 0.5.11)
|
40
|
+
ruby_core_source (>= 0.1.4)
|
41
|
+
ruby-debug19 (0.11.6)
|
42
|
+
columnize (>= 0.3.1)
|
43
|
+
linecache19 (>= 0.5.11)
|
44
|
+
ruby-debug-base19 (>= 0.11.19)
|
45
|
+
ruby_core_source (0.1.4)
|
46
|
+
archive-tar-minitar (>= 0.5.2)
|
47
|
+
thor (0.14.6)
|
48
|
+
|
49
|
+
PLATFORMS
|
50
|
+
ruby
|
51
|
+
|
52
|
+
DEPENDENCIES
|
53
|
+
RedCloth (>= 4.2.3)
|
54
|
+
activesupport (>= 2.3.5)
|
55
|
+
bluecloth (>= 2.0.9)
|
56
|
+
i18n (>= 0.5.0)
|
57
|
+
rspec (>= 2.3.0)
|
58
|
+
ruby-debug
|
59
|
+
ruby-debug19
|
60
|
+
smartgen!
|
61
|
+
thor (>= 0.14.6)
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
Smartgen
|
2
|
+
========
|
3
|
+
|
4
|
+
Smartgen generates static HTML files from markup files, using textile or markdown, and ERB to create layout templates.
|
5
|
+
|
6
|
+
## Basic Usage
|
7
|
+
|
8
|
+
To use you must first add the gem to your Gemfile:
|
9
|
+
|
10
|
+
gem 'smartgen'
|
11
|
+
|
12
|
+
Then you can create a resource configuration:
|
13
|
+
|
14
|
+
Smartgen[:my_doc].configure do |config|
|
15
|
+
config.src_files = ['doc/**/*']
|
16
|
+
config.output_folder = 'public/docs'
|
17
|
+
end
|
18
|
+
|
19
|
+
Finally you generate it:
|
20
|
+
|
21
|
+
Smartgen[:my_doc].generate!
|
22
|
+
|
23
|
+
## Adding a layout
|
24
|
+
|
25
|
+
By default Smartgen will only parse your textile (*.textile) or markdown (*.md or *.markdown) files, based on their extension and output it. You can give a layout file that will be used when rendering each file:
|
26
|
+
|
27
|
+
Smartgen[:my_doc].configure do |config|
|
28
|
+
config.src_files = ['doc/**/*']
|
29
|
+
config.output_folder = 'public/docs'
|
30
|
+
config.layout = 'doc/layout.html.erb'
|
31
|
+
end
|
32
|
+
|
33
|
+
This layout file is an ERB template, that has some methods available, for example this would be a basic layout:
|
34
|
+
|
35
|
+
<html>
|
36
|
+
<body>
|
37
|
+
<%= markup_file.contents %>
|
38
|
+
</body>
|
39
|
+
</html>
|
40
|
+
|
41
|
+
## Using metadata in layout
|
42
|
+
|
43
|
+
You can specify a metadata file and use it in layouts:
|
44
|
+
|
45
|
+
Smartgen[:my_doc].configure do |config|
|
46
|
+
config.src_files = ['doc/**/*']
|
47
|
+
config.output_folder = 'public/docs'
|
48
|
+
config.layout = 'doc/layout.html.erb'
|
49
|
+
config.metadata_file = 'doc/metadata.yml'
|
50
|
+
end
|
51
|
+
|
52
|
+
This would be `doc/metadata.yml` contents
|
53
|
+
|
54
|
+
title: Common title
|
55
|
+
pages:
|
56
|
+
- &index
|
57
|
+
file: index
|
58
|
+
title: Index Page
|
59
|
+
description: Description for index page
|
60
|
+
- &some_page
|
61
|
+
file: some_page
|
62
|
+
title: Some Page
|
63
|
+
description: Description for some page
|
64
|
+
menu: [*index, *some_page]
|
65
|
+
|
66
|
+
And this could be a layout that makes use of these metadata:
|
67
|
+
|
68
|
+
<html>
|
69
|
+
<head>
|
70
|
+
<title><% metadata.current_page.title %> :: <%= metadata.title %></title>
|
71
|
+
</head>
|
72
|
+
<body>
|
73
|
+
<section id="menu">
|
74
|
+
<ul>
|
75
|
+
<% metadata.menu.each do |entry| %>
|
76
|
+
<lu><a href="<%= entry.file %>.html" title="<%= entry.description %>"><%= entry.title %></a></li>
|
77
|
+
<% end %>
|
78
|
+
</ul>
|
79
|
+
</section>
|
80
|
+
|
81
|
+
<section id="contents">
|
82
|
+
<%= markup_file.contents %>
|
83
|
+
</section>
|
84
|
+
</body>
|
85
|
+
</html>
|
86
|
+
|
87
|
+
As you can see, there is a special metadata method called `current_page`. This is created whenever you declare a pages section in your metadata file with a `file` key that matches the current file being processed. This way you can use this to put specific file metadata when rendering layouts.
|
88
|
+
|
89
|
+
## Copying assets
|
90
|
+
|
91
|
+
When you generate documentation with Smartgen you'll often need to also copy stylesheets, javascript files and images to the output folder. You can easily do so by specifying an array of assets when configuring:
|
92
|
+
|
93
|
+
Smartgen[:my_doc].configure do |config|
|
94
|
+
config.src_files = ['doc/**/*']
|
95
|
+
config.output_folder = 'public/docs'
|
96
|
+
config.assets = ['doc/stylesheets/*.css', 'doc/javascripts/*.js', 'doc/images/*.{png|jpg|gif}']
|
97
|
+
end
|
98
|
+
|
99
|
+
As you can see you can pass an array of `Dir.glob` to either assets or src_files configuration.
|
100
|
+
|
101
|
+
## Using different configurations
|
102
|
+
|
103
|
+
You may create as many resource configurations as you want. You create a configuration the first time you call `Smartgen[:some_config_name]`, and then, whenever you use it again it will return that configuration. You can change the configuration by calling `configure`:
|
104
|
+
|
105
|
+
Smartgen[:doc].configure do |config|
|
106
|
+
config.src_files = ['doc/**/*']
|
107
|
+
config.output_folder = 'public/docs'
|
108
|
+
config.layout = 'doc/layout.html.erb'
|
109
|
+
config.metadata_file = 'doc/metadata.yml'
|
110
|
+
end
|
111
|
+
|
112
|
+
Smartgen[:some_other_documentation].configure do |config|
|
113
|
+
config.src_files = ['other_doc/**/*']
|
114
|
+
config.output_folder = 'public/other_docs'
|
115
|
+
config.layout = 'other_layout.html.erb'
|
116
|
+
end
|
117
|
+
|
118
|
+
Smartgen[:doc].generate!
|
119
|
+
Smartgen[:some_other_documentation].generate!
|
data/Rakefile
ADDED
data/bin/smartgen
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'smartgen/autorun'
|
5
|
+
rescue LoadError
|
6
|
+
$stderr.puts <<-EOS
|
7
|
+
#{'*'*50}
|
8
|
+
Could not find 'smartgen/autorun'
|
9
|
+
|
10
|
+
This may happen if you're using rubygems as your package manager, but it is not
|
11
|
+
being required through some mechanism before executing the rspec command.
|
12
|
+
|
13
|
+
You may need to do one of the following in your shell:
|
14
|
+
|
15
|
+
# for bash/zsh
|
16
|
+
export RUBYOPT=rubygems
|
17
|
+
|
18
|
+
# for csh, etc.
|
19
|
+
set RUBYOPT=rubygems
|
20
|
+
|
21
|
+
For background, please see http://gist.github.com/54177.
|
22
|
+
#{'*'*50}
|
23
|
+
EOS
|
24
|
+
exit(1)
|
25
|
+
end
|
data/lib/smartgen.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path(File.join('smartgen', 'object_hash'), File.dirname(__FILE__))
|
3
|
+
require File.expand_path(File.join('smartgen', 'resource'), File.dirname(__FILE__))
|
4
|
+
require File.expand_path(File.join('smartgen', 'configuration'), File.dirname(__FILE__))
|
5
|
+
require File.expand_path(File.join('smartgen', 'markup_file'), File.dirname(__FILE__))
|
6
|
+
require File.expand_path(File.join('smartgen', 'renderers'), File.dirname(__FILE__))
|
7
|
+
require File.expand_path(File.join('smartgen', 'engines'), File.dirname(__FILE__))
|
8
|
+
require File.expand_path(File.join('smartgen', 'generator'), File.dirname(__FILE__))
|
9
|
+
|
10
|
+
module Smartgen
|
11
|
+
class << self
|
12
|
+
def [](name)
|
13
|
+
resources[name] ||= Smartgen::Resource.new
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def resources
|
18
|
+
@resources ||= {}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Smartgen
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :src_files
|
4
|
+
attr_accessor :output_folder
|
5
|
+
attr_accessor :layout
|
6
|
+
attr_accessor :assets
|
7
|
+
attr_accessor :metadata_file
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@src_files = []
|
11
|
+
@output_folder = 'tmp'
|
12
|
+
@layout = nil
|
13
|
+
@assets = []
|
14
|
+
@metadata_file = 'metadata.yml'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'active_support/core_ext/class/inheritable_attributes'
|
2
|
+
require 'active_support/core_ext/try'
|
3
|
+
|
4
|
+
module Smartgen
|
5
|
+
module Engine
|
6
|
+
class Base
|
7
|
+
class_inheritable_accessor :pre_processors
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
self.pre_processors ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def process(body)
|
14
|
+
parse(pre_process(body))
|
15
|
+
end
|
16
|
+
|
17
|
+
def supported?(extension)
|
18
|
+
extensions.include?(extension)
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def register(processor)
|
23
|
+
self.pre_processors ||= []
|
24
|
+
self.pre_processors << processor
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def pre_process(body)
|
30
|
+
self.pre_processors.inject(body) do |processed_body, pre_processor|
|
31
|
+
processed_body = pre_processor.process(processed_body)
|
32
|
+
processed_body
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse(body)
|
37
|
+
body
|
38
|
+
end
|
39
|
+
|
40
|
+
def extensions
|
41
|
+
[]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'thor/group'
|
2
|
+
|
3
|
+
module Smartgen
|
4
|
+
class Generator < Thor::Group
|
5
|
+
include Thor::Actions
|
6
|
+
|
7
|
+
argument :src_files, :type => :array
|
8
|
+
argument :output_folder, :type => :string
|
9
|
+
|
10
|
+
class_option :layout, :type => :string
|
11
|
+
class_option :assets, :type => :array, :default => []
|
12
|
+
class_option :metadata_file, :type => :string
|
13
|
+
|
14
|
+
attr_reader :loaded_files
|
15
|
+
|
16
|
+
def create_output_folder
|
17
|
+
destination_root = output_folder
|
18
|
+
empty_directory output_folder
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_files
|
22
|
+
markup_files.each do |markup_file|
|
23
|
+
create_file output_folder_path("#{markup_file.filename}.html"), process_file(markup_file), :force => true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def copy_assets
|
28
|
+
options[:assets].each do |dir|
|
29
|
+
self.class.source_root File.dirname(dir)
|
30
|
+
directory File.basename(dir), output_folder_path(File.basename(dir)), :force => true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
def renderer
|
36
|
+
@renderer ||= Smartgen::Renderer::ERB.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def renderer=(value)
|
40
|
+
@renderer = value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def process_file(markup_file)
|
47
|
+
if has_layout?
|
48
|
+
self.class.renderer.render(layout, markup_file, metadata_for(markup_file))
|
49
|
+
else
|
50
|
+
markup_file.contents
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def has_layout?
|
55
|
+
options.has_key?("layout")
|
56
|
+
end
|
57
|
+
|
58
|
+
def layout
|
59
|
+
File.read(options["layout"])
|
60
|
+
end
|
61
|
+
|
62
|
+
def metadata_for(markup_file)
|
63
|
+
metadata = load_metadata
|
64
|
+
add_current_page_data_to(metadata, markup_file)
|
65
|
+
metadata
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_metadata
|
69
|
+
if options["metadata_file"]
|
70
|
+
YAML.load(File.read(options["metadata_file"]))
|
71
|
+
else
|
72
|
+
{}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_current_page_data_to(metadata, markup_file)
|
77
|
+
if metadata.has_key?("pages")
|
78
|
+
metadata["current_page"] = page_metadata(metadata, markup_file) || {}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def page_metadata(metadata, markup_file)
|
83
|
+
metadata["pages"].select { |page| current_page?(page, markup_file) }.first
|
84
|
+
end
|
85
|
+
|
86
|
+
def current_page?(page, markup_file)
|
87
|
+
page.has_key?("file") && page["file"] == markup_file.filename
|
88
|
+
end
|
89
|
+
|
90
|
+
def markup_files
|
91
|
+
Dir[*src_files].select { |f| supported?(File.extname(f)) }.map do |markup_filename|
|
92
|
+
MarkupFile.new markup_filename
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def supported?(extension)
|
97
|
+
MarkupFile.engines.one? { |engine| engine.supported?(extension) }
|
98
|
+
end
|
99
|
+
|
100
|
+
def output_folder_path(path)
|
101
|
+
File.join(output_folder, path)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|