forge 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitmodules +3 -0
- data/.rspec +1 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +81 -0
- data/LICENSE +20 -0
- data/README.md +24 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/forge +12 -0
- data/features/create.feature +34 -0
- data/features/link.feature +14 -0
- data/features/step_definitions/forge_steps.rb +38 -0
- data/features/support/env.rb +17 -0
- data/forge.gemspec +135 -0
- data/layouts/config/config.json.erb +13 -0
- data/layouts/config/stylesheet_header.erb +11 -0
- data/layouts/default/functions/functions.php.erb +21 -0
- data/layouts/default/stylesheets/_reset.scss +5 -0
- data/layouts/default/stylesheets/_typography.scss +5 -0
- data/layouts/default/stylesheets/style.css.scss.erb +28 -0
- data/layouts/default/templates/404.php.erb +10 -0
- data/layouts/default/templates/archive.php.erb +11 -0
- data/layouts/default/templates/attachment.php.erb +34 -0
- data/layouts/default/templates/comments.php +2 -0
- data/layouts/default/templates/footer.php +9 -0
- data/layouts/default/templates/header.php.erb +30 -0
- data/layouts/default/templates/index.php +6 -0
- data/layouts/default/templates/page.php +18 -0
- data/layouts/default/templates/partials/loop.php.erb +30 -0
- data/layouts/default/templates/search.php.erb +14 -0
- data/layouts/default/templates/sidebar.php +9 -0
- data/layouts/default/templates/single.php.erb +32 -0
- data/layouts/lib/forge-settings/README.md +43 -0
- data/layouts/lib/forge-settings/classes/settings.php +11 -0
- data/layouts/lib/forge-settings/classes/settings/collection.php +190 -0
- data/layouts/lib/forge-settings/classes/settings/option.php +125 -0
- data/layouts/lib/forge-settings/classes/settings/option/select.php +30 -0
- data/layouts/lib/forge-settings/classes/settings/option/text.php +15 -0
- data/layouts/lib/forge-settings/classes/settings/section.php +56 -0
- data/lib/forge.rb +11 -0
- data/lib/forge/builder.rb +165 -0
- data/lib/forge/cli.rb +86 -0
- data/lib/forge/config.rb +63 -0
- data/lib/forge/error.rb +8 -0
- data/lib/forge/generator.rb +128 -0
- data/lib/forge/guard.rb +57 -0
- data/lib/forge/project.rb +91 -0
- data/lib/forge/version.rb +3 -0
- data/lib/guard/forge/assets.rb +31 -0
- data/lib/guard/forge/config.rb +31 -0
- data/lib/guard/forge/functions.rb +31 -0
- data/lib/guard/forge/templates.rb +28 -0
- data/spec/lib/forge/config_spec.rb +79 -0
- data/spec/lib/forge/project_spec.rb +34 -0
- data/spec/spec_helper.rb +13 -0
- metadata +263 -0
data/lib/forge/config.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Forge
|
4
|
+
# Reads/Writes a configuration file in the user's home directory
|
5
|
+
#
|
6
|
+
class Config
|
7
|
+
|
8
|
+
@config
|
9
|
+
|
10
|
+
attr_accessor :config
|
11
|
+
|
12
|
+
def initialize()
|
13
|
+
@config = {
|
14
|
+
:theme => {
|
15
|
+
:author => nil,
|
16
|
+
:author_url => nil,
|
17
|
+
},
|
18
|
+
:links => []
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Provides access to the config using the Hash square brackets
|
23
|
+
def [](var)
|
24
|
+
@config[var]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Allows modifying variables through hash square brackets
|
28
|
+
def []=(var, value)
|
29
|
+
@config[var] = value
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the path to the user's configuration file
|
33
|
+
def config_file
|
34
|
+
@config_file ||= File.expand_path(File.join('~', '.forge', 'config.yml'))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Writes the configuration file
|
38
|
+
def write(options={})
|
39
|
+
# If we're unit testing then it helps to use a
|
40
|
+
# StringIO object instead of a file buffer
|
41
|
+
io = options[:io] || File.open(self.config_file, 'w')
|
42
|
+
|
43
|
+
io.write JSON.generate(@config)
|
44
|
+
|
45
|
+
io.close
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Loads config declarations in user's home dir
|
51
|
+
#
|
52
|
+
# If file does not exist then it will be created
|
53
|
+
def read
|
54
|
+
return write unless File.exists?(self.config_file)
|
55
|
+
|
56
|
+
data = File.open(self.config_file).read
|
57
|
+
|
58
|
+
@config = data.empty? ? {} : JSON.parse(data)
|
59
|
+
|
60
|
+
self
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/forge/error.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
|
2
|
+
module Forge
|
3
|
+
class Generator
|
4
|
+
class << self
|
5
|
+
def run(project, layout='default')
|
6
|
+
generator = self.new(project, layout)
|
7
|
+
generator.run
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(project, layout='default')
|
12
|
+
@project = project
|
13
|
+
@task = project.task
|
14
|
+
@layout = layout
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_structure
|
18
|
+
# Create the build directory for Forge output
|
19
|
+
@task.empty_directory @project.build_path
|
20
|
+
|
21
|
+
source_paths = [
|
22
|
+
['assets', 'images'],
|
23
|
+
['assets', 'javascripts'],
|
24
|
+
['assets', 'stylesheets'],
|
25
|
+
|
26
|
+
['functions'],
|
27
|
+
|
28
|
+
['includes'],
|
29
|
+
|
30
|
+
['templates', 'pages'],
|
31
|
+
['templates', 'partials'],
|
32
|
+
]
|
33
|
+
|
34
|
+
# Build out Forge structure in the source directory
|
35
|
+
source_paths.each do |path|
|
36
|
+
@task.empty_directory File.join(@project.source_path, path)
|
37
|
+
end
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def copy_stylesheets
|
43
|
+
source = File.expand_path(File.join(self.layout_path, 'stylesheets'))
|
44
|
+
target = File.expand_path(File.join(@project.assets_path, 'stylesheets'))
|
45
|
+
|
46
|
+
render_directory(source, target)
|
47
|
+
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def copy_templates
|
52
|
+
source = File.expand_path(File.join(self.layout_path, 'templates'))
|
53
|
+
target = File.expand_path(File.join(@project.source_path, 'templates'))
|
54
|
+
|
55
|
+
render_directory(source, target)
|
56
|
+
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def copy_settings_library
|
61
|
+
settings_path = @task.find_in_source_paths(File.join('lib', 'forge-settings', 'classes'))
|
62
|
+
|
63
|
+
source = File.expand_path(settings_path)
|
64
|
+
target = File.expand_path(File.join(@project.includes_path, 'forge-settings', '.'))
|
65
|
+
|
66
|
+
@task.directory(source, target)
|
67
|
+
end
|
68
|
+
|
69
|
+
def copy_functions
|
70
|
+
source = File.expand_path(File.join(self.layout_path, 'functions', 'functions.php.erb'))
|
71
|
+
target = File.expand_path(File.join(@project.source_path, 'functions', 'functions.php'))
|
72
|
+
|
73
|
+
write_template(source, target)
|
74
|
+
end
|
75
|
+
|
76
|
+
def layout_path
|
77
|
+
@layout_path ||= File.join(Forge::ROOT, 'layouts', @layout)
|
78
|
+
end
|
79
|
+
|
80
|
+
def run
|
81
|
+
write_config
|
82
|
+
create_structure
|
83
|
+
copy_stylesheets
|
84
|
+
copy_templates
|
85
|
+
copy_functions
|
86
|
+
copy_settings_library
|
87
|
+
return self
|
88
|
+
end
|
89
|
+
|
90
|
+
def write_config
|
91
|
+
write_template(['config', 'config.json.erb'], @project.config_file)
|
92
|
+
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
def write_template(source, target)
|
97
|
+
source = File.join(source)
|
98
|
+
template = File.expand_path(@task.find_in_source_paths((source)))
|
99
|
+
target = File.expand_path(File.join(target))
|
100
|
+
|
101
|
+
@task.create_file target do
|
102
|
+
@project.parse_erb(template)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
protected
|
107
|
+
def render_directory(source, target)
|
108
|
+
Dir.glob("#{source}/**/*") do |file|
|
109
|
+
unless File.directory?(file)
|
110
|
+
source_file = file.gsub(source, '')
|
111
|
+
target_file = File.join(target, source_file)
|
112
|
+
|
113
|
+
if source_file.end_with? ".erb"
|
114
|
+
target_file = target_file.slice(0..-5)
|
115
|
+
|
116
|
+
content = @project.parse_erb(file)
|
117
|
+
else
|
118
|
+
content = File.open(file).read
|
119
|
+
end
|
120
|
+
|
121
|
+
@task.create_file target_file do
|
122
|
+
content
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/forge/guard.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/guard'
|
3
|
+
|
4
|
+
module Forge
|
5
|
+
module Guard
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :project, :task, :builder
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.add_guard(&block)
|
12
|
+
@additional_guards ||= []
|
13
|
+
@additional_guards << block
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.start(project, task, options={}, livereload={})
|
17
|
+
@project = project
|
18
|
+
@task = task
|
19
|
+
@builder = Builder.new(project)
|
20
|
+
|
21
|
+
options_hash = ""
|
22
|
+
options.each do |k,v|
|
23
|
+
options_hash << ", :#{k} => '#{v}'"
|
24
|
+
end
|
25
|
+
|
26
|
+
assets_path = @project.assets_path.gsub(/#{@project.root}\//, '')
|
27
|
+
source_path = @project.source_path.gsub(/#{@project.root}\//, '')
|
28
|
+
config_file = @project.config_file.gsub(/#{@project.root}\//, '')
|
29
|
+
|
30
|
+
guardfile_contents = %Q{
|
31
|
+
guard 'forgeconfig'#{options_hash} do
|
32
|
+
watch("#{config_file}")
|
33
|
+
end
|
34
|
+
guard 'forgeassets' do
|
35
|
+
watch(%r{#{assets_path}/javascripts/*})
|
36
|
+
watch(%r{#{assets_path}/stylesheets/*})
|
37
|
+
watch(%r{#{assets_path}/images/*})
|
38
|
+
end
|
39
|
+
guard 'forgetemplates' do
|
40
|
+
watch(%r{#{source_path}/templates/*})
|
41
|
+
watch(%r{#{source_path}/partials/*})
|
42
|
+
end
|
43
|
+
guard 'forgefunctions' do
|
44
|
+
watch(%r{#{source_path}/functions/*})
|
45
|
+
watch(%r{#{source_path}/includes/*})
|
46
|
+
end
|
47
|
+
}
|
48
|
+
|
49
|
+
(@additional_guards || []).each do |block|
|
50
|
+
result = block.call(options, livereload)
|
51
|
+
guardfile_contents << result unless result.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
::Guard.start({ :guardfile_contents => guardfile_contents })
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Forge
|
5
|
+
class Project
|
6
|
+
class << self
|
7
|
+
def create(root, config, task)
|
8
|
+
root = File.expand_path(root)
|
9
|
+
|
10
|
+
project = self.new(root, task, config)
|
11
|
+
Generator.run(project)
|
12
|
+
|
13
|
+
project
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_accessor :root, :config, :task
|
18
|
+
|
19
|
+
def initialize(root, task, config={})
|
20
|
+
@root = File.expand_path(root)
|
21
|
+
@config = config || {}
|
22
|
+
@task = task
|
23
|
+
|
24
|
+
self.load_config if @config.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def assets_path
|
28
|
+
@assets_path ||= File.join(self.source_path, 'assets')
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_path
|
32
|
+
File.join(self.root, '.forge', 'build')
|
33
|
+
end
|
34
|
+
|
35
|
+
def source_path
|
36
|
+
File.join(self.root, 'source')
|
37
|
+
end
|
38
|
+
|
39
|
+
def package_path
|
40
|
+
File.join(self.root, 'package')
|
41
|
+
end
|
42
|
+
|
43
|
+
def templates_path
|
44
|
+
File.join(self.source_path, 'templates')
|
45
|
+
end
|
46
|
+
|
47
|
+
def functions_path
|
48
|
+
File.join(self.source_path, 'functions')
|
49
|
+
end
|
50
|
+
|
51
|
+
def includes_path
|
52
|
+
File.join(self.source_path, 'includes')
|
53
|
+
end
|
54
|
+
|
55
|
+
def config_file
|
56
|
+
@config_file ||= File.join(self.root, 'config.json')
|
57
|
+
end
|
58
|
+
|
59
|
+
# Create a symlink from source to the project build dir
|
60
|
+
def link(source)
|
61
|
+
source = File.expand_path(source)
|
62
|
+
|
63
|
+
unless File.directory?(File.dirname(source))
|
64
|
+
raise Forge::LinkSourceDirNotFound
|
65
|
+
end
|
66
|
+
|
67
|
+
@task.link_file build_path, source
|
68
|
+
end
|
69
|
+
|
70
|
+
def theme_id
|
71
|
+
File.basename(self.root).gsub(/\W/, '_')
|
72
|
+
end
|
73
|
+
|
74
|
+
def load_config
|
75
|
+
unless File.exists?(self.config_file)
|
76
|
+
raise Error, "Could not find the config file, are you sure you're in a
|
77
|
+
forge project directory?"
|
78
|
+
end
|
79
|
+
|
80
|
+
self.config = JSON.parse File.open(config_file).read
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_binding
|
84
|
+
binding
|
85
|
+
end
|
86
|
+
|
87
|
+
def parse_erb(file)
|
88
|
+
ERB.new(::File.binread(file), nil, '-', '@output_buffer').result(binding)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/guard'
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
class ForgeAssets < ::Guard::Guard
|
6
|
+
|
7
|
+
def initialize(watchers=[], options={})
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def start
|
12
|
+
UI.info "Building all assets"
|
13
|
+
::Forge::Guard.builder.build_assets
|
14
|
+
end
|
15
|
+
|
16
|
+
# Called on Ctrl-\ signal
|
17
|
+
# This method should be principally used for long action like running all specs/tests/...
|
18
|
+
def run_all
|
19
|
+
UI.info "Rebuilding all assets"
|
20
|
+
::Forge::Guard.builder.clean_images
|
21
|
+
::Forge::Guard.builder.build_assets
|
22
|
+
end
|
23
|
+
|
24
|
+
# Called on file(s) modifications
|
25
|
+
def run_on_change(paths)
|
26
|
+
UI.info "Assets have changed, rebuilding..."
|
27
|
+
::Forge::Guard.builder.clean_images
|
28
|
+
::Forge::Guard.builder.build_assets
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/guard'
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
class ForgeConfig < ::Guard::Guard
|
6
|
+
def initialize(watchers=[], options={})
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
# Called on Ctrl-Z signal
|
11
|
+
# This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
|
12
|
+
def reload
|
13
|
+
UI.info "Reloading project config"
|
14
|
+
::Forge::Guard.project.load_config
|
15
|
+
end
|
16
|
+
|
17
|
+
# Called on Ctrl-\ signal
|
18
|
+
# This method should be principally used for long action like running all specs/tests/...
|
19
|
+
def run_all
|
20
|
+
UI.info "Reloading project config"
|
21
|
+
::Forge::Guard.project.load_config
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
# Called on file(s) modifications
|
26
|
+
def run_on_change(paths)
|
27
|
+
UI.info "Project config changed, reloading"
|
28
|
+
::Forge::Guard.project.load_config
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'guard'
|
2
|
+
require 'guard/guard'
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
class ForgeFunctions < ::Guard::Guard
|
6
|
+
def initialize(watchers=[], options={})
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
UI.info "Copying functions over"
|
12
|
+
::Forge::Guard.builder.copy_functions
|
13
|
+
::Forge::Guard.builder.copy_includes
|
14
|
+
end
|
15
|
+
|
16
|
+
def run_all
|
17
|
+
UI.info "Rebuilding all functions"
|
18
|
+
::Forge::Guard.builder.copy_functions
|
19
|
+
::Forge::Guard.builder.clean_includes
|
20
|
+
::Forge::Guard.builder.copy_includes
|
21
|
+
end
|
22
|
+
|
23
|
+
# Called on file(s) modifications
|
24
|
+
def run_on_change(paths)
|
25
|
+
UI.info "Functions have changed, copying over"
|
26
|
+
::Forge::Guard.builder.copy_functions
|
27
|
+
::Forge::Guard.builder.clean_includes
|
28
|
+
::Forge::Guard.builder.copy_includes
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|