forge 0.0.1
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.
- 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
|