ymdp 0.1.3.2 → 0.1.4
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/VERSION +1 -1
- data/lib/ymdp.rb +1 -1
- data/lib/ymdp/commands/build.rb +14 -0
- data/lib/ymdp/compiler/base.rb +206 -0
- data/lib/ymdp/compiler/domains.rb +103 -0
- data/lib/ymdp/{support → compiler}/git_helper.rb +0 -0
- data/lib/ymdp/compiler/options.rb +48 -0
- data/lib/ymdp/compiler/template.rb +358 -304
- data/lib/ymdp/configuration/config.rb +39 -0
- data/lib/ymdp/{support → processor}/form_post.rb +1 -1
- data/lib/ymdp/processor/validator.rb +2 -1
- data/lib/ymdp/{support → processor}/w3c.rb +0 -0
- data/lib/ymdp/support/file.rb +25 -1
- data/spec/compiler_spec.rb +154 -0
- data/spec/compiler_template_spec.rb +104 -0
- data/spec/data/config/servers.yml +9 -8
- data/spec/data/config/servers.yml.example +9 -8
- data/spec/domains_spec.rb +101 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/stubs.rb +42 -0
- data/ymdp.gemspec +17 -6
- metadata +16 -5
- data/lib/ymdp/compiler/compiler.rb +0 -278
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/lib/ymdp.rb
CHANGED
@@ -18,7 +18,7 @@ Dir["#{dir}/*.rb"].each do |path|
|
|
18
18
|
require File.expand_path(path)
|
19
19
|
end
|
20
20
|
|
21
|
-
["support", "configuration"
|
21
|
+
["support", "configuration"].each do |directory|
|
22
22
|
Dir["#{dir}/#{directory}/*.rb"].each do |path|
|
23
23
|
require File.expand_path(path)
|
24
24
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
YMDP_ENV = "build"
|
2
|
+
|
3
|
+
require 'compiler/options'
|
4
|
+
require 'compiler/domains'
|
5
|
+
|
6
|
+
YMDP::Compiler::Template::Base.base_path = BASE_PATH
|
7
|
+
YMDP::Compiler::Template::Base.servers = SERVERS
|
8
|
+
|
9
|
+
YMDP::Compiler::Domains.base_path = BASE_PATH
|
10
|
+
YMDP::Compiler::Domains.servers = SERVERS
|
11
|
+
|
12
|
+
@options = YMDP::Compiler::Options.parse
|
13
|
+
YMDP::Compiler::Domains.new(@options).compile
|
14
|
+
|
@@ -0,0 +1,206 @@
|
|
1
|
+
# Compiles the source code for an individual domain.
|
2
|
+
#
|
3
|
+
# Usage:
|
4
|
+
#
|
5
|
+
# @compiler = YMDP::Compiler::Base.new('staging', 'asdfh23rh2fas', :base_path => ".", :server => {
|
6
|
+
# "server" => "staging", "application_id" => "12345", "assets_id" => "abcdefg_1" })
|
7
|
+
#
|
8
|
+
# You can then compile the domain:
|
9
|
+
#
|
10
|
+
# @compiler.build
|
11
|
+
#
|
12
|
+
module YMDP
|
13
|
+
module Compiler
|
14
|
+
class Base
|
15
|
+
attr_accessor :domain, :git_hash, :options, :base_path, :server
|
16
|
+
|
17
|
+
# A TemplateCompiler instance covers a single domain, handling all the processing necessary to
|
18
|
+
# convert the application source code into usable destination files ready for upload.
|
19
|
+
#
|
20
|
+
def initialize(domain, git_hash, options={})
|
21
|
+
@domain = domain
|
22
|
+
@git_hash = git_hash
|
23
|
+
@options = options
|
24
|
+
@base_path = options[:base_path]
|
25
|
+
@server = options[:server]
|
26
|
+
|
27
|
+
raise ArgumentError.new("base_path is required") unless @base_path
|
28
|
+
end
|
29
|
+
|
30
|
+
# Perform all the processing for a single domain.
|
31
|
+
#
|
32
|
+
# This is the main method on this object.
|
33
|
+
#
|
34
|
+
def process_all
|
35
|
+
create_directory("servers/#{domain}")
|
36
|
+
clean_domain
|
37
|
+
["views", "assets"].each do |dir|
|
38
|
+
process_path("#{base_path}/app/#{dir}/")
|
39
|
+
end
|
40
|
+
process_all_translations
|
41
|
+
copy_images
|
42
|
+
end
|
43
|
+
|
44
|
+
# Do all the processing necessary to convert all the application source code from the given path
|
45
|
+
# into usable destination files ready for upload to the server:
|
46
|
+
#
|
47
|
+
# - create server directory if necessary,
|
48
|
+
# - for each file in the source path, build the file, and
|
49
|
+
# - copy the images from the source to the destination directory.
|
50
|
+
#
|
51
|
+
def process_path(path)
|
52
|
+
$stdout.puts "Processing #{path} for #{domain}"
|
53
|
+
process_all_files(path)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Process all code files (HTML and JavaScript) into usable, complete HTML files.
|
57
|
+
#
|
58
|
+
def process_all_files(path)
|
59
|
+
Dir["#{path}**/*"].each do |f|
|
60
|
+
build_file(f)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Build this file if it's either:
|
65
|
+
# - a view, but not a partial or layout, or
|
66
|
+
# - a JavaScript file.
|
67
|
+
#
|
68
|
+
def build_file(file)
|
69
|
+
params = {
|
70
|
+
:file => file,
|
71
|
+
:domain => domain,
|
72
|
+
:git_hash => git_hash,
|
73
|
+
:message => options[:message],
|
74
|
+
:verbose => options[:verbose],
|
75
|
+
:base_path => base_path,
|
76
|
+
:server => server
|
77
|
+
}
|
78
|
+
if build?(file)
|
79
|
+
if file =~ /(\.haml|\.erb)$/
|
80
|
+
YMDP::Compiler::Template::View.new(params).build
|
81
|
+
elsif file =~ /\.js$/
|
82
|
+
YMDP::Compiler::Template::JavaScript.new(params).build
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Convert all YRB translation files from YRB ".pres" format into a single JSON file per language.
|
88
|
+
#
|
89
|
+
def process_all_translations
|
90
|
+
$stdout.puts "Processing ./app/assets/yrb/ for #{domain}"
|
91
|
+
YMDP::Base.supported_languages.each do |lang|
|
92
|
+
process_each_yrb(lang)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Convert the YRB translation files of a single language for this domain into a single JSON file.
|
97
|
+
#
|
98
|
+
def process_each_yrb(lang)
|
99
|
+
tmp_file = "#{TMP_DIR}/keys_#{lang}.pres"
|
100
|
+
|
101
|
+
# Concatenate together all the YRB ".pres" files for this language into one file in the tmp dir.
|
102
|
+
#
|
103
|
+
F.concat_files("#{yrb_path}/#{lang}/*", tmp_file)
|
104
|
+
|
105
|
+
yrb = YMDP::Compiler::Template::YRB.new(:file => tmp_file, :domain => domain)
|
106
|
+
yrb.build
|
107
|
+
yrb.validate if CONFIG.validate_json_assets?
|
108
|
+
|
109
|
+
FileUtils.rm(tmp_file)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Creates a fresh destination directory structure for the code to be compiled into.
|
113
|
+
#
|
114
|
+
def clean_domain
|
115
|
+
dir = "#{servers_path}/#{domain}"
|
116
|
+
FileUtils.rm_rf("#{dir}/views")
|
117
|
+
FileUtils.rm_rf("#{dir}/assets/javascripts")
|
118
|
+
FileUtils.rm_rf("#{dir}/assets/stylesheets")
|
119
|
+
FileUtils.rm_rf("#{dir}/assets/yrb")
|
120
|
+
FileUtils.rm_rf("#{TMP_DIR}/")
|
121
|
+
FileUtils.mkdir_p(TMP_DIR)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Format text in a standard way for output to the screen.
|
125
|
+
#
|
126
|
+
def log(text)
|
127
|
+
"#{Time.now.to_s} #{text}"
|
128
|
+
end
|
129
|
+
|
130
|
+
# Convert a file's path from its source to its destination.
|
131
|
+
#
|
132
|
+
# The source directory is in the 'app' directory.
|
133
|
+
#
|
134
|
+
# The destination directory is made from the 'servers' root and the domain name.
|
135
|
+
#
|
136
|
+
# For example:
|
137
|
+
# - ./servers/staging
|
138
|
+
# - ./servers/alpha
|
139
|
+
#
|
140
|
+
def destination(path)
|
141
|
+
destination = path.dup
|
142
|
+
destination.gsub!("#{base_path}/app", "#{servers_path}/#{domain}")
|
143
|
+
end
|
144
|
+
|
145
|
+
# If this directory doesn't exist, create it and print that it's being created.
|
146
|
+
#
|
147
|
+
def create_directory(path)
|
148
|
+
dest = destination(path)
|
149
|
+
|
150
|
+
unless File.exists?("#{base_path}/#{path}")
|
151
|
+
$stdout.puts " create #{path}"
|
152
|
+
FileUtils.mkdir_p("#{base_path}/#{path}")
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Images don't require any processing, just copy them over into this domain's assets directory.
|
157
|
+
#
|
158
|
+
def copy_images
|
159
|
+
if options[:verbose]
|
160
|
+
$stdout.puts log("Moving images into #{servers_path}/#{domain}/assets/images...")
|
161
|
+
end
|
162
|
+
FileUtils.rm_rf("#{servers_path}/#{domain}/assets/images")
|
163
|
+
FileUtils.mkdir_p("#{servers_path}/#{domain}/assets")
|
164
|
+
FileUtils.cp_r("#{images_path}/", "#{servers_path}/#{domain}/assets")
|
165
|
+
end
|
166
|
+
|
167
|
+
# A filename beginning with an underscore is a partial.
|
168
|
+
#
|
169
|
+
def partial?(file)
|
170
|
+
file.split("/").last =~ /^_/
|
171
|
+
end
|
172
|
+
|
173
|
+
# A file in the layouts directory is a layout.
|
174
|
+
#
|
175
|
+
def layout?(file)
|
176
|
+
file =~ /\/app\/views\/layouts\//
|
177
|
+
end
|
178
|
+
|
179
|
+
# Build if it's not a partial and not a layout.
|
180
|
+
#
|
181
|
+
def build?(file)
|
182
|
+
!partial?(file) && !layout?(file)
|
183
|
+
end
|
184
|
+
|
185
|
+
def app_path
|
186
|
+
"#{base_path}/app"
|
187
|
+
end
|
188
|
+
|
189
|
+
def assets_path
|
190
|
+
"#{app_path}/assets"
|
191
|
+
end
|
192
|
+
|
193
|
+
def yrb_path
|
194
|
+
"#{assets_path}/yrb"
|
195
|
+
end
|
196
|
+
|
197
|
+
def images_path
|
198
|
+
"#{assets_path}/images"
|
199
|
+
end
|
200
|
+
|
201
|
+
def servers_path
|
202
|
+
"#{app_path}/servers"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'compiler/git_helper'
|
2
|
+
require 'compiler/base'
|
3
|
+
require 'compiler/template'
|
4
|
+
|
5
|
+
# Covers all the domains and the actions that are taken on all domains at once.
|
6
|
+
#
|
7
|
+
# Usage:
|
8
|
+
#
|
9
|
+
# YMDP::Compiler::Domains.new(:message => "Commit message").compile
|
10
|
+
#
|
11
|
+
# Options are provided by command-line parsing from YMDP::Compiler::Options.
|
12
|
+
#
|
13
|
+
module YMDP
|
14
|
+
module Compiler
|
15
|
+
# Covers all the domains and the actions that are taken on all domains at once.
|
16
|
+
#
|
17
|
+
class Domains
|
18
|
+
attr_accessor :git, :git_hash, :message, :domains, :options
|
19
|
+
|
20
|
+
def initialize(options=nil)
|
21
|
+
@options = options
|
22
|
+
@servers = @options[:servers]
|
23
|
+
@domains = @options[:domain] || all_domains
|
24
|
+
@domains = @domains.to_a
|
25
|
+
@message = @options[:message]
|
26
|
+
|
27
|
+
commit if @options[:commit]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Class Methods to handle global stuff like base path and server settings
|
31
|
+
|
32
|
+
def self.base_path= base_path
|
33
|
+
@@base_path = base_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.base_path
|
37
|
+
@@base_path
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.servers= servers
|
41
|
+
@@servers = servers
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.servers
|
45
|
+
@@servers
|
46
|
+
end
|
47
|
+
|
48
|
+
# Instance Methods to access global stuff like base path and server settings
|
49
|
+
|
50
|
+
def servers
|
51
|
+
@@servers
|
52
|
+
end
|
53
|
+
|
54
|
+
def base_path
|
55
|
+
@@base_path
|
56
|
+
end
|
57
|
+
|
58
|
+
# Compile the source code for all domains into their usable destination files.
|
59
|
+
#
|
60
|
+
def compile
|
61
|
+
Timer.new(:title => "YMDP").time do
|
62
|
+
clean_tmp_dir do
|
63
|
+
process_domains
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns all domains.
|
69
|
+
#
|
70
|
+
def all_domains
|
71
|
+
servers.servers.keys
|
72
|
+
end
|
73
|
+
|
74
|
+
# Commit to git and store the hash of the commit.
|
75
|
+
#
|
76
|
+
def commit
|
77
|
+
@git = GitHelper.new
|
78
|
+
@git.do_commit(@message)
|
79
|
+
@git_hash = git.get_hash(options[:branch])
|
80
|
+
end
|
81
|
+
|
82
|
+
# Process source code for each domain in turn.
|
83
|
+
#
|
84
|
+
def process_domains
|
85
|
+
domains.each do |domain|
|
86
|
+
compiler = YMDP::Compiler::Base.new(domain, git_hash, options)
|
87
|
+
|
88
|
+
compiler.process_all
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Perform a block, starting with a clean 'tmp' directory and ending with one.
|
93
|
+
#
|
94
|
+
def clean_tmp_dir
|
95
|
+
system "rm -rf #{TMP_DIR}"
|
96
|
+
system "mkdir #{TMP_DIR}"
|
97
|
+
yield
|
98
|
+
system "rm -rf #{TMP_DIR}"
|
99
|
+
system "mkdir #{TMP_DIR}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
File without changes
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module YMDP
|
2
|
+
module Compiler
|
3
|
+
# Command-line options processor for Compiler module.
|
4
|
+
#
|
5
|
+
class Options
|
6
|
+
# Parse command line options into an options hash.
|
7
|
+
#
|
8
|
+
def self.parse
|
9
|
+
options = {
|
10
|
+
:commit => false,
|
11
|
+
:branch => "master",
|
12
|
+
:base_path => BASE_PATH,
|
13
|
+
:servers => SERVERS
|
14
|
+
}
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
options[:commit] = false
|
17
|
+
options[:verbose] = CONFIG.verbose?
|
18
|
+
opts.banner = "Usage: build.rb [options]"
|
19
|
+
|
20
|
+
opts.on("-d", "--domain [domain]", "Force Domain") do |v|
|
21
|
+
options[:domain] = v
|
22
|
+
end
|
23
|
+
opts.on("-b", "--branch [branch]", "Current Branch") do |v|
|
24
|
+
options[:branch] = v
|
25
|
+
end
|
26
|
+
opts.on("-m", "--message [message]", "Commit Message") do |v|
|
27
|
+
options[:commit] = true
|
28
|
+
options[:message] = v
|
29
|
+
end
|
30
|
+
opts.on("-n", "--no-commit", "Don't Commit") do |v|
|
31
|
+
options[:commit] = false
|
32
|
+
end
|
33
|
+
opts.on("-v", "--verbose", "Verbose (show all file writes)") do |v|
|
34
|
+
options[:verbose] = true
|
35
|
+
end
|
36
|
+
opts.on("-r", "--rake [task]", "Execute Rake task") do |v|
|
37
|
+
options[:rake] = v
|
38
|
+
end
|
39
|
+
opts.on("-c", "--compress", "Compress JavaScript and CSS") do |v|
|
40
|
+
options[:compress] = v
|
41
|
+
end
|
42
|
+
end.parse!
|
43
|
+
|
44
|
+
options
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -7,379 +7,433 @@
|
|
7
7
|
#
|
8
8
|
# Usage:
|
9
9
|
#
|
10
|
-
# YMDP::Template::View.new(params).build
|
11
|
-
# YMDP::Template::JavaScript.new(params).build
|
10
|
+
# YMDP::Compiler::Template::View.new(params).build
|
11
|
+
# YMDP::Compiler::Template::JavaScript.new(params).build
|
12
12
|
#
|
13
|
-
# See YMDP::Template::Base#initialize for details on params.
|
13
|
+
# See YMDP::Compiler::Template::Base#initialize for details on params.
|
14
14
|
#
|
15
15
|
module YMDP
|
16
|
-
module
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
16
|
+
module Compiler
|
17
|
+
module Template
|
18
|
+
# Compiles a single file in a single domain, processing its Haml or ERB and turning
|
19
|
+
# it into usable destination files in the 'servers' directory.
|
20
|
+
#
|
21
|
+
class Base
|
22
|
+
# Usage:
|
23
|
+
#
|
24
|
+
# @template = YMDP::Compiler::Template::Base.new(params)
|
25
|
+
#
|
26
|
+
# Arguments:
|
27
|
+
#
|
28
|
+
# - verbose: boolean value, output verbose notices,
|
29
|
+
# - domain: string, indicates which domain the template is compiling to,
|
30
|
+
# - file: filename of the template in question,
|
31
|
+
# - hash: git hash of the latest commit,
|
32
|
+
# - message: commit message of the latest commit.
|
33
|
+
#
|
34
|
+
attr_accessor :domain, :server, :file, :assets_directory, :hash, :message
|
35
|
+
|
36
|
+
def initialize(params)
|
37
|
+
@verbose = params[:verbose]
|
38
|
+
@domain = params[:domain]
|
39
|
+
|
40
|
+
@file = params[:file]
|
41
|
+
@assets_directory = "/om/assets/#{servers[@domain]['assets_id']}"
|
42
|
+
@hash = params[:git_hash]
|
43
|
+
@message = params[:message]
|
41
44
|
|
42
|
-
|
45
|
+
set_content_variables
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
+
@view = base_filename(@file.split("/").last)
|
48
|
+
Application.current_view = @view
|
49
|
+
end
|
50
|
+
|
51
|
+
# Is the verbose setting on?
|
52
|
+
#
|
53
|
+
def verbose?
|
54
|
+
@verbose
|
55
|
+
end
|
47
56
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
57
|
+
# Parses the file 'content.yml' and adds each of its keys to the environment as
|
58
|
+
# an instance variable, so they will be available inside the template.
|
59
|
+
#
|
60
|
+
def set_content_variables
|
61
|
+
content = YAML.load_file("#{CONFIG_PATH}/content.yml")
|
62
|
+
content.each do |key, value|
|
63
|
+
attribute = "@#{key}"
|
64
|
+
instance_variable_set(attribute, value) unless instance_variable_defined?(attribute)
|
65
|
+
end
|
56
66
|
end
|
57
|
-
end
|
58
67
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
68
|
+
# If the filename begins with a _ it's a partial.
|
69
|
+
#
|
70
|
+
def partial?
|
71
|
+
@file =~ /#{base_path}\/app\/views\/_/
|
72
|
+
end
|
64
73
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
74
|
+
# Compile this view unless it is a partial.
|
75
|
+
#
|
76
|
+
def build
|
77
|
+
unless partial?
|
78
|
+
write_template(processed_template)
|
79
|
+
end
|
70
80
|
end
|
71
|
-
end
|
72
81
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
82
|
+
# Returns the compiled template code after its Haml or ERB has been processed.
|
83
|
+
#
|
84
|
+
def processed_template
|
85
|
+
result = ""
|
86
|
+
File.open(@file) do |f|
|
87
|
+
template = f.read
|
88
|
+
if @file =~ /\.haml$/
|
89
|
+
result = process_haml(template, @file)
|
90
|
+
else
|
91
|
+
result = process_template(template)
|
92
|
+
end
|
83
93
|
end
|
94
|
+
result
|
84
95
|
end
|
85
|
-
result
|
86
|
-
end
|
87
96
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
97
|
+
# Implemented in child classes, this defines what must be done to process a template.
|
98
|
+
#
|
99
|
+
def process_template(template)
|
100
|
+
raise "Define in child"
|
101
|
+
end
|
93
102
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
103
|
+
# Produces the destination path of this template, in the servers directory for
|
104
|
+
# the given domain.
|
105
|
+
#
|
106
|
+
# For example:
|
107
|
+
#
|
108
|
+
# source: app/views/authorize.html.haml
|
109
|
+
# destination: servers/staging/views/authorize.html.haml
|
110
|
+
#
|
111
|
+
def destination_path
|
112
|
+
# just the file, with no directory
|
113
|
+
filename = File.basename(@file)
|
105
114
|
|
106
|
-
|
107
|
-
|
115
|
+
# just the filename, with no extension
|
116
|
+
filename = convert_filename(filename)
|
108
117
|
|
109
|
-
|
110
|
-
|
118
|
+
# just the directory, with no file
|
119
|
+
directory = File.dirname(@file)
|
111
120
|
|
112
|
-
|
113
|
-
|
121
|
+
# replace the app directory with the server directory
|
122
|
+
relative_directory = directory.gsub!("#{base_path}/app", server_path)
|
114
123
|
|
115
|
-
|
116
|
-
|
124
|
+
# make the directory if it doesn't exist
|
125
|
+
FileUtils.mkdir_p(relative_directory)
|
117
126
|
|
118
|
-
|
119
|
-
|
127
|
+
"#{relative_directory}/#{filename}"
|
128
|
+
end
|
120
129
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
130
|
+
# Path to the servers directory for the current domain:
|
131
|
+
#
|
132
|
+
# - "./servers/staging"
|
133
|
+
# - "./servers/alpha"
|
134
|
+
#
|
135
|
+
def server_path
|
136
|
+
"#{servers_path}/#{@domain}"
|
137
|
+
end
|
129
138
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
139
|
+
# Outputs a message if @verbose is on.
|
140
|
+
#
|
141
|
+
def verbose(message)
|
142
|
+
$stdout.puts(message) if @verbose
|
143
|
+
end
|
135
144
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
145
|
+
# Writes the input string to the destination file without adding any layout.
|
146
|
+
#
|
147
|
+
def write_template_without_layout(result)
|
148
|
+
path = destination_path
|
140
149
|
|
141
|
-
|
142
|
-
|
150
|
+
File.open(path, "w") do |f|
|
151
|
+
f.write(result)
|
152
|
+
end
|
153
|
+
verbose "Finished writing #{path}.\n"
|
143
154
|
end
|
144
|
-
verbose "Finished writing #{path}.\n"
|
145
|
-
end
|
146
155
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
156
|
+
# Writes the input string to the destination file, passing it through the
|
157
|
+
# application template.
|
158
|
+
#
|
159
|
+
# The application layout can be either Haml or ERB.
|
160
|
+
#
|
161
|
+
def write_template_with_layout(result)
|
162
|
+
@content = result
|
163
|
+
application_layout = "#{base_path}\/app\/views\/layouts\/application.html"
|
164
|
+
haml_layout = application_layout + ".haml"
|
165
|
+
erb_layout = application_layout + ".erb"
|
152
166
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
167
|
+
if File.exists?(haml_layout)
|
168
|
+
layout = File.open(haml_layout) do |f|
|
169
|
+
template = f.read
|
170
|
+
process_haml(template, haml_layout)
|
171
|
+
end
|
172
|
+
elsif File.exists?(erb_layout)
|
173
|
+
layout = File.open(erb_layout) do |f|
|
174
|
+
template = f.read
|
175
|
+
process_template(erb_layout)
|
176
|
+
end
|
162
177
|
end
|
178
|
+
|
179
|
+
write_template_without_layout(layout)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Write this processed template to its destination file.
|
183
|
+
#
|
184
|
+
# Overwrite in child class to define whether the class uses a template or not.
|
185
|
+
#
|
186
|
+
def write_template(result)
|
187
|
+
write_template_with_layout(result)
|
163
188
|
end
|
164
189
|
|
165
|
-
|
190
|
+
def servers_path
|
191
|
+
"#{base_path}/servers"
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
# Class Methods to handle global stuff like base path and server settings
|
199
|
+
|
200
|
+
def self.base_path= base_path
|
201
|
+
@@base_path = base_path
|
202
|
+
end
|
203
|
+
|
204
|
+
def self.base_path
|
205
|
+
@@base_path
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.servers= servers
|
209
|
+
@@servers = servers
|
210
|
+
end
|
211
|
+
|
212
|
+
def self.servers
|
213
|
+
@@servers
|
214
|
+
end
|
215
|
+
|
216
|
+
# Instance Methods to access global stuff like base path and server settings
|
217
|
+
|
218
|
+
def servers
|
219
|
+
@@servers
|
220
|
+
end
|
221
|
+
|
222
|
+
def base_path
|
223
|
+
@@base_path
|
166
224
|
end
|
167
225
|
|
168
|
-
|
169
|
-
|
170
|
-
# Overwrite in child class to define whether the class uses a template or not.
|
171
|
-
#
|
172
|
-
def write_template(result)
|
173
|
-
write_template_with_layout(result)
|
226
|
+
|
227
|
+
|
174
228
|
end
|
175
|
-
end
|
176
229
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
230
|
+
class View < Base
|
231
|
+
# TODO: Refactor this. Right now it includes all the YMDP::Base and other helper files
|
232
|
+
# into the same namespace where we're processing the templates. It does this so it can
|
233
|
+
# send its 'binding' into the ERB or Haml template and the template will be able to
|
234
|
+
# process methods like "render :partial => 'sidebar'" and so on.
|
235
|
+
#
|
236
|
+
# All the methods which are meant to be run from inside a view need to be refactored into
|
237
|
+
# their own class, which can be sent into the template as a binding.
|
238
|
+
#
|
239
|
+
include ActionView::Helpers::TagHelper
|
187
240
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
241
|
+
begin
|
242
|
+
include ApplicationHelper
|
243
|
+
rescue NameError
|
244
|
+
end
|
192
245
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
246
|
+
include YMDP::Base
|
247
|
+
include YMDP::AssetTagHelper
|
248
|
+
include YMDP::FormTagHelper
|
249
|
+
include YMDP::LinkTagHelper
|
197
250
|
|
198
|
-
|
251
|
+
attr_accessor :output_buffer
|
199
252
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
253
|
+
# Filename without its extension:
|
254
|
+
#
|
255
|
+
# - "authorize.html.haml" becomes "authorize"
|
256
|
+
#
|
257
|
+
def base_filename(filename)
|
258
|
+
filename.gsub(/(\.html|\.erb|\.haml)/, "")
|
259
|
+
end
|
207
260
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
261
|
+
# Filename without its extension:
|
262
|
+
#
|
263
|
+
# - "authorize.html.haml" becomes "authorize"
|
264
|
+
#
|
265
|
+
def convert_filename(filename)
|
266
|
+
base_filename(filename)
|
267
|
+
end
|
215
268
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
269
|
+
# Process this template with ERB.
|
270
|
+
#
|
271
|
+
def process_template(template)
|
272
|
+
ERB.new(template, 0, "%<>").result(binding)
|
273
|
+
end
|
221
274
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
275
|
+
# Process this template with Haml.
|
276
|
+
#
|
277
|
+
def process_haml(template, filename=nil)
|
278
|
+
options = {}
|
279
|
+
if filename
|
280
|
+
options[:filename] = filename
|
281
|
+
end
|
282
|
+
Haml::Engine.new(template, options).render(self)
|
228
283
|
end
|
229
|
-
Haml::Engine.new(template, options).render(self)
|
230
|
-
end
|
231
284
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
285
|
+
# Write this template with the application layout applied.
|
286
|
+
#
|
287
|
+
# Validate the resulting HTML file if that option is turned on.
|
288
|
+
#
|
289
|
+
def write_template(result)
|
290
|
+
write_template_with_layout(result)
|
291
|
+
YMDP::Validator::HTML.validate(destination_path) if CONFIG.validate_html?
|
292
|
+
end
|
239
293
|
end
|
240
|
-
end
|
241
294
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
295
|
+
# Process templates for JavaScript files.
|
296
|
+
#
|
297
|
+
# JavaScript files support ERB tags.
|
298
|
+
#
|
299
|
+
class JavaScript < View
|
300
|
+
# Write the processed template without any layout.
|
301
|
+
#
|
302
|
+
# Run the JavaScript compressor on the file if that option is turned on.
|
303
|
+
#
|
304
|
+
def write_template(result)
|
305
|
+
filename = @file.split("/").last
|
306
|
+
tmp_filename = "./tmp/#{filename}"
|
307
|
+
save_to_file(result, tmp_filename)
|
308
|
+
result = YMDP::Compressor::JavaScript.compress(tmp_filename) if CONFIG.compress_embedded_js?
|
309
|
+
write_template_without_layout(result)
|
310
|
+
end
|
257
311
|
end
|
258
|
-
end
|
259
312
|
|
260
|
-
|
261
|
-
#
|
262
|
-
# Convert them to a hash and write the hash to a JSON file.
|
263
|
-
#
|
264
|
-
# Each language can have as many YRB translation files (with an extension of ".pres")
|
265
|
-
# as necessary. The files are concatenated together and translated into a single JSON file
|
266
|
-
# for each language.
|
267
|
-
#
|
268
|
-
class YRB < Base
|
269
|
-
# Base directory for translations for this domain.
|
313
|
+
# Process Yahoo! Resource Bundle format translation files.
|
270
314
|
#
|
271
|
-
|
272
|
-
directory = "#{BASE_PATH}/servers/#{@domain}/assets/yrb"
|
273
|
-
FileUtils.mkdir_p(directory)
|
274
|
-
directory
|
275
|
-
end
|
276
|
-
|
277
|
-
# The destination of the compiled JSON file.
|
315
|
+
# Convert them to a hash and write the hash to a JSON file.
|
278
316
|
#
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
end
|
283
|
-
|
284
|
-
# JSON values of the compiled translations.
|
317
|
+
# Each language can have as many YRB translation files (with an extension of ".pres")
|
318
|
+
# as necessary. The files are concatenated together and translated into a single JSON file
|
319
|
+
# for each language.
|
285
320
|
#
|
286
|
-
|
287
|
-
|
288
|
-
|
321
|
+
class YRB < Base
|
322
|
+
# Base directory for translations for this domain.
|
323
|
+
#
|
324
|
+
def directory
|
325
|
+
directory = "#{base_path}/servers/#{@domain}/assets/yrb"
|
326
|
+
FileUtils.mkdir_p(directory)
|
327
|
+
directory
|
328
|
+
end
|
289
329
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
330
|
+
# The destination of the compiled JSON file.
|
331
|
+
#
|
332
|
+
def destination_path
|
333
|
+
filename = convert_filename(@file.split("/").last)
|
334
|
+
"#{directory}/#{filename}"
|
335
|
+
end
|
295
336
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
to_hash.each do |k,v|
|
301
|
-
k = k.downcase
|
302
|
-
h[k] = "#{v}"
|
337
|
+
# JSON values of the compiled translations.
|
338
|
+
#
|
339
|
+
def to_json
|
340
|
+
processed_template
|
303
341
|
end
|
304
|
-
h.to_yaml
|
305
|
-
end
|
306
342
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
end
|
343
|
+
# Turn it back into a hash.
|
344
|
+
#
|
345
|
+
def to_hash
|
346
|
+
JSON.parse(to_json)
|
347
|
+
end
|
313
348
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
349
|
+
# Convert the hash to Yaml if you should want to do that.
|
350
|
+
#
|
351
|
+
def to_yaml
|
352
|
+
h = {}
|
353
|
+
to_hash.each do |k,v|
|
354
|
+
k = k.downcase
|
355
|
+
h[k] = "#{v}"
|
356
|
+
end
|
357
|
+
h.to_yaml
|
358
|
+
end
|
359
|
+
|
360
|
+
# This function is the file which is written to the destination--in this
|
361
|
+
# case, the JSON file.
|
362
|
+
#
|
363
|
+
def processed_template
|
364
|
+
super.to_json
|
365
|
+
end
|
366
|
+
|
367
|
+
# Validate the JSON file.
|
368
|
+
#
|
369
|
+
def validate
|
370
|
+
YMDP::Validator::JSON.validate(destination_path)
|
371
|
+
end
|
319
372
|
|
320
|
-
|
373
|
+
private
|
321
374
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
375
|
+
# Strip off the ".pres" extension from original YRB files.
|
376
|
+
#
|
377
|
+
def base_filename(filename)
|
378
|
+
filename.gsub(/\.pres/, "")
|
379
|
+
end
|
327
380
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
381
|
+
# Take the base filename and add the ".json" extension.
|
382
|
+
#
|
383
|
+
def convert_filename(filename)
|
384
|
+
"#{base_filename(filename)}.json"
|
385
|
+
end
|
333
386
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
387
|
+
# Is this line a valid comment in YRB?
|
388
|
+
def comment?(line)
|
389
|
+
line =~ /^[\s]*#/
|
390
|
+
end
|
338
391
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
392
|
+
# Is this line valid YRB syntax?
|
393
|
+
#
|
394
|
+
def key_and_value_from_line(line)
|
395
|
+
if line =~ /^([^\=]+)=(.+)/
|
396
|
+
return $1, $2.strip
|
397
|
+
else
|
398
|
+
return nil, nil
|
399
|
+
end
|
346
400
|
end
|
347
|
-
end
|
348
401
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
puts
|
360
|
-
puts "Duplicate value in #{destination_path}"
|
361
|
-
puts " #{key}=#{@hash[key]}"
|
362
|
-
puts " #{key}=#{value}"
|
363
|
-
puts
|
364
|
-
if @hash[key] == value
|
365
|
-
puts " Values are the same but duplicate values still should not exist!"
|
402
|
+
# Parse YRB and add it to a hash. Raise an error if the key already exists in the hash.
|
403
|
+
#
|
404
|
+
def process_template(template)
|
405
|
+
@hash = {}
|
406
|
+
lines = template.split("\n")
|
407
|
+
lines.each do |line|
|
408
|
+
unless comment?(line)
|
409
|
+
key, value = key_and_value_from_line(line)
|
410
|
+
unless key.blank?
|
411
|
+
if @hash.has_key?(key)
|
366
412
|
puts
|
413
|
+
puts "Duplicate value in #{destination_path}"
|
414
|
+
puts " #{key}=#{@hash[key]}"
|
415
|
+
puts " #{key}=#{value}"
|
416
|
+
puts
|
417
|
+
if @hash[key] == value
|
418
|
+
puts " Values are the same but duplicate values still should not exist!"
|
419
|
+
puts
|
420
|
+
end
|
421
|
+
raise "Duplicate key error"
|
367
422
|
end
|
368
|
-
|
423
|
+
@hash[key] = value
|
369
424
|
end
|
370
|
-
@hash[key] = value
|
371
425
|
end
|
372
426
|
end
|
427
|
+
@hash
|
373
428
|
end
|
374
|
-
@hash
|
375
|
-
end
|
376
429
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
430
|
+
# Write JSON file to its destination.
|
431
|
+
#
|
432
|
+
def write_template(result)
|
433
|
+
puts destination_path if CONFIG.verbose?
|
434
|
+
write_template_without_layout(result)
|
435
|
+
end
|
382
436
|
end
|
383
437
|
end
|
384
438
|
end
|
385
|
-
end
|
439
|
+
end
|