ngi 0.2.1
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.
- 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}}')
|