fones 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/CHANGELOG.md +8 -0
  4. data/Gemfile +28 -0
  5. data/Gemfile.lock +108 -0
  6. data/LICENSE +20 -0
  7. data/README.md +61 -0
  8. data/Rakefile +54 -0
  9. data/VERSION +1 -0
  10. data/bin/fones +12 -0
  11. data/features/step_definitions/fones_steps.rb +38 -0
  12. data/features/support/env.rb +17 -0
  13. data/fones.gemspec +187 -0
  14. data/layouts/config/config.tt +19 -0
  15. data/layouts/default/css/_1030up.scss.erb +8 -0
  16. data/layouts/default/css/_1240up.scss.erb +8 -0
  17. data/layouts/default/css/_2x.scss.erb +40 -0
  18. data/layouts/default/css/_481up.scss.erb +109 -0
  19. data/layouts/default/css/_768up.scss.erb +280 -0
  20. data/layouts/default/css/_base.scss.erb +836 -0
  21. data/layouts/default/css/_grid.scss.erb +48 -0
  22. data/layouts/default/css/_header.scss.erb +18 -0
  23. data/layouts/default/css/_mixins.scss.erb +248 -0
  24. data/layouts/default/css/_normalize.scss.erb +536 -0
  25. data/layouts/default/css/_print.scss.erb +80 -0
  26. data/layouts/default/css/ie.scss.erb +52 -0
  27. data/layouts/default/css/login.scss.erb +65 -0
  28. data/layouts/default/css/style.css.scss.erb +111 -0
  29. data/layouts/default/functions/functions.php.erb +166 -0
  30. data/layouts/default/functions/library/admin.php.erb +131 -0
  31. data/layouts/default/functions/library/bones.php.erb +397 -0
  32. data/layouts/default/functions/library/custom-post-type.php.erb +122 -0
  33. data/layouts/default/functions/library/translation/README +18 -0
  34. data/layouts/default/functions/library/translation/da_DK.po +374 -0
  35. data/layouts/default/functions/library/translation/de_DE.po +385 -0
  36. data/layouts/default/functions/library/translation/default.po +372 -0
  37. data/layouts/default/functions/library/translation/es_ES.po +380 -0
  38. data/layouts/default/functions/library/translation/fr_FR.po +579 -0
  39. data/layouts/default/functions/library/translation/he_IL.po +382 -0
  40. data/layouts/default/functions/library/translation/hr.po +548 -0
  41. data/layouts/default/functions/library/translation/it_IT.po +376 -0
  42. data/layouts/default/functions/library/translation/ja.po +492 -0
  43. data/layouts/default/functions/library/translation/nb_NO.po +380 -0
  44. data/layouts/default/functions/library/translation/nl_NL.po +376 -0
  45. data/layouts/default/functions/library/translation/pl_PL.po +371 -0
  46. data/layouts/default/functions/library/translation/pt_PT.po +376 -0
  47. data/layouts/default/functions/library/translation/ru_RU.po +358 -0
  48. data/layouts/default/functions/library/translation/sv_SE.po +380 -0
  49. data/layouts/default/functions/library/translation/translation.php.erb +18 -0
  50. data/layouts/default/functions/library/translation/zh_CN.po +382 -0
  51. data/layouts/default/img/apple-icon-touch.png +0 -0
  52. data/layouts/default/img/custom-post-icon.png +0 -0
  53. data/layouts/default/img/favicon.ico +0 -0
  54. data/layouts/default/img/favicon.png +0 -0
  55. data/layouts/default/img/login-logo.png +0 -0
  56. data/layouts/default/img/nothing.gif +0 -0
  57. data/layouts/default/img/nothumb.gif +0 -0
  58. data/layouts/default/img/screenshot.png +0 -0
  59. data/layouts/default/img/win8-tile-icon.png +0 -0
  60. data/layouts/default/js/admin.js +1 -0
  61. data/layouts/default/js/libs/modernizr.custom.min.js +4 -0
  62. data/layouts/default/js/scripts.js +108 -0
  63. data/layouts/default/js/theme.js +2 -0
  64. data/layouts/default/templates/404.php.erb +43 -0
  65. data/layouts/default/templates/archive-custom_type.php.erb +73 -0
  66. data/layouts/default/templates/archive.php.erb +108 -0
  67. data/layouts/default/templates/attachment.php.erb +32 -0
  68. data/layouts/default/templates/comments.php.erb +121 -0
  69. data/layouts/default/templates/footer.php.erb +22 -0
  70. data/layouts/default/templates/header.php.erb +63 -0
  71. data/layouts/default/templates/index.php.erb +72 -0
  72. data/layouts/default/templates/page-custom.php.erb +66 -0
  73. data/layouts/default/templates/page.php.erb +60 -0
  74. data/layouts/default/templates/search.php.erb +71 -0
  75. data/layouts/default/templates/sidebar.php.erb +17 -0
  76. data/layouts/default/templates/single-custom_type.php.erb +78 -0
  77. data/layouts/default/templates/single.php.erb +61 -0
  78. data/layouts/default/templates/taxonomy-custom_cat.php.erb +87 -0
  79. data/lib/fones.rb +11 -0
  80. data/lib/forge/builder.rb +269 -0
  81. data/lib/forge/cli.rb +86 -0
  82. data/lib/forge/config.rb +61 -0
  83. data/lib/forge/engines.rb +12 -0
  84. data/lib/forge/error.rb +8 -0
  85. data/lib/forge/generator.rb +144 -0
  86. data/lib/forge/guard.rb +65 -0
  87. data/lib/forge/project.rb +162 -0
  88. data/lib/forge/version.rb +3 -0
  89. data/lib/guard/forge/assets.rb +31 -0
  90. data/lib/guard/forge/config.rb +34 -0
  91. data/lib/guard/forge/functions.rb +33 -0
  92. data/lib/guard/forge/templates.rb +28 -0
  93. data/pkg/fones-0.1.0.gem +0 -0
  94. data/spec/lib/forge/config_spec.rb +79 -0
  95. data/spec/lib/forge/project_spec.rb +34 -0
  96. data/spec/spec_helper.rb +13 -0
  97. metadata +437 -0
data/lib/fones.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'forge/error'
2
+
3
+ module Fones
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,269 @@
1
+ require 'sprockets'
2
+ require 'sprockets-sass'
3
+ require 'sass'
4
+ require 'less'
5
+ require 'zip/zip'
6
+ require 'forge/engines'
7
+
8
+ module Fones
9
+ class Builder
10
+ def initialize(project)
11
+ @project = project
12
+ @task = project.task
13
+ @templates_path = @project.templates_path
14
+ @assets_path = @project.assets_path
15
+ @functions_path = @project.functions_path
16
+ @includes_path = @project.includes_path
17
+ @package_path = @project.package_path
18
+
19
+ init_sprockets
20
+ end
21
+
22
+ # Runs all the methods necessary to build a completed project
23
+ def build
24
+ clean_build_directory
25
+ copy_templates
26
+ copy_functions
27
+ copy_includes
28
+ build_assets
29
+ end
30
+
31
+ # Use the rubyzip library to build a zip from the generated source
32
+ def zip(filename=nil)
33
+ filename = filename || File.basename(@project.root)
34
+ project_base = File.basename(@project.root)
35
+
36
+ zip_filename = File.join(File.basename(@package_path), "#{filename}.zip")
37
+ # Create a temporary file for RubyZip to write to
38
+ temp_filename = "#{zip_filename}.tmp"
39
+
40
+ File.delete(temp_filename) if File.exists?(temp_filename)
41
+
42
+ # Wrapping the zip creation in Thor's create_file to get "overwrite" prompts
43
+ # Note: I could be overcomplicating this
44
+ @task.create_file(zip_filename) do
45
+ Zip::ZipFile.open(temp_filename, Zip::ZipFile::CREATE) do |zip|
46
+ # Get all filenames in the build directory recursively
47
+ filenames = Dir[File.join(@project.build_path, '**', '*')]
48
+
49
+ # Remove the build directory path from the filename
50
+ filenames.collect! {|path| path.gsub(/#{@project.build_path}\//, '')}
51
+
52
+ # Add each file in the build directory to the zip file
53
+ filenames.each do |filename|
54
+ zip.add File.join(project_base, filename), File.join(@project.build_path, filename)
55
+ end
56
+ end
57
+
58
+ # Give Thor contents of zip file for "overwrite" prompt
59
+ File.open(temp_filename, 'rb') { |f| f.read }
60
+ end
61
+
62
+ # Clean up the temp file
63
+ File.delete(temp_filename)
64
+ end
65
+
66
+ # Empty out the build directory
67
+ def clean_build_directory
68
+ FileUtils.rm_rf Dir.glob(File.join(@project.build_path, '*'))
69
+ end
70
+
71
+ def clean_templates
72
+ # TODO: cleaner way of removing templates only?
73
+ Dir.glob(File.join(@project.build_path, '*.php')).each do |path|
74
+ FileUtils.rm path unless path.include?('functions.php')
75
+ end
76
+ end
77
+
78
+ def copy_templates
79
+ template_paths.each do |template_path|
80
+ # Skip directories
81
+ next if File.directory?(template_path)
82
+
83
+ if template_path.end_with?('.erb')
84
+ # Chop the .erb extension off the filename
85
+ destination = File.join(@project.build_path, File.basename(template_path).slice(0..-5))
86
+
87
+ write_erb(template_path, destination)
88
+ else
89
+ # Regular old copy of PHP-only files
90
+ FileUtils.cp template_path, @project.build_path
91
+ end
92
+ end
93
+ end
94
+
95
+ def clean_functions
96
+ FileUtils.rm File.join(@project.build_path, 'functions.php')
97
+ FileUtils.rm_rf File.join(@project.build_path, 'library')
98
+ end
99
+
100
+ def copy_functions
101
+ functions_erb_path = File.join(@functions_path, 'functions.php.erb')
102
+ functions_php_path = File.join(@functions_path, 'functions.php')
103
+
104
+ if File.exists?(functions_erb_path)
105
+ destination = File.join(@project.build_path, 'functions.php')
106
+ write_erb(functions_erb_path, destination)
107
+ elsif File.exists?(functions_php_path)
108
+ FileUtils.cp functions_php_path, @project.build_path
109
+ end
110
+
111
+ library_paths = Dir.glob(File.join(@functions_path, '*')).reject do |filename|
112
+ [functions_erb_path, functions_php_path].include?(filename)
113
+ end
114
+
115
+ unless library_paths.empty?
116
+
117
+ # Iterate over all files in source/library, skipping the actual functions.php file
118
+ paths = Dir.glob(File.join(@functions_path, '**', '*')).reject do |filename|
119
+ [functions_erb_path, functions_php_path].include?(filename)
120
+ end
121
+
122
+ copy_paths_with_erb(paths, @functions_path, @project.build_path)
123
+ end
124
+ end
125
+
126
+ def clean_includes
127
+ FileUtils.rm_rf File.join(@project.build_path, 'includes')
128
+ end
129
+
130
+ def copy_includes
131
+ unless Dir.glob(File.join(@includes_path, '*')).empty?
132
+ # Create the includes folder in the build directory
133
+ FileUtils.mkdir(File.join(@project.build_path, 'includes'))
134
+
135
+ # Iterate over all files in source/includes, so we can exclude if necessary
136
+ paths = Dir.glob(File.join(@includes_path, '**', '*'))
137
+ copy_paths_with_erb(paths, @includes_path, File.join(@project.build_path, 'includes'))
138
+ end
139
+ end
140
+
141
+ def clean_images
142
+ FileUtils.rm_rf File.join(@project.build_path, 'img')
143
+ end
144
+
145
+ def build_assets
146
+ [['style.css'], ['css', 'ie.css'], ['css', 'login.css'], ['js', 'theme.js'], ['js', 'admin.js']].each do |asset|
147
+ destination = File.join(@project.build_path, asset)
148
+
149
+ sprocket = @sprockets.find_asset(asset.last)
150
+
151
+ # Catch any sprockets errors and continue the process
152
+ begin
153
+ @task.shell.mute do
154
+ FileUtils.mkdir_p(File.dirname(destination)) unless File.directory?(File.dirname(destination))
155
+ sprocket.write_to(destination) unless sprocket.nil?
156
+
157
+ if @project.config[:compress_js] && destination.end_with?('.js')
158
+ require "yui/compressor"
159
+
160
+ # Grab the initial sprockets output
161
+ sprockets_output = File.open(destination, 'r').read
162
+
163
+ # Re-write the file, minified
164
+ File.open(destination, 'w') do |file|
165
+ file.write(YUI::JavaScriptCompressor.new.compress(sprockets_output))
166
+ end
167
+ end
168
+ end
169
+ rescue Exception => e
170
+ @task.say "Error while building #{asset.last}:"
171
+ @task.say e.message, Thor::Shell::Color::RED
172
+ File.open(destination, 'w') do |file|
173
+ file.puts(e.message)
174
+ end
175
+
176
+ # Re-initializing sprockets to prevent further errors
177
+ # TODO: This is done for lack of a better solution
178
+ init_sprockets
179
+ end
180
+ end
181
+
182
+ # Copy the images directory over
183
+ FileUtils.cp_r(File.join(@assets_path, 'img'), @project.build_path) if File.exists?(File.join(@assets_path, 'img'))
184
+
185
+ # Check for screenshot and move it into main build directory
186
+ Dir.glob(File.join(@project.build_path, 'img', '*')).each do |filename|
187
+ if filename.index(/(screenshot|favicon)\.(png|jpg|jpeg|gif|ico)/)
188
+ FileUtils.mv(filename, @project.build_path + File::SEPARATOR )
189
+ end
190
+ end
191
+ end
192
+
193
+ private
194
+
195
+ def copy_paths_with_erb(paths, source_dir, destination_dir)
196
+ paths.each do |path|
197
+ # Remove source directory from full file path to get the relative path
198
+ relative_path = path.gsub(source_dir, '')
199
+
200
+ destination = File.join(destination_dir, relative_path)
201
+
202
+ if destination.end_with?('.erb')
203
+ # Remove the .erb extension if the path was an erb file
204
+ destination = destination.slice(0..-5)
205
+ # And process it as an erb
206
+ write_erb(path, destination)
207
+ else
208
+ # Otherwise, we simply move the file over
209
+ FileUtils.mkdir_p(destination) if File.directory?(path)
210
+ FileUtils.cp path, destination unless File.directory?(path)
211
+ end
212
+ end
213
+ end
214
+
215
+ def init_sprockets
216
+ @sprockets = Sprockets::Environment.new
217
+
218
+ ['js', 'css', 'lib'].each do |dir|
219
+ @sprockets.append_path File.join(@assets_path, dir)
220
+ end
221
+
222
+ # Add assets/styleshets to load path for Less Engine
223
+ Tilt::LessTemplateWithPaths.load_path = File.join(@assets_path, 'css')
224
+
225
+ # Passing the @project instance variable to the Sprockets::Context instance
226
+ # used for processing the asset ERB files. Ruby meta-programming, FTW.
227
+ @sprockets.context_class.instance_exec(@project) do |project|
228
+ define_method :config do
229
+ project.config
230
+ end
231
+ end
232
+ end
233
+
234
+ def template_paths
235
+ Dir.glob(File.join(@templates_path, '**', '*'))
236
+ end
237
+
238
+ # Generate a unique filename for the zip output
239
+ def get_output_filename(basename)
240
+ package_path_base = File.basename(@package_path)
241
+ filename = File.join(package_path_base, "#{basename}.zip")
242
+
243
+ i = 1
244
+ while File.exists?(filename)
245
+ filename = File.join(package_path_base, "#{basename}(#{i}).zip")
246
+ i += 1
247
+ end
248
+
249
+ filename
250
+ end
251
+
252
+ protected
253
+
254
+ # Write an .erb from source to destination, catching and reporting errors along the way
255
+ def write_erb(source, destination)
256
+ begin
257
+ @task.shell.mute do
258
+ @task.create_file(destination) do
259
+ @project.parse_erb(source)
260
+ end
261
+ end
262
+ rescue Exception => e
263
+ @task.say "Error while building #{File.basename(source)}:"
264
+ @task.say e.message + "\n", Thor::Shell::Color::RED
265
+ exit
266
+ end
267
+ end
268
+ end
269
+ 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 Fones
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 Fones project"
17
+ def create(dir)
18
+ theme = {}
19
+ theme[:name] = dir
20
+
21
+ project = Fones::Project.create(dir, theme, self)
22
+ end
23
+
24
+ desc "link PATH", "Create a symbolic link to the compilation directory"
25
+ long_desc "This command will symlink the compiled version of the theme to the specified path.\n\n"+
26
+ "To compile the theme use the `forge watch` command"
27
+ def link(path)
28
+ project = Fones::Project.new('.', self)
29
+
30
+ FileUtils.mkdir_p project.build_path unless File.directory?(project.build_path)
31
+
32
+ do_link(project, path)
33
+ end
34
+
35
+ desc "watch", "Start watch process"
36
+ long_desc "Watches the source directory in your project for changes, and reflects those changes in a compile folder"
37
+ method_option :config, :type => :string, :desc => "Name of alternate config file"
38
+ def watch
39
+ project = Fones::Project.new('.', self, nil, options[:config])
40
+
41
+ # Empty the build directory before starting up to clean out old files
42
+ FileUtils.rm_rf project.build_path
43
+ FileUtils.mkdir_p project.build_path
44
+
45
+ Fones::Guard.start(project, self)
46
+ end
47
+
48
+ desc "build DIRECTORY", "Build your theme into specified directory"
49
+ method_option :config, :type => :string, :desc => "Name of alternate config file"
50
+ def build(dir='build')
51
+ project = Fones::Project.new('.', self, nil, options[:config])
52
+
53
+ builder = Builder.new(project)
54
+ builder.build
55
+
56
+ Dir.glob(File.join(dir, '**', '*')).each do |file|
57
+ shell.mute { remove_file(file) }
58
+ end
59
+
60
+ directory(project.build_path, dir)
61
+ end
62
+
63
+ desc "package FILENAME", "Compile and zip your project to FILENAME.zip"
64
+ method_option :config, :type => :string, :desc => "Name of alternate config file"
65
+ def package(filename=nil)
66
+ project = Fones::Project.new('.', self, nil, options[:config])
67
+
68
+ builder = Builder.new(project)
69
+ builder.build
70
+ builder.zip(filename)
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
@@ -0,0 +1,61 @@
1
+ module Fones
2
+ # Reads/Writes a configuration file in the user's home directory
3
+ #
4
+ class Config
5
+
6
+ @config
7
+
8
+ attr_accessor :config
9
+
10
+ def initialize()
11
+ @config = {
12
+ :theme => {
13
+ :author => nil,
14
+ :author_url => nil,
15
+ },
16
+ :links => []
17
+ }
18
+ end
19
+
20
+ # Provides access to the config using the Hash square brackets
21
+ def [](var)
22
+ @config[var]
23
+ end
24
+
25
+ # Allows modifying variables through hash square brackets
26
+ def []=(var, value)
27
+ @config[var] = value
28
+ end
29
+
30
+ # Returns the path to the user's configuration file
31
+ def config_file
32
+ @config_file ||= File.expand_path(File.join('~', '.forge', 'config.yml'))
33
+ end
34
+
35
+ # Writes the configuration file
36
+ def write(options={})
37
+ # If we're unit testing then it helps to use a
38
+ # StringIO object instead of a file buffer
39
+ io = options[:io] || File.open(self.config_file, 'w')
40
+
41
+ io.write JSON.generate(@config)
42
+
43
+ io.close
44
+
45
+ self
46
+ end
47
+
48
+ # Loads config declarations in user's home dir
49
+ #
50
+ # If file does not exist then it will be created
51
+ def read
52
+ return write unless File.exists?(self.config_file)
53
+
54
+ data = File.open(self.config_file).read
55
+
56
+ @config = data.empty? ? {} : JSON.parse(data)
57
+
58
+ self
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ module Tilt
2
+ class LessTemplateWithPaths < LessTemplate
3
+ class << self
4
+ attr_accessor :load_path
5
+ end
6
+
7
+ def prepare
8
+ parser = ::Less::Parser.new(:filename => eval_file, :line => line, :paths => [self.class.load_path])
9
+ @engine = parser.parse(data)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module Fones
2
+ class Error < StandardError
3
+ end
4
+
5
+ # Raised when the link source could not be found
6
+ class LinkSourceDirNotFound < Error
7
+ end
8
+ end