fones 0.1.0

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