architecture-js 0.0.0 → 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.
- data/Gemfile +10 -2
- data/Gemfile.lock +14 -0
- data/README.md +1 -1
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/architecture-js.gemspec +62 -5
- data/bin/architect +214 -0
- data/lib/architecture-js.rb +32 -0
- data/lib/architecture-js/command.rb +80 -0
- data/lib/architecture-js/dependencies.rb +18 -0
- data/lib/architecture-js/generator.rb +44 -0
- data/lib/architecture-js/helpers.rb +30 -0
- data/lib/architecture-js/notification.rb +54 -0
- data/lib/architecture-js/project.rb +138 -0
- data/spec/architecture-js_spec.rb +51 -4
- data/spec/cli_spec.rb +38 -0
- data/spec/command_spec.rb +60 -0
- data/spec/fixtures/compiled_src.js +2 -0
- data/spec/fixtures/ejs_template.ejs +6 -0
- data/spec/fixtures/existing.architecture +6 -0
- data/spec/fixtures/lib1.js +1 -0
- data/spec/fixtures/lib2.js +1 -0
- data/spec/fixtures/myapp.architecture +6 -0
- data/spec/fixtures/src_file.js +2 -0
- data/spec/fixtures/test_template.erb +6 -0
- data/spec/fixtures/test_template.js +6 -0
- data/spec/fixtures/test_template_options.js +6 -0
- data/spec/generator_spec.rb +49 -0
- data/spec/helpers_spec.rb +16 -0
- data/spec/notification_spec.rb +27 -0
- data/spec/project_spec.rb +103 -0
- data/spec/spec_helper.rb +32 -7
- metadata +144 -15
@@ -0,0 +1,80 @@
|
|
1
|
+
module ArchitectureJS
|
2
|
+
module Command
|
3
|
+
def watch(path = nil)
|
4
|
+
require "fssm"
|
5
|
+
|
6
|
+
path ||= File.expand_path(Dir.getwd)
|
7
|
+
|
8
|
+
puts ArchitectureJS::Notification.log "ArchitectureJS are watching for changes. Press Ctrl-C to stop."
|
9
|
+
project = ArchitectureJS::Project.init_with_config
|
10
|
+
project.update
|
11
|
+
watch_hash = Hash.new
|
12
|
+
|
13
|
+
project.watch_directories.each do |dir|
|
14
|
+
watch_hash["#{path}/#{dir}"] = "**/*.js"
|
15
|
+
end
|
16
|
+
|
17
|
+
watch_hash[path] = "**/*.conf"
|
18
|
+
watch_hash["#{ArchitectureJS::BASE_DIR}/repository"] = "**/*.js"
|
19
|
+
|
20
|
+
FSSM.monitor do
|
21
|
+
watch_hash.each do |dir, g|
|
22
|
+
path "#{dir}" do
|
23
|
+
glob g
|
24
|
+
|
25
|
+
update do |base, relative|
|
26
|
+
puts ArchitectureJS::Notification.event "change detected in #{relative}"
|
27
|
+
project.config.read if relative.match(/conf$/)
|
28
|
+
project.update
|
29
|
+
end
|
30
|
+
|
31
|
+
create do |base, relative|
|
32
|
+
puts ArchitectureJS::Notification.event "#{relative} created"
|
33
|
+
project.update
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end # watch
|
39
|
+
|
40
|
+
def create(config = nil)
|
41
|
+
settings = {
|
42
|
+
name: nil,
|
43
|
+
root: File.expand_path(Dir.getwd)
|
44
|
+
}
|
45
|
+
|
46
|
+
settings.merge!(config) unless config.nil?
|
47
|
+
|
48
|
+
raise 'you must specify a project name: architect create ProjectName' if settings[:name].nil?
|
49
|
+
|
50
|
+
project = ArchitectureJS::Project.new({ name: settings[:name] }, settings[:root])# TODO add settings[:framework]
|
51
|
+
project.create
|
52
|
+
end
|
53
|
+
|
54
|
+
def compile(options = nil)
|
55
|
+
settings = {
|
56
|
+
force_compress: false,
|
57
|
+
path: File.expand_path(Dir.getwd)
|
58
|
+
}
|
59
|
+
|
60
|
+
settings.merge!(options) if options
|
61
|
+
|
62
|
+
project = ArchitectureJS::create_project_from_config(settings[:path])
|
63
|
+
project.config[:output] = 'compressed' if settings[:force_compress]
|
64
|
+
project.update
|
65
|
+
end
|
66
|
+
|
67
|
+
# TODO make generate generic to accept a type, look up in either local templates or master, and pass it options and flags parsed for use in erb files
|
68
|
+
def generate(config)
|
69
|
+
conf_path = "#{config[:project].root}/ninjs.conf"
|
70
|
+
raise "ninjs.conf was not located in #{conf_path}" unless File.exists? conf_path
|
71
|
+
generator = ArchitectureJS::Generator.new(config)
|
72
|
+
generator.generate
|
73
|
+
end
|
74
|
+
|
75
|
+
module_function :create,
|
76
|
+
:watch,
|
77
|
+
:compile,
|
78
|
+
:generate
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
begin
|
2
|
+
require 'yaml'
|
3
|
+
require 'jsmin'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'sprockets'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'time'
|
8
|
+
require 'erb'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rubygems'
|
11
|
+
require 'yaml'
|
12
|
+
require 'jsmin'
|
13
|
+
require 'tempfile'
|
14
|
+
require 'sprockets'
|
15
|
+
require 'fileutils'
|
16
|
+
require 'time'
|
17
|
+
require 'erb'
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ArchitectureJS
|
2
|
+
class Generator
|
3
|
+
|
4
|
+
attr_reader :template_paths,
|
5
|
+
:templates,
|
6
|
+
:project
|
7
|
+
|
8
|
+
def initialize(project)
|
9
|
+
@project = project
|
10
|
+
@template_paths = @project.template_directories
|
11
|
+
@templates = Hash.new
|
12
|
+
find_templates @template_paths
|
13
|
+
#@template_dir = template_dir
|
14
|
+
#@template_files = Dir.entries(template_dir).reject {|file| file.match /^\./ }
|
15
|
+
#@templates = Hash.new
|
16
|
+
#@template_files.each do |file|
|
17
|
+
# name = file.gsub /\.\w+$/, ''
|
18
|
+
# @templates[name] = ERB.new(File.read(File.expand_path(file, @template_dir)))
|
19
|
+
#end
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_templates(paths)
|
23
|
+
paths.each do |path|
|
24
|
+
Dir["#{path}/*_template*"].each do |file|
|
25
|
+
template_name = get_template_name file
|
26
|
+
@templates[template_name] = get_template(file)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_template_name(file)
|
32
|
+
file.split(/\/|\\/).last.gsub(/_template\.\w*/, '')
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_template(file)
|
36
|
+
ERB.new File.read(file)
|
37
|
+
end
|
38
|
+
|
39
|
+
def render_template(template, options = nil)
|
40
|
+
project = @project
|
41
|
+
@templates[template].result(binding)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ArchitectureJS
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
def get_file_name(module_path)
|
5
|
+
module_path = module_path.split(/[\\\/]/).last
|
6
|
+
split = module_path.split(/[\.\-\s]/)
|
7
|
+
module_filename = String.new
|
8
|
+
split.each do |piece|
|
9
|
+
module_filename << piece unless piece.match(/^module$|^js$/i)
|
10
|
+
end
|
11
|
+
module_filename
|
12
|
+
end
|
13
|
+
|
14
|
+
def array_to_yml(array)
|
15
|
+
yml = array.empty? ? '[]' : %Q{['#{array.join("', '")}']}
|
16
|
+
end
|
17
|
+
|
18
|
+
def symbolize_keys(hash)
|
19
|
+
symbolized_hash = Hash.new
|
20
|
+
hash.each do |key, value|
|
21
|
+
symbolized_hash[key.to_sym] = value
|
22
|
+
end
|
23
|
+
symbolized_hash
|
24
|
+
end
|
25
|
+
|
26
|
+
module_function :get_file_name,
|
27
|
+
:array_to_yml,
|
28
|
+
:symbolize_keys
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module ArchitectureJS
|
2
|
+
class Notification
|
3
|
+
|
4
|
+
win_platform = !![
|
5
|
+
/bccwin/i,
|
6
|
+
/djgpp/i,
|
7
|
+
/mingw/i,
|
8
|
+
/mswin/i,
|
9
|
+
/wince/i,
|
10
|
+
].find{ |r| RUBY_PLATFORM =~ r }
|
11
|
+
|
12
|
+
@@indicators = {
|
13
|
+
none: "",
|
14
|
+
log: "\e[32m>>>\e[0m ",
|
15
|
+
event: "\e[33m<<<\e[0m ",
|
16
|
+
added: "\e[32m+++\e[0m ",
|
17
|
+
error: "\e[0;31m!!!\e[0m "
|
18
|
+
}
|
19
|
+
|
20
|
+
@@indicators.merge!({
|
21
|
+
none: "",
|
22
|
+
log: ">>>",
|
23
|
+
event: "<<<",
|
24
|
+
added: "+++",
|
25
|
+
error: "!!!"
|
26
|
+
}) if win_platform
|
27
|
+
|
28
|
+
def self.notify(type, message)
|
29
|
+
raise "There is no #{type} indicator" unless @@indicators[type]
|
30
|
+
"#{@@indicators[type]}#{message}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.notice(message)
|
34
|
+
self.notify :none, message
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.log(message)
|
38
|
+
self.notify :log, message
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.event(message)
|
42
|
+
self.notify :event, message
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.added(message)
|
46
|
+
self.notify :added, message
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.error(message)
|
50
|
+
self.notify :error, message
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module ArchitectureJS
|
2
|
+
class Project # TODO make generator belong to project to have default templates hooked up to generator
|
3
|
+
attr_reader :root,
|
4
|
+
:src_files,
|
5
|
+
:framework,
|
6
|
+
:config_name,
|
7
|
+
:watch_directories,
|
8
|
+
:directories,
|
9
|
+
:template_directories,
|
10
|
+
:generator
|
11
|
+
|
12
|
+
attr_accessor :config
|
13
|
+
|
14
|
+
# this line adds the default framework to ArchitectureJS
|
15
|
+
ArchitectureJS::register_framework 'none', self
|
16
|
+
|
17
|
+
def initialize(config, root = nil)
|
18
|
+
raise "#{self.class}.new({ name: 'myapp' }, options): config[:name] is undefined" unless config[:name]
|
19
|
+
@config_file = "#{config[:name].downcase}.architecture"
|
20
|
+
root ||= Dir.getwd
|
21
|
+
@root = File.expand_path(root)
|
22
|
+
@template_directories = ["#{ArchitectureJS::BASE_DIR}/templates", "#{@root}/templates"]
|
23
|
+
@directories = ['lib', 'src']
|
24
|
+
@watch_directories = ['src']
|
25
|
+
@src_files = Array.new
|
26
|
+
@config = {
|
27
|
+
framework: 'none',
|
28
|
+
src_dir: 'src',
|
29
|
+
build_dir: 'lib',
|
30
|
+
asset_root: '../',
|
31
|
+
output: 'compressed'
|
32
|
+
}
|
33
|
+
@config.merge! config unless config.nil?
|
34
|
+
@generator = ArchitectureJS::Generator.new self
|
35
|
+
end
|
36
|
+
|
37
|
+
def read_config
|
38
|
+
config = YAML.load_file("#{@root}/#{@config_file}")
|
39
|
+
assign_config_variables config
|
40
|
+
end
|
41
|
+
|
42
|
+
def assign_config_variables(config)
|
43
|
+
config.each do |key, value|
|
44
|
+
@config[key.to_sym] = value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def create
|
49
|
+
puts ArchitectureJS::Notification.notice "Creating the #{@config[:name]} project in #{@root}"
|
50
|
+
create_project_scaffold
|
51
|
+
write_config
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_project_scaffold
|
55
|
+
Dir.mkdir "#{@root}" unless File.exists? "#{@root}"
|
56
|
+
|
57
|
+
@directories.each do |dir|
|
58
|
+
puts ArchitectureJS::Notification.added "#{dir} created" unless File.exists? "#{@root}/#{dir}"
|
59
|
+
Dir.mkdir "#{@root}/#{dir}" unless File.exists? "#{@root}/#{dir}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def write_config
|
64
|
+
File.open("#{@root}/#{@config_file}", "w+") do |conf_file|
|
65
|
+
@config.each do |key, value|
|
66
|
+
conf_file << "#{key}: #{ArchitectureJS::Helpers.array_to_yml value}\n" if value.is_a? Array
|
67
|
+
conf_file << "#{key}: #{value}\n" if value.is_a? String
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
puts ArchitectureJS::Notification.added "#{@config_file} created"
|
72
|
+
end
|
73
|
+
|
74
|
+
def update
|
75
|
+
get_src_files
|
76
|
+
compile_src_files
|
77
|
+
compress_application if @output == 'compressed'
|
78
|
+
puts ArchitectureJS::Notification.log "application updated" unless @errors
|
79
|
+
@errors = false
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_src_files
|
83
|
+
[*@config[:src_dir]].each do |directory|
|
84
|
+
add_src_files_to_project File.expand_path(directory, @root)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_src_files_to_project(directory)
|
89
|
+
puts '-------------------'
|
90
|
+
puts directory
|
91
|
+
puts '-------------------'
|
92
|
+
Dir["#{directory}/*.js"].each do |file|
|
93
|
+
src_filename = file.gsub(directory, '')
|
94
|
+
@src_files << "#{directory}#{src_filename}" unless src_filename.match(/^\/_/)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def compile_src_files
|
99
|
+
@src_files.each do |file_path|
|
100
|
+
file_name = ArchitectureJS::Helpers.get_file_name file_path
|
101
|
+
compile_src_file file_path, file_name
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def compile_src_file(file_path, file_name)
|
106
|
+
sprockets = Sprockets::Secretary.new(
|
107
|
+
:root => "#{ArchitectureJS::BASE_DIR}",
|
108
|
+
:asset_root => File.expand_path(@config[:asset_root], @root),
|
109
|
+
:load_path => ["repository"],
|
110
|
+
source_files: ["#{file_path}"]
|
111
|
+
)
|
112
|
+
|
113
|
+
compiled_file = sprockets.concatenation
|
114
|
+
message = File.exists?("#{@root}/#{@config[:build_dir]}/#{file_name}.js") ? "\e[32m>>>\e[0m #{@config[:build_dir]}/#{file_name}.js updated" : "\e[32m>>>\e[0m #{@config[:build_dir]}/#{file_name}.js created"
|
115
|
+
compiled_file.save_to "#{@root}/#{@config[:build_dir]}/#{file_name}.js"
|
116
|
+
sprockets.install_assets
|
117
|
+
|
118
|
+
rescue Exception => error
|
119
|
+
@errors = true
|
120
|
+
puts ArchitectureJS::Notification.error "Sprockets error: #{error.message}"
|
121
|
+
end
|
122
|
+
|
123
|
+
def compress_application
|
124
|
+
app_root = File.expand_path "#{@config[:build_dir]}"
|
125
|
+
src_files = Dir.entries(app_root)
|
126
|
+
src_files.reject! { |file| file =~ /^\./ }
|
127
|
+
|
128
|
+
src_files.each do |module_file|
|
129
|
+
full_path = "#{app_root}/#{module_file}"
|
130
|
+
uncompressed = File.open(full_path, "r").read
|
131
|
+
File.open(full_path, "w+") do |module_file|
|
132
|
+
module_file << JSMin.minify(uncompressed)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end # class Project
|
138
|
+
end # module ArchitectureJS
|
@@ -1,7 +1,54 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
|
-
describe
|
4
|
-
it
|
5
|
-
|
3
|
+
describe ArchitectureJS do
|
4
|
+
it 'should have a BASE_DIR constant' do
|
5
|
+
ArchitectureJS::BASE_DIR.should_not be_nil
|
6
6
|
end
|
7
|
+
|
8
|
+
it 'should have a LIB_DIR constant' do
|
9
|
+
ArchitectureJS::LIB_DIR.should_not be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should have a ROOT_DIR' do
|
13
|
+
ArchitectureJS::ROOT_DIR.should_not be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should have the correct VERSION' do
|
17
|
+
version = File.open("#{ArchitectureJS::BASE_DIR}/VERSION").read
|
18
|
+
ArchitectureJS::VERSION.should === version
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should have a FRAMEWORKS constant' do
|
22
|
+
ArchitectureJS::FRAMEWORKS.should_not be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
context "Instantiation with a config file" do
|
26
|
+
|
27
|
+
before :each do
|
28
|
+
FileUtils.mkdir("#{TMP_DIR}")
|
29
|
+
FileUtils.cp "#{FIXTURES}/existing.architecture", "#{TMP_DIR}/myapp.architecture"
|
30
|
+
suppress_output { @project = ArchitectureJS::create_project_from_config(TMP_DIR) }
|
31
|
+
end
|
32
|
+
|
33
|
+
after :each do
|
34
|
+
FileUtils.rm_rf "#{TMP_DIR}" if File.exists? "#{TMP_DIR}"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should raise an error if there is no .architecture file" do
|
38
|
+
FileUtils.rm_rf "#{TMP_DIR}/myapp.architecture"
|
39
|
+
lambda { ArchitectureJS::create_project_from_config TMP_DIR }.should raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should set defaults from config file' do
|
43
|
+
@project.config.should == {
|
44
|
+
framework: 'none',
|
45
|
+
src_dir: 'source',
|
46
|
+
build_dir: 'dest',
|
47
|
+
asset_root: '../',
|
48
|
+
output: 'compressed',
|
49
|
+
name: 'test',
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
end # Instantiation with an existing config file
|
7
54
|
end
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'CLI' do
|
4
|
+
before :each do
|
5
|
+
@bin = "#{ArchitectureJS::BASE_DIR}/bin/architect"
|
6
|
+
FileUtils.mkdir "#{TMP_DIR}" unless File.exists? "#{TMP_DIR}"
|
7
|
+
suppress_output { %x(cd #{TMP_DIR}; #{@bin} create myapp) }
|
8
|
+
FileUtils.cp "#{FIXTURES}/lib1.js", "#{TMP_DIR}/lib/lib1.js"
|
9
|
+
FileUtils.cp "#{FIXTURES}/lib2.js", "#{TMP_DIR}/lib/lib2.js"
|
10
|
+
FileUtils.cp "#{FIXTURES}/src_file.js", "#{TMP_DIR}/src/myapp.js"
|
11
|
+
end
|
12
|
+
|
13
|
+
after :each do
|
14
|
+
FileUtils.rm_rf "#{TMP_DIR}" if File.exists? "#{TMP_DIR}"
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should create a new application' do
|
18
|
+
"#{TMP_DIR}/myapp.architecture".should be_same_file_as "#{FIXTURES}/myapp.architecture"
|
19
|
+
File.directory? "#{TMP_DIR}/lib"
|
20
|
+
File.directory? "#{TMP_DIR}/src"
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should create a new application in a subdirectory' do
|
24
|
+
suppress_output { %x(cd #{TMP_DIR}; #{@bin} create myapp sub) }
|
25
|
+
"#{TMP_DIR}/sub/myapp.architecture".should be_same_file_as "#{FIXTURES}/myapp.architecture"
|
26
|
+
File.directory? "#{TMP_DIR}/sub/lib"
|
27
|
+
File.directory? "#{TMP_DIR}/sub/src"
|
28
|
+
File.exists? "#{TMP_DIR}/sub/myapp.js"
|
29
|
+
FileUtils.rm_rf "#{TMP_DIR}/sub"
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should compile the application' do
|
33
|
+
suppress_output { %x(cd #{TMP_DIR}; #{@bin} compile) }
|
34
|
+
File.exists?("#{TMP_DIR}/lib/myapp.js").should be_true
|
35
|
+
"#{TMP_DIR}/lib/myapp.js".should be_same_file_as "#{FIXTURES}/compiled_src.js"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|