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
@@ -0,0 +1,125 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
abstract class Settings_Option {
|
4
|
+
protected $_name, $_valid_values, $_value, $_type, $_default_value,
|
5
|
+
$_tab, $_label, $_description, $_parent_name, $_validation_function;
|
6
|
+
|
7
|
+
public function name( $name = NULL ) {
|
8
|
+
if ( NULL === $name )
|
9
|
+
return $this->_name;
|
10
|
+
|
11
|
+
$this->_name = $name;
|
12
|
+
return $this;
|
13
|
+
}
|
14
|
+
|
15
|
+
public function valid_values( $valid_values = NULL ) {
|
16
|
+
if ( NULL === $valid_values )
|
17
|
+
return $this->_valid_values;
|
18
|
+
|
19
|
+
$this->_valid_values = $valid_values;
|
20
|
+
return $this;
|
21
|
+
}
|
22
|
+
|
23
|
+
public function value( $value = NULL ) {
|
24
|
+
if ( NULL === $value ) {
|
25
|
+
return $this->_value;
|
26
|
+
}
|
27
|
+
|
28
|
+
$this->_value = $value;
|
29
|
+
return $this;
|
30
|
+
}
|
31
|
+
|
32
|
+
public function type( $type = NULL ) {
|
33
|
+
if ( NULL === $type )
|
34
|
+
return $this->_type;
|
35
|
+
|
36
|
+
$this->_type = $type;
|
37
|
+
return $this;
|
38
|
+
}
|
39
|
+
|
40
|
+
public function default_value( $default_value = NULL ) {
|
41
|
+
if ( NULL === $default_value )
|
42
|
+
return $this->_default_value;
|
43
|
+
|
44
|
+
$this->_default_value = $default_value;
|
45
|
+
return $this;
|
46
|
+
}
|
47
|
+
|
48
|
+
public function tab( $tab = NULL ) {
|
49
|
+
if ( NULL === $tab )
|
50
|
+
return $this->_tab;
|
51
|
+
|
52
|
+
$this->_tab = $tab;
|
53
|
+
return $this;
|
54
|
+
}
|
55
|
+
|
56
|
+
public function label( $label = NULL ) {
|
57
|
+
if ( NULL === $label )
|
58
|
+
return $this->_label;
|
59
|
+
|
60
|
+
$this->_label = $label;
|
61
|
+
return $this;
|
62
|
+
}
|
63
|
+
|
64
|
+
public function description( $description = NULL ) {
|
65
|
+
if ( NULL === $description )
|
66
|
+
return $this->_description;
|
67
|
+
|
68
|
+
$this->_description = $description;
|
69
|
+
return $this;
|
70
|
+
}
|
71
|
+
|
72
|
+
public function parent_name( $parent_name = NULL ) {
|
73
|
+
if ( NULL === $parent_name )
|
74
|
+
return $this->_parent_name;
|
75
|
+
|
76
|
+
$this->_parent_name = $parent_name;
|
77
|
+
return $this;
|
78
|
+
}
|
79
|
+
|
80
|
+
public function section( $section = NULL ) {
|
81
|
+
if ( NULL === $section )
|
82
|
+
return $this->_section;
|
83
|
+
|
84
|
+
$this->_section = $section;
|
85
|
+
return $this;
|
86
|
+
}
|
87
|
+
|
88
|
+
public function validation_function( $validation_function = NULL ) {
|
89
|
+
if ( NULL === $validation_function )
|
90
|
+
return $this->_validation_function;
|
91
|
+
|
92
|
+
$this->_validation_function = $validation_function;
|
93
|
+
return $this;
|
94
|
+
}
|
95
|
+
|
96
|
+
// The HTML ID takes the form 'parentname-optionname'
|
97
|
+
protected function html_id() {
|
98
|
+
return $this->parent_name() . '-' . $this->name();
|
99
|
+
}
|
100
|
+
|
101
|
+
// Name takes the form 'parentname[optionname]'
|
102
|
+
protected function html_name() {
|
103
|
+
return $this->parent_name() . '[' . $this->name() . ']';
|
104
|
+
}
|
105
|
+
|
106
|
+
public function register() {
|
107
|
+
add_settings_field(
|
108
|
+
$this->name(),
|
109
|
+
$this->label(),
|
110
|
+
array( &$this, 'to_html' ),
|
111
|
+
$this->parent_name(),
|
112
|
+
$this->section() );
|
113
|
+
}
|
114
|
+
|
115
|
+
public function validate( $value ) {
|
116
|
+
if ( $validation_function = $this->validation_function() ) {
|
117
|
+
return $validation_function( $value );
|
118
|
+
} else {
|
119
|
+
return $this->standard_validation( $value );
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
abstract public function to_html();
|
124
|
+
abstract protected function standard_validation( $value );
|
125
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
class Settings_Option_Select extends Settings_Option {
|
4
|
+
public function to_html() {
|
5
|
+
$id = $this->html_id();
|
6
|
+
$name = $this->html_name();
|
7
|
+
|
8
|
+
$output = "<select id='$id' name='$name'>";
|
9
|
+
|
10
|
+
foreach ( $this->valid_values() as $value => $text ) {
|
11
|
+
// If this value is selected, mark it so
|
12
|
+
$selected = selected( $this->value(), $value, false );
|
13
|
+
|
14
|
+
$output .= "<option value='$value' $selected >$text</option>";
|
15
|
+
}
|
16
|
+
|
17
|
+
$output .= "</select>";
|
18
|
+
|
19
|
+
echo $output;
|
20
|
+
}
|
21
|
+
|
22
|
+
protected function standard_validation( $value ) {
|
23
|
+
$valid_values = $this->valid_values();
|
24
|
+
if ( array_key_exists( $value, $valid_values ) ) {
|
25
|
+
return $value;
|
26
|
+
}
|
27
|
+
|
28
|
+
return $this->default_value();
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
class Settings_Option_Text extends Settings_Option {
|
4
|
+
public function to_html() {
|
5
|
+
$id = $this->html_id();
|
6
|
+
$name = $this->html_name();
|
7
|
+
$value = $this->value();
|
8
|
+
|
9
|
+
echo "<input type='text' id='$id' name='$name' value='$value' />";
|
10
|
+
}
|
11
|
+
|
12
|
+
protected function standard_validation( $value ) {
|
13
|
+
return trim( $value );
|
14
|
+
}
|
15
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
class Settings_Section {
|
4
|
+
protected $_id, $_title, $_description, $_parent_name;
|
5
|
+
|
6
|
+
public function __construct( $id, $title, $description, $parent_name ) {
|
7
|
+
$this->id( $id );
|
8
|
+
$this->title( $title );
|
9
|
+
$this->description( $description );
|
10
|
+
$this->parent_name( $parent_name );
|
11
|
+
}
|
12
|
+
|
13
|
+
public function id( $id = NULL ) {
|
14
|
+
if ( NULL === $id )
|
15
|
+
return $this->_id;
|
16
|
+
|
17
|
+
$this->_id = $id;
|
18
|
+
return $this;
|
19
|
+
}
|
20
|
+
|
21
|
+
public function title( $title = NULL ) {
|
22
|
+
if ( NULL === $title )
|
23
|
+
return $this->_title;
|
24
|
+
|
25
|
+
$this->_title = $title;
|
26
|
+
return $this;
|
27
|
+
}
|
28
|
+
|
29
|
+
public function description( $description = NULL ) {
|
30
|
+
if ( NULL === $description )
|
31
|
+
return $this->_description;
|
32
|
+
|
33
|
+
$this->_description = $description;
|
34
|
+
return $this;
|
35
|
+
}
|
36
|
+
|
37
|
+
public function parent_name( $parent_name = NULL ) {
|
38
|
+
if ( NULL === $parent_name )
|
39
|
+
return $this->_parent_name;
|
40
|
+
|
41
|
+
$this->_parent_name = $parent_name;
|
42
|
+
return $this;
|
43
|
+
}
|
44
|
+
|
45
|
+
public function description_html() {
|
46
|
+
echo "<p>{$this->description()}</p>";
|
47
|
+
}
|
48
|
+
|
49
|
+
public function register() {
|
50
|
+
add_settings_section(
|
51
|
+
$this->id(),
|
52
|
+
$this->title(),
|
53
|
+
array( &$this, 'description_html' ),
|
54
|
+
$this->parent_name() );
|
55
|
+
}
|
56
|
+
}
|
data/lib/forge.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'forge/error'
|
2
|
+
|
3
|
+
module Forge
|
4
|
+
ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
5
|
+
autoload :Guard, 'forge/guard'
|
6
|
+
autoload :CLI, 'forge/cli'
|
7
|
+
autoload :Project, 'forge/project'
|
8
|
+
autoload :Builder, 'forge/builder'
|
9
|
+
autoload :Generator, 'forge/generator'
|
10
|
+
autoload :Config, 'forge/config'
|
11
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'sprockets'
|
2
|
+
require 'sprockets-sass'
|
3
|
+
require 'sass'
|
4
|
+
require 'zip/zip'
|
5
|
+
require 'compass'
|
6
|
+
|
7
|
+
module Forge
|
8
|
+
class Builder
|
9
|
+
def initialize(project)
|
10
|
+
@project = project
|
11
|
+
@task = project.task
|
12
|
+
@templates_path = @project.templates_path
|
13
|
+
@assets_path = @project.assets_path
|
14
|
+
@functions_path = @project.functions_path
|
15
|
+
@includes_path = @project.includes_path
|
16
|
+
|
17
|
+
init_sprockets
|
18
|
+
end
|
19
|
+
|
20
|
+
# Runs all the methods necessary to build a completed project
|
21
|
+
def build
|
22
|
+
clean_build_directory
|
23
|
+
copy_templates
|
24
|
+
copy_functions
|
25
|
+
build_assets
|
26
|
+
end
|
27
|
+
|
28
|
+
# Use the rubyzip library to build a zip from the generated source
|
29
|
+
def zip
|
30
|
+
basename = File.basename(@project.root)
|
31
|
+
|
32
|
+
Zip::ZipFile.open(get_output_filename(basename), Zip::ZipFile::CREATE) do |zip|
|
33
|
+
# Get all filenames in the build directory recursively
|
34
|
+
filenames = Dir[File.join(@project.build_path, '**', '*')]
|
35
|
+
|
36
|
+
# Remove the build directory path from the filename
|
37
|
+
filenames.collect! {|path| path.gsub(/#{@project.build_path}\//, '')}
|
38
|
+
|
39
|
+
# Add each file in the build directory to the zip file
|
40
|
+
filenames.each do |filename|
|
41
|
+
zip.add File.join(basename, filename), File.join(@project.build_path, filename)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Empty out the build directory
|
47
|
+
def clean_build_directory
|
48
|
+
FileUtils.rm_rf Dir.glob(File.join(@project.build_path, '*'))
|
49
|
+
end
|
50
|
+
|
51
|
+
def clean_templates
|
52
|
+
# TODO: cleaner way of removing templates only?
|
53
|
+
Dir.glob(File.join(@project.build_path, '*.php')).each do |path|
|
54
|
+
FileUtils.rm path unless path.include?('functions.php')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def copy_templates
|
59
|
+
template_paths.each do |template_path|
|
60
|
+
FileUtils.cp template_path, @project.build_path unless File.directory?(template_path)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def copy_functions
|
65
|
+
FileUtils.cp_r File.join(@functions_path, 'functions.php'), @project.build_path
|
66
|
+
end
|
67
|
+
|
68
|
+
def clean_includes
|
69
|
+
FileUtils.rm_rf File.join(@project.build_path, 'includes')
|
70
|
+
end
|
71
|
+
|
72
|
+
def copy_includes
|
73
|
+
unless Dir.glob(File.join(@includes_path, '*')).empty?
|
74
|
+
FileUtils.cp_r @includes_path, @project.build_path
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def clean_images
|
79
|
+
FileUtils.rm_rf File.join(@project.build_path, 'images')
|
80
|
+
end
|
81
|
+
|
82
|
+
def build_assets
|
83
|
+
[['style.css'], ['js', 'theme.js']].each do |asset|
|
84
|
+
destination = File.join(@project.build_path, asset)
|
85
|
+
|
86
|
+
sprocket = @sprockets.find_asset(asset.last)
|
87
|
+
|
88
|
+
sprockets_error = false
|
89
|
+
|
90
|
+
# Catch any sprockets errors and continue the process
|
91
|
+
begin
|
92
|
+
FileUtils.mkdir_p(File.dirname(destination)) unless File.directory?(File.dirname(destination))
|
93
|
+
sprocket.write_to(destination) unless sprocket.nil?
|
94
|
+
|
95
|
+
if asset.last == 'style.css' && (not sprockets_error)
|
96
|
+
@task.prepend_file destination, @project.parse_erb(stylesheet_header)
|
97
|
+
end
|
98
|
+
rescue Exception => e
|
99
|
+
@task.say "Error while building #{asset.last}:"
|
100
|
+
@task.say e.message, Thor::Shell::Color::RED
|
101
|
+
File.open(destination, 'w') do |file|
|
102
|
+
file.puts(e.message)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Re-initializing sprockets to prevent further errors
|
106
|
+
# TODO: This is done for lack of a better solution
|
107
|
+
init_sprockets
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Copy the images directory over
|
112
|
+
FileUtils.cp_r File.join(@assets_path, 'images'), File.join(@project.build_path)
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def init_sprockets
|
118
|
+
@sprockets = Sprockets::Environment.new
|
119
|
+
|
120
|
+
['javascripts', 'stylesheets'].each do |dir|
|
121
|
+
@sprockets.append_path File.join(@assets_path, dir)
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
# Add all compass frameworks to the sass path
|
126
|
+
# TODO: This feels really hacky - is there a better way?
|
127
|
+
Compass::Frameworks::ALL.each do |framework|
|
128
|
+
Sass::Engine::DEFAULT_OPTIONS[:load_paths] << framework.stylesheets_directory
|
129
|
+
end
|
130
|
+
|
131
|
+
@sprockets.context_class.instance_eval do
|
132
|
+
def config
|
133
|
+
return {:name => 'asd'}
|
134
|
+
p "CALLING CONFIG"
|
135
|
+
@project.config
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def template_paths
|
141
|
+
Dir.glob(File.join(@templates_path, '**', '*'))
|
142
|
+
end
|
143
|
+
|
144
|
+
# Generate a unique filename for the zip output
|
145
|
+
def get_output_filename(basename)
|
146
|
+
filename = "#{basename}.zip"
|
147
|
+
|
148
|
+
i = 1
|
149
|
+
while File.exists?(filename)
|
150
|
+
filename = "#{basename}(#{i}).zip"
|
151
|
+
i += 1
|
152
|
+
end
|
153
|
+
|
154
|
+
filename
|
155
|
+
end
|
156
|
+
|
157
|
+
protected
|
158
|
+
def stylesheet_header
|
159
|
+
return @stylesheet_header unless @stylesheet_header.nil?
|
160
|
+
|
161
|
+
file = @task.find_in_source_paths(File.join('config', 'stylesheet_header.erb'))
|
162
|
+
@stylesheet_header = File.expand_path(file)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/forge/cli.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'yaml'
|
3
|
+
require 'guard/forge/assets'
|
4
|
+
require 'guard/forge/config'
|
5
|
+
require 'guard/forge/templates'
|
6
|
+
require 'guard/forge/functions'
|
7
|
+
|
8
|
+
module Forge
|
9
|
+
class CLI < Thor
|
10
|
+
include Thor::Actions
|
11
|
+
|
12
|
+
def self.source_root
|
13
|
+
File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'layouts'))
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "create DIRECTORY", "Creates a Forge project"
|
17
|
+
method_option :name, :type => :string, :desc => "The theme name"
|
18
|
+
method_option :uri, :type => :string, :desc => "The theme's uri"
|
19
|
+
method_option :author, :type => :string, :desc => "The author of the theme"
|
20
|
+
method_option :author_uri, :type => :string, :desc => "The author's uri"
|
21
|
+
method_option :interactive, :type => :boolean, :desc => "Use interactive configuration setup", :aliases => "-i"
|
22
|
+
def create(dir)
|
23
|
+
prompts = {
|
24
|
+
:name => "What is the name of this theme?",
|
25
|
+
:uri => "What is the website for this theme?",
|
26
|
+
:author => "Who is the author of this theme?",
|
27
|
+
:author_uri => "What is the author's website?"
|
28
|
+
}
|
29
|
+
|
30
|
+
theme = {}
|
31
|
+
|
32
|
+
prompts.each do |k,v|
|
33
|
+
theme[k] = options[k]
|
34
|
+
theme[k] = ask(v) if options[:interactive]
|
35
|
+
end
|
36
|
+
|
37
|
+
theme[:name] = dir if (theme[:name].nil? || theme[:name].empty?)
|
38
|
+
|
39
|
+
project = Forge::Project.create(dir, theme, self)
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "link PATH", "symlink the compiled version of theme to the specified path"
|
43
|
+
long_desc "This command will symlink the compiled version of the theme to the specified path.\n\n"+
|
44
|
+
"To compile the theme use the `forge watch` command"
|
45
|
+
def link(path)
|
46
|
+
project = Forge::Project.new('.', self)
|
47
|
+
|
48
|
+
FileUtils.mkdir_p project.build_path unless File.directory?(project.build_path)
|
49
|
+
|
50
|
+
do_link(project, path)
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "watch", "Start watch process"
|
54
|
+
def watch
|
55
|
+
project = Forge::Project.new('.', self)
|
56
|
+
|
57
|
+
# Empty the build directory before starting up to clean out old files
|
58
|
+
FileUtils.rm_rf project.build_path
|
59
|
+
FileUtils.mkdir_p project.build_path
|
60
|
+
|
61
|
+
Forge::Guard.start(project, self)
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "package", "Compile and zip your project"
|
65
|
+
def package
|
66
|
+
project = Forge::Project.new('.', self)
|
67
|
+
|
68
|
+
builder = Builder.new(project)
|
69
|
+
builder.build
|
70
|
+
builder.zip
|
71
|
+
end
|
72
|
+
|
73
|
+
protected
|
74
|
+
def do_link(project, path)
|
75
|
+
begin
|
76
|
+
project.link(path)
|
77
|
+
rescue LinkSourceDirNotFound
|
78
|
+
say_status :error, "The path #{File.dirname(path)} does not exist", :red
|
79
|
+
exit 2
|
80
|
+
rescue Errno::EEXIST
|
81
|
+
say_status :error, "The path #{path} already exsts", :red
|
82
|
+
exit 2
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|