ngi 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +164 -0
- data/Rakefile +2 -0
- data/bin/ngi +35 -0
- data/lib/config/angular_init.config.json +100 -0
- data/lib/config/backup.angular_init.config.json +72 -0
- data/lib/dep/json.rb +62 -0
- data/lib/dep/json/add/bigdecimal.rb +28 -0
- data/lib/dep/json/add/complex.rb +28 -0
- data/lib/dep/json/add/core.rb +11 -0
- data/lib/dep/json/add/date.rb +34 -0
- data/lib/dep/json/add/date_time.rb +50 -0
- data/lib/dep/json/add/exception.rb +31 -0
- data/lib/dep/json/add/ostruct.rb +31 -0
- data/lib/dep/json/add/range.rb +29 -0
- data/lib/dep/json/add/rational.rb +27 -0
- data/lib/dep/json/add/regexp.rb +30 -0
- data/lib/dep/json/add/struct.rb +30 -0
- data/lib/dep/json/add/symbol.rb +25 -0
- data/lib/dep/json/add/time.rb +38 -0
- data/lib/dep/json/common.rb +484 -0
- data/lib/dep/json/ext.rb +21 -0
- data/lib/dep/json/ext/.keep +0 -0
- data/lib/dep/json/generic_object.rb +70 -0
- data/lib/dep/json/pure.rb +21 -0
- data/lib/dep/json/pure/generator.rb +522 -0
- data/lib/dep/json/pure/parser.rb +359 -0
- data/lib/dep/json/version.rb +8 -0
- data/lib/ngi.rb +16 -0
- data/lib/ngi/configure.rb +165 -0
- data/lib/ngi/delegate.rb +24 -0
- data/lib/ngi/generator.rb +199 -0
- data/lib/ngi/utils/command_parser.rb +104 -0
- data/lib/ngi/utils/jser.rb +46 -0
- data/lib/ngi/utils/utils.rb +30 -0
- data/lib/ngi/version.rb +3 -0
- data/lib/templates/markup/html/default/index.html +11 -0
- data/lib/templates/script/coffee/default/basic.js +23 -0
- data/lib/templates/script/coffee/default/config.js +12 -0
- data/lib/templates/script/coffee/default/constant.js +7 -0
- data/lib/templates/script/coffee/default/module.js +7 -0
- data/lib/templates/script/es5/default/basic.js +29 -0
- data/lib/templates/script/es5/default/config.js +13 -0
- data/lib/templates/script/es5/default/constant.js +7 -0
- data/lib/templates/script/es5/default/module.js +7 -0
- data/ngi.gemspec +23 -0
- metadata +129 -0
data/lib/ngi/delegate.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# angular_init (short-name: ngi)
|
2
|
+
# Copyright 2015 Joshua Beam
|
3
|
+
# github.com/joshbeam/angular_init
|
4
|
+
# MIT License
|
5
|
+
|
6
|
+
# CURRENT_DIR is defined in angualr_init.rb
|
7
|
+
|
8
|
+
# require CURRENT_DIR+'/generator'
|
9
|
+
# require CURRENT_DIR+'/configure'
|
10
|
+
|
11
|
+
require_relative 'generator'
|
12
|
+
require_relative 'configure'
|
13
|
+
|
14
|
+
# Generator and Configure are "wrapped" in this class
|
15
|
+
# that "delegates" (hence the name "Delegate")
|
16
|
+
# the flow of control to either the Generator class
|
17
|
+
# or the Configure class, based on the argument passed
|
18
|
+
# in (which is handled by bin/ngi)
|
19
|
+
|
20
|
+
class Delegate
|
21
|
+
# Review: is this the best way to do it?
|
22
|
+
Generator = ::Generator
|
23
|
+
Configure = ::Configure
|
24
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# angular_init (short-name: ngi)
|
2
|
+
# Copyright 2015 Joshua Beam
|
3
|
+
# github.com/joshbeam/angular_init
|
4
|
+
# MIT License
|
5
|
+
|
6
|
+
require_relative "utils/utils"
|
7
|
+
|
8
|
+
# This class generates templates (hence the name "Generator")
|
9
|
+
class Generator
|
10
|
+
Utils = ::Utils
|
11
|
+
|
12
|
+
class AskLoop < Utils::AskLoop
|
13
|
+
def self.ask(args)
|
14
|
+
puts "\n"
|
15
|
+
print args[:prompt]
|
16
|
+
|
17
|
+
answer = $stdin.gets.strip.downcase
|
18
|
+
|
19
|
+
while true
|
20
|
+
if args[:check] == answer
|
21
|
+
break
|
22
|
+
else
|
23
|
+
puts "Exited!"
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
answer
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
WHITESPACE = /\s*/
|
33
|
+
EMPTY = ""
|
34
|
+
CURRENT_DIR = File.dirname(__FILE__)
|
35
|
+
|
36
|
+
################################
|
37
|
+
|
38
|
+
# SET UP ALL THE CONFIG OPTIONS
|
39
|
+
# Generator.new (the initialization function) is called in self.run
|
40
|
+
|
41
|
+
def initialize(args)
|
42
|
+
@type = args[:type]
|
43
|
+
@config = args[:config]['global']
|
44
|
+
|
45
|
+
all_components = @config['components']
|
46
|
+
component = all_components.find{ |t| t['name'] == @type }
|
47
|
+
|
48
|
+
# basically just rebuilding the object so we can use it here
|
49
|
+
@component = {
|
50
|
+
:of_type => component['type'],
|
51
|
+
:language => @config['language'][component['type']],
|
52
|
+
:using => component['using'],
|
53
|
+
:template => component['template']
|
54
|
+
}
|
55
|
+
|
56
|
+
template_dir = "#{CURRENT_DIR}/../templates/"
|
57
|
+
template_dir << "#{@component[:of_type]}/#{@component[:language]}/#{@component[:using]}/#{@component[:template]}"
|
58
|
+
|
59
|
+
@template_file = IO.read(template_dir)
|
60
|
+
|
61
|
+
if block_given?
|
62
|
+
yield(self)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
###############################
|
67
|
+
|
68
|
+
def new_file_name
|
69
|
+
print "[?] New file name: "
|
70
|
+
|
71
|
+
@new_file = $stdin.gets.gsub(WHITESPACE,EMPTY)
|
72
|
+
end
|
73
|
+
|
74
|
+
def module_name
|
75
|
+
print "[?] Module name: "
|
76
|
+
|
77
|
+
@module_name = $stdin.gets.gsub(WHITESPACE,EMPTY)
|
78
|
+
end
|
79
|
+
|
80
|
+
def name
|
81
|
+
print "[?] #{@type.capitalize} name: "
|
82
|
+
|
83
|
+
@name = $stdin.gets.gsub(WHITESPACE,EMPTY)
|
84
|
+
end
|
85
|
+
|
86
|
+
def inject
|
87
|
+
# REVIEW: use symbols instead of strings?
|
88
|
+
special = ['routes','controller'].include?(@type)
|
89
|
+
auto_injections = [
|
90
|
+
{
|
91
|
+
:for_type => 'routes',
|
92
|
+
:service => '$routeProvider'
|
93
|
+
},
|
94
|
+
{
|
95
|
+
:for_type => 'controller',
|
96
|
+
:service => '$scope'
|
97
|
+
}
|
98
|
+
]
|
99
|
+
|
100
|
+
injection = special ? auto_injections.select { |inj| inj[:for_type] == @type }[0][:service] : nil
|
101
|
+
|
102
|
+
auto_injection_statement = special ? " (already injected #{injection})" : ''
|
103
|
+
|
104
|
+
print "[?] Inject#{auto_injection_statement}: "
|
105
|
+
|
106
|
+
# accepts a comma-delimited list
|
107
|
+
# EXAMPLE: testService, testService2
|
108
|
+
# => [testService,testService2]
|
109
|
+
@dependencies = $stdin.gets.split(',').map { |dep| dep.strip }.reject(&:empty?)
|
110
|
+
|
111
|
+
# automatically inject $scope into a controller
|
112
|
+
# FIXME: don't use index accessors (numbers are confusing)
|
113
|
+
@dependencies << auto_injections[1][:service] if @type == 'controller' && !@dependencies.include?(auto_injections[1][:service])
|
114
|
+
|
115
|
+
# automatically insert $routeProvider into a routes config
|
116
|
+
@dependencies << auto_injections[0][:service] if @type == 'routes' && !@dependencies.include?(auto_injections[0][:service])
|
117
|
+
end
|
118
|
+
|
119
|
+
def replace
|
120
|
+
# inject may or may not have run... if it wasn't run, then @dependencies was never set
|
121
|
+
# for example, for html templates, we don't run the inject function
|
122
|
+
# @dependencies = @dependencies || []
|
123
|
+
@dependencies ||= []
|
124
|
+
has_dependencies = @dependencies.size > 0
|
125
|
+
|
126
|
+
# Use 'config' as the type, since 'routes' is really an alias for a specific type of 'config'.
|
127
|
+
# TODO: map aliases from config file
|
128
|
+
@type = 'config' if @type == 'routes'
|
129
|
+
|
130
|
+
# Regex replacements to generate the template
|
131
|
+
@template_file = @template_file
|
132
|
+
.gsub(/\{\{type\}\}/,@type)
|
133
|
+
.gsub(/\{\{name\}\}/,@name || "")
|
134
|
+
.gsub(/\{\{module\}\}/, "#@module_name")
|
135
|
+
.gsub(
|
136
|
+
/\{\{inject\s\|\sarray_string\}\}/,
|
137
|
+
has_dependencies ?
|
138
|
+
@dependencies.to_s.gsub(/"/,'\'')
|
139
|
+
: '[]'
|
140
|
+
)
|
141
|
+
.gsub(
|
142
|
+
/\{\{inject\s\|\scomma_delimited_variables\}\}/,
|
143
|
+
has_dependencies ?
|
144
|
+
@dependencies.each_with_index.inject("") { |str,(dep,i)| str+=dep.to_s+(i == @dependencies.size-1 ? "" : ", ") }
|
145
|
+
: ""
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
def tag
|
150
|
+
# If Liquid-style tags are used in a template that can be used
|
151
|
+
# for multiple components, remove those parts that don't
|
152
|
+
# belong to the type of component user wants to generate
|
153
|
+
@template_file = @template_file
|
154
|
+
.gsub(/\{\%\sif\s#{@type}\s\%\}(.*)\{\%\sendif\s#{@type}\s\%\}/m, '\1')
|
155
|
+
.gsub(/\s\{\%\sif\s.*\s\%\}.*\{\%\sendif\s.*\s\%\}/m, '')
|
156
|
+
end
|
157
|
+
|
158
|
+
def write
|
159
|
+
# create the new file
|
160
|
+
def overwrite?
|
161
|
+
AskLoop.ask(:check => "y", :prompt => "File exists already, overwrite it? (y/n) ")
|
162
|
+
end
|
163
|
+
|
164
|
+
if(File.exist?(@new_file))
|
165
|
+
overwrite?
|
166
|
+
end
|
167
|
+
|
168
|
+
File.open(@new_file,'w') do |file|
|
169
|
+
file.write(@template_file)
|
170
|
+
file.close
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Use this function to be able to say AngularInit::Delegate::Generator.run() inside the executable file
|
175
|
+
# This function simply goes through all of the methods in order to interactively
|
176
|
+
# prompt the user to generate a new template
|
177
|
+
def self.run(args)
|
178
|
+
Generator.new(args) do |g|
|
179
|
+
g.new_file_name
|
180
|
+
|
181
|
+
# we don't need to define the module if we're creating a module
|
182
|
+
g.module_name unless args[:type] == 'module'
|
183
|
+
|
184
|
+
# 'run', 'config', and 'routes' don't have custom names in AngularJS
|
185
|
+
# REVIEW: use symbols instead of strings?
|
186
|
+
g.name unless ['run','config','routes','index'].include? args[:type]
|
187
|
+
|
188
|
+
g.inject unless ['index'].include? args[:type]
|
189
|
+
|
190
|
+
g.replace
|
191
|
+
|
192
|
+
g.tag
|
193
|
+
|
194
|
+
g.write
|
195
|
+
end
|
196
|
+
|
197
|
+
puts 'All done!'
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# angular_init (short-name: ngi)
|
2
|
+
# Copyright 2015 Joshua Beam
|
3
|
+
# github.com/joshbeam/angular_init
|
4
|
+
# MIT License
|
5
|
+
|
6
|
+
|
7
|
+
# Similar to Ruby's OptionParser
|
8
|
+
# However, this is customized for angular_init
|
9
|
+
|
10
|
+
class CommandParser
|
11
|
+
attr_reader :args
|
12
|
+
attr_accessor :banner, :version, :separator, :name
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
# TODO: to "Usage #{file_name}", etc.
|
16
|
+
@name = "<CLI>"
|
17
|
+
@banner = "Usage: #{@name} <command>"
|
18
|
+
@version = "0.0.0"
|
19
|
+
@separator = "===================="
|
20
|
+
@listeners = []
|
21
|
+
|
22
|
+
# automatically register some listeners
|
23
|
+
register_help
|
24
|
+
register_version
|
25
|
+
|
26
|
+
# be able to pass in a block for setup
|
27
|
+
if block_given?
|
28
|
+
yield(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def name=(name)
|
33
|
+
# need to also replace the name in the banner
|
34
|
+
@banner = @banner.gsub(@name,name)
|
35
|
+
|
36
|
+
@name = name
|
37
|
+
end
|
38
|
+
|
39
|
+
# register the listeners
|
40
|
+
def on(options,description="",&block)
|
41
|
+
listener = {}
|
42
|
+
|
43
|
+
# be able to pass in a single argument, or an array of arguments
|
44
|
+
options = *options unless options.is_a? Array
|
45
|
+
|
46
|
+
listener[:options] = options.map do |opt|
|
47
|
+
opt.strip.split(" ")
|
48
|
+
end
|
49
|
+
|
50
|
+
listener[:block] = block
|
51
|
+
listener[:description] = description
|
52
|
+
|
53
|
+
@listeners << listener
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse(args)
|
57
|
+
# puts @listeners
|
58
|
+
matched_listener = {
|
59
|
+
:options => nil,
|
60
|
+
:block => nil
|
61
|
+
}
|
62
|
+
|
63
|
+
@listeners.each do |listener|
|
64
|
+
listener[:options].each do |opt_arr|
|
65
|
+
if opt_arr == args
|
66
|
+
matched_listener[:options] = opt_arr
|
67
|
+
matched_listener[:block] = listener[:block]
|
68
|
+
break
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
unless matched_listener[:options].nil?
|
74
|
+
# matched_listener[:options] should always be an array
|
75
|
+
# when we call, we can each member of that array to be
|
76
|
+
# passed separately
|
77
|
+
matched_listener[:block].call(*matched_listener[:options])
|
78
|
+
else
|
79
|
+
# if there was no match, show the help menu
|
80
|
+
parse(["-h"])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def register_help
|
85
|
+
# automaticaly register this listener
|
86
|
+
on(["-h","--help"],"Show the help menu") do
|
87
|
+
puts @separator
|
88
|
+
puts @banner
|
89
|
+
|
90
|
+
@listeners.each_with_index do |listener,i|
|
91
|
+
puts "\n"
|
92
|
+
puts "(#{i+1}) #{listener[:description]}: #{listener[:options].join(', ')}"
|
93
|
+
end
|
94
|
+
puts @separator
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def register_version
|
99
|
+
# automaticaly register this listener
|
100
|
+
on(["-v","--version"],"Show the version") do
|
101
|
+
puts "#{@name} #{@version}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# angular_init (short-name: ngi)
|
2
|
+
# Copyright 2015 Joshua Beam
|
3
|
+
# github.com/joshbeam/angular_init
|
4
|
+
# MIT License
|
5
|
+
|
6
|
+
module JSer
|
7
|
+
# Since ngi is an AngularJS tool and the users
|
8
|
+
# are familiar with JavaScript, this class
|
9
|
+
# prints a string version of a Ruby hash or array
|
10
|
+
# as it would appear in normal JavaScript syntax
|
11
|
+
# For example:
|
12
|
+
# { "hello" => "world" }
|
13
|
+
# becomes:
|
14
|
+
# { 'hello': 'world' }
|
15
|
+
# and ["some","array"]
|
16
|
+
# becomes:
|
17
|
+
# ['some','array']
|
18
|
+
def to_str
|
19
|
+
self.to_s.gsub(/\"/,"'").gsub(/\=\>/,": ")
|
20
|
+
end
|
21
|
+
|
22
|
+
# A JSer class
|
23
|
+
# Usage:
|
24
|
+
# JSHash.new({"hello" => "world"}).to_str
|
25
|
+
class JSHash < Hash
|
26
|
+
def initialize(hash)
|
27
|
+
super
|
28
|
+
hash.each do |key,val|
|
29
|
+
self[key] = val
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
include JSer
|
34
|
+
end
|
35
|
+
|
36
|
+
# Another JSer class
|
37
|
+
# Usage:
|
38
|
+
# JSArray.new(["some","array"]).to_str
|
39
|
+
class JSArray < Array
|
40
|
+
def initialize(array)
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
include JSer
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# angular_init (short-name: ngi)
|
2
|
+
# Copyright 2015 Joshua Beam
|
3
|
+
# github.com/joshbeam/angular_init
|
4
|
+
# MIT License
|
5
|
+
|
6
|
+
require_relative "command_parser"
|
7
|
+
require_relative "jser"
|
8
|
+
|
9
|
+
module Utils
|
10
|
+
CommandParser = ::CommandParser
|
11
|
+
JSArray = JSer::JSArray
|
12
|
+
JSHash = JSer::JSHash
|
13
|
+
|
14
|
+
class AskLoop; end
|
15
|
+
|
16
|
+
# This class is just a way to meaningfully
|
17
|
+
# collect an array of valid user inputs
|
18
|
+
# for use with OptionParser in bin/ngi
|
19
|
+
class UserInput
|
20
|
+
attr_reader :valid_inputs
|
21
|
+
|
22
|
+
def initialize(args)
|
23
|
+
@valid_inputs = args[:valid_inputs]
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid?(input)
|
27
|
+
@valid_inputs.include?(input)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/ngi/version.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
((app) ->
|
2
|
+
|
3
|
+
'use strict'
|
4
|
+
|
5
|
+
{{name}}.$inject = {{inject | array_string}}
|
6
|
+
|
7
|
+
app.{{type}} '{{name}}', {{name}}
|
8
|
+
|
9
|
+
{{name}} = ({{inject | comma_delimited_variables}}) ->
|
10
|
+
{% if directive %}
|
11
|
+
d =
|
12
|
+
restrict: 'A'
|
13
|
+
link: link
|
14
|
+
|
15
|
+
link = (scope, element, attrs) ->
|
16
|
+
|
17
|
+
d
|
18
|
+
{% endif directive %}
|
19
|
+
{% if filter %}
|
20
|
+
(input) ->
|
21
|
+
input
|
22
|
+
{% endif filter %}
|
23
|
+
) angular.module('{{module}}')
|