konstruct 0.9.1 → 1.0.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.
- checksums.yaml +4 -4
- data/README.md +33 -27
- data/konstruct.gemspec +6 -6
- data/lib/cli/develop.rb +54 -47
- data/lib/cli/project.rb +333 -81
- data/lib/konstruct.rb +157 -84
- data/lib/konstruct/template.rb +71 -0
- data/lib/konstruct/version.rb +1 -1
- data/lib/utilities/gulp.rb +32 -42
- data/lib/utilities/system.rb +218 -0
- data/lib/utilities/utils.rb +165 -184
- metadata +18 -5
- data/lib/cli/documentation.rb +0 -44
- data/lib/cli/init.rb +0 -195
- data/lib/konstruct/config.rb +0 -22
@@ -0,0 +1,218 @@
|
|
1
|
+
# KONSTRUCT CLI [ KONSTRUCT MODULE ] ===========================================
|
2
|
+
|
3
|
+
# ====== INDEX ================================================================
|
4
|
+
# ==
|
5
|
+
# == 1. UPDATE APP
|
6
|
+
# == 2. UPDATE SYSTEM
|
7
|
+
# == 3. INSTALL SYSTEM
|
8
|
+
# ==
|
9
|
+
# ====== INDEX ================================================================
|
10
|
+
|
11
|
+
module Util
|
12
|
+
|
13
|
+
class System
|
14
|
+
|
15
|
+
# 1. UPDATE APP ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
16
|
+
|
17
|
+
def preflight()
|
18
|
+
|
19
|
+
# 1.1. INIT FUNCTIONS ----------------------------------------------------
|
20
|
+
|
21
|
+
msg = Util::Message.new()
|
22
|
+
fs = Util::FS.new()
|
23
|
+
sys = Util::System.new()
|
24
|
+
config_dir = File.expand_path('~/.konstruct')
|
25
|
+
|
26
|
+
# 1.1. END ---------------------------------------------------------------
|
27
|
+
|
28
|
+
# 1.2. CHECK FOR UPDATE --------------------------------------------------
|
29
|
+
|
30
|
+
version_url = "https://rubygems.org/gems/konstruct/versions.atom";
|
31
|
+
xml_data = Net::HTTP.get_response(URI.parse(version_url)).body
|
32
|
+
data = XmlSimple.xml_in(xml_data)
|
33
|
+
string = data["entry"][0]["title"].to_s
|
34
|
+
remote_version = Gem::Version.new(string[13, 5])
|
35
|
+
#remote_version = Gem::Version.new("1.1.0")
|
36
|
+
current_version = Gem::Version.new(Konstruct::VERSION)
|
37
|
+
|
38
|
+
if remote_version > current_version
|
39
|
+
|
40
|
+
abort "A new version (#{remote_version}) of Konstruct CLI is available. Please run `$ gem install konstruct`."
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# 1.2. END ---------------------------------------------------------------
|
45
|
+
|
46
|
+
# 1.3. END ---------------------------------------------------------------
|
47
|
+
|
48
|
+
unless Dir[config_dir].length > 0
|
49
|
+
|
50
|
+
msg.warning("Konstruct is not installed yet. Please wait while we do this now.");
|
51
|
+
init()
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
# 1.3. END ---------------------------------------------------------------
|
56
|
+
|
57
|
+
# 1.3. CHECK SYSTEM ------------------------------------------------------
|
58
|
+
|
59
|
+
if File.file?("#{config_dir}/config.yml")
|
60
|
+
|
61
|
+
config = YAML.load_file("#{config_dir}/config.yml")
|
62
|
+
|
63
|
+
system_version = Gem::Version.new(config["version"])
|
64
|
+
app_version = Gem::Version.new(Konstruct::VERSION)
|
65
|
+
|
66
|
+
if app_version > system_version
|
67
|
+
|
68
|
+
msg.warning("Your version of Konstruct is out of date, and needs to be updated. Please wait while we do this now.");
|
69
|
+
|
70
|
+
init();
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# 1.3. END ---------------------------------------------------------------
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
# 1. END +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
81
|
+
|
82
|
+
# 2. INIT SYSTEM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
83
|
+
|
84
|
+
def init()
|
85
|
+
|
86
|
+
# 2.1. INIT FUNCTIONS ----------------------------------------------------
|
87
|
+
|
88
|
+
msg = Util::Message.new()
|
89
|
+
fs = Util::FS.new()
|
90
|
+
git = Util::Git.new()
|
91
|
+
|
92
|
+
config_dir = File.expand_path('~/.konstruct')
|
93
|
+
|
94
|
+
# 2.1. END ---------------------------------------------------------------
|
95
|
+
|
96
|
+
# 2.2. CREATE .KONSTRUCT DIRECTORY ---------------------------------------
|
97
|
+
|
98
|
+
if Dir[config_dir].length > 0
|
99
|
+
|
100
|
+
`rm -rf #{config_dir}`
|
101
|
+
msg.warning("Uninstalled existing .konstruct")
|
102
|
+
fs.make_dir(config_dir)
|
103
|
+
msg.success("Created #{config_dir}")
|
104
|
+
|
105
|
+
else
|
106
|
+
|
107
|
+
fs.make_dir(config_dir)
|
108
|
+
msg.success("Created #{config_dir}")
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# 2.2. END ---------------------------------------------------------------
|
113
|
+
|
114
|
+
# 2.2. CREATE CONFIG.YML FILE --------------------------------------------
|
115
|
+
|
116
|
+
date = Time.new
|
117
|
+
date_installed = "#{ date.year }-#{ date.month }-#{ date.day }"
|
118
|
+
|
119
|
+
file_data = Konstruct::TEMPLATE
|
120
|
+
|
121
|
+
File.open("#{config_dir}/config.yml","w") do |f|
|
122
|
+
f.write(file_data.to_yaml)
|
123
|
+
end
|
124
|
+
|
125
|
+
msg.success("Created #{config_dir}/data.yml")
|
126
|
+
|
127
|
+
# 2.2. END ---------------------------------------------------------------
|
128
|
+
|
129
|
+
# 2.3. INSTALL GULP ------------------------------------------------------
|
130
|
+
|
131
|
+
gulpDir = "#{config_dir}/gulp"
|
132
|
+
|
133
|
+
fs.make_dir(gulpDir)
|
134
|
+
git.install(gulpDir, "https://github.com/konstruct/konstruct.gulp.git", "lib", "")
|
135
|
+
|
136
|
+
msg.success("Cloned Gulp to #{gulpDir}")
|
137
|
+
|
138
|
+
# 2.3. END ---------------------------------------------------------------
|
139
|
+
|
140
|
+
# 2.4. INSTALL NPM -------------------------------------------------------
|
141
|
+
|
142
|
+
doSudo = choose("Do you need to install node modules as root?", :Yes, :No)
|
143
|
+
|
144
|
+
if doSudo == :Yes
|
145
|
+
|
146
|
+
msg.warning("You should fix your installation of nodeJS to not require root privileges!")
|
147
|
+
msg.paragraph("Installing NPM Assets. This might take a while.")
|
148
|
+
|
149
|
+
FileUtils.cd(gulpDir) do
|
150
|
+
|
151
|
+
`sudo npm install`
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
else
|
156
|
+
|
157
|
+
msg.paragraph("Installing NPM Assets. This might take a while.")
|
158
|
+
|
159
|
+
FileUtils.cd(gulpDir) do
|
160
|
+
|
161
|
+
`npm install`
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
msg.success("Installed Gulp to #{gulpDir}")
|
168
|
+
|
169
|
+
# 2.4. END ---------------------------------------------------------------
|
170
|
+
|
171
|
+
# 2.5. FINISH INSTALL ----------------------------------------------------
|
172
|
+
|
173
|
+
puts ""
|
174
|
+
puts ""
|
175
|
+
puts Paint[' $III7IIIIIIIIIIIIIIIIIIIIIIIIII: ', "#de544b"]
|
176
|
+
puts Paint[' ZZZZZZ$7IIIIIIIIIIIIIIIIIIIIIIII ', "#de544b"]
|
177
|
+
puts Paint[' ZZZZZZZZZZZZ$7IIIIIIIIIIIIIIIIII ', "#de544b"]
|
178
|
+
puts Paint[' ZZZZZZZZZZZZZZZZZZZ$IIIIIIIIIIII~', "#de544b"]
|
179
|
+
puts Paint[' ZZZZZZZZZZZZZZZZZZZZZZZ:,:+IIIIII', "#de544b"]
|
180
|
+
puts Paint[' ZZZZZZZZZZZZZZZZZZZZZZ. :?', "#de544b"]
|
181
|
+
puts Paint[' I$ZZZZZZZZZZZZZZZZZZ7 ', "#de544b"]
|
182
|
+
puts Paint[' III$ZZZZZZZZZZZZZZZ~ ', "#de544b"]
|
183
|
+
puts Paint[' IIIII7ZZZZZZZZZZZZ ', "#de544b"]
|
184
|
+
puts Paint[' IIIIIII7ZZZZZZZZ$ ', "#de544b"]
|
185
|
+
puts Paint[' IIIIIIIIIIZZZZZ: ', "#de544b"]
|
186
|
+
puts Paint[' IIIIIIIIIIIIZI ', "#de544b"]
|
187
|
+
puts Paint[' IIIIIIIIIIIIII ', "#de544b"]
|
188
|
+
puts Paint[' IIIIIIIIIIIIIIII= ', "#de544b"]
|
189
|
+
puts Paint[' IIIIIIIIIIIIIIIII7= ', "#de544b"]
|
190
|
+
puts Paint[' IIIIIIIIIIIIIIIIIIII~ ', "#de544b"]
|
191
|
+
puts Paint[' IIIIIIIIIIIIIIIIIIIIII= ', "#de544b"]
|
192
|
+
puts Paint[' IIIIIIIIIIIIIIIIIIIIIII7~ ', "#de544b"]
|
193
|
+
puts Paint[' IIIIIIIIIIIIIIIIIIIIIIIIIII.. ', "#de544b"]
|
194
|
+
puts Paint[' IIIIIIIIIIIIIIIIIIIIIIIIIIII7 ', "#de544b"]
|
195
|
+
puts Paint[' IIIIIIIIIIIIIIIIIIIIIIIIIIIIIII,.', "#de544b"]
|
196
|
+
puts Paint[' IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII7', "#de544b"]
|
197
|
+
puts ""
|
198
|
+
puts ""
|
199
|
+
puts Paint[" GO BUILD SOMETHING AWESOME!", "#999999"]
|
200
|
+
puts ""
|
201
|
+
puts Paint[" Successfully installed Konstruct #{Konstruct::VERSION}.", "#999999"]
|
202
|
+
puts ""
|
203
|
+
puts Paint[" Type '$ konstruct documentation' to get help.", "#999999"]
|
204
|
+
puts ""
|
205
|
+
|
206
|
+
exit(0)
|
207
|
+
|
208
|
+
# 2.5. END ---------------------------------------------------------------
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
# 2. END +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
# END OF FILE ==================================================================
|
data/lib/utilities/utils.rb
CHANGED
@@ -7,210 +7,191 @@
|
|
7
7
|
# ==
|
8
8
|
# ====== INDEX =======================================================================================================
|
9
9
|
|
10
|
-
#
|
10
|
+
# B. UTILITIES ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
11
11
|
|
12
|
+
module Util
|
12
13
|
|
14
|
+
# B.1. MESSAGES -----------------------------------------------------------------------------------------------------
|
13
15
|
|
14
|
-
|
16
|
+
class Message
|
15
17
|
|
16
|
-
# B.
|
18
|
+
# B.1.1. WARNING MESSAGE
|
19
|
+
|
20
|
+
def warning(msg)
|
21
|
+
|
22
|
+
puts ""
|
23
|
+
puts Paint["[WARNING:]", :yellow]
|
24
|
+
puts Paint[msg, :yellow]
|
25
|
+
puts ""
|
17
26
|
|
18
|
-
module Util
|
19
|
-
|
20
|
-
# B.1. MESSAGES ---------------------------------------------------------------------------------------------------
|
21
|
-
|
22
|
-
class Message
|
23
|
-
|
24
|
-
# B.1.1. WARNING MESSAGE
|
25
|
-
|
26
|
-
def warning(msg)
|
27
|
-
|
28
|
-
puts ""
|
29
|
-
puts Paint["WARNING:", :yellow]
|
30
|
-
puts Paint[msg, :yellow]
|
31
|
-
puts ""
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
# B.1.1. END
|
36
|
-
|
37
|
-
# B.1.2. SUCCESS MESSAGE
|
38
|
-
|
39
|
-
def success(msg)
|
40
|
-
|
41
|
-
puts ""
|
42
|
-
puts Paint["SUCCESS:", :green]
|
43
|
-
puts Paint[msg, :green]
|
44
|
-
puts ""
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
# B.1.2. END
|
49
|
-
|
50
|
-
# B.1.3. ERROR MESSAGE
|
51
|
-
|
52
|
-
def error(msg)
|
53
|
-
|
54
|
-
puts ""
|
55
|
-
puts Paint["ERROR:", :red]
|
56
|
-
puts Paint[msg, :red]
|
57
|
-
puts ""
|
58
|
-
|
59
|
-
exit 1
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
# B.1.3. END
|
64
|
-
|
65
|
-
# B.1.4. HEADING
|
66
|
-
|
67
|
-
def heading(msg)
|
68
|
-
|
69
|
-
puts ""
|
70
|
-
|
71
|
-
puts Paint["----------------------------------------------------------------------------", :cyan]
|
72
|
-
|
73
|
-
puts Paint["--", :cyan]
|
74
|
-
puts Paint["-- #{ msg }", :cyan]
|
75
|
-
puts Paint["--", :cyan]
|
76
|
-
|
77
|
-
puts Paint["----------------------------------------------------------------------------", :cyan]
|
78
|
-
|
79
|
-
puts ""
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
# B.1.4. END
|
84
|
-
|
85
|
-
# B.1.5. PARAGRAPH
|
86
|
-
|
87
|
-
def paragraph(msg)
|
88
|
-
|
89
|
-
puts ""
|
90
|
-
|
91
|
-
puts Paint[msg, "999999"]
|
92
|
-
|
93
|
-
puts ""
|
94
|
-
|
95
|
-
end
|
96
|
-
|
97
|
-
# B.1.5. END
|
98
|
-
|
99
27
|
end
|
100
|
-
|
101
|
-
# B.1. END --------------------------------------------------------------------------------------------------------
|
102
|
-
|
103
|
-
# B.2. FILE SYSTEM ------------------------------------------------------------------------------------------------
|
104
|
-
|
105
|
-
class FS
|
106
|
-
|
107
|
-
# B.2.1. CHECK FOR EMPTY DIRECTORY
|
108
|
-
|
109
|
-
def isEmpty(path)
|
110
|
-
|
111
|
-
if Dir.entries(path).length > 2
|
112
|
-
|
113
|
-
result = true
|
114
|
-
|
115
|
-
else
|
116
|
-
|
117
|
-
result = false
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
end
|
122
|
-
|
123
|
-
# B.2.1. END
|
124
|
-
|
125
|
-
# B.2.2. CLEAR THE ENTIRE DIRECTORY
|
126
|
-
|
127
|
-
def clear_directory(path)
|
128
|
-
|
129
|
-
msg = Util::Message.new()
|
130
|
-
|
131
|
-
if isEmpty(path)
|
132
28
|
|
133
|
-
|
29
|
+
# B.1.1. END
|
134
30
|
|
135
|
-
|
31
|
+
# B.1.2. SUCCESS MESSAGE
|
136
32
|
|
137
|
-
|
138
|
-
puts Paint["DIRECTORY LISTING: #{path}", :yellow]
|
139
|
-
puts ""
|
140
|
-
puts Paint[Dir.entries(path), :yellow]
|
141
|
-
puts ""
|
33
|
+
def success(msg)
|
142
34
|
|
143
|
-
|
35
|
+
puts ""
|
36
|
+
puts Paint["[SUCCESS]", :green]
|
37
|
+
puts Paint[msg, :green]
|
38
|
+
puts ""
|
144
39
|
|
145
|
-
|
40
|
+
end
|
146
41
|
|
147
|
-
|
42
|
+
# B.1.2. END
|
148
43
|
|
149
|
-
|
150
|
-
|
151
|
-
`rm -rf *`
|
44
|
+
# B.1.3. ERROR MESSAGE
|
152
45
|
|
153
|
-
|
46
|
+
def error(msg)
|
154
47
|
|
155
|
-
|
48
|
+
puts ""
|
49
|
+
puts Paint["[ERROR]", :red]
|
50
|
+
puts Paint[msg, :red]
|
51
|
+
puts ""
|
156
52
|
|
157
|
-
|
158
|
-
exit(1)
|
53
|
+
exit 1
|
159
54
|
|
160
|
-
|
55
|
+
end
|
161
56
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
57
|
+
# B.1.3. END
|
58
|
+
|
59
|
+
# B.1.4. HEADING
|
60
|
+
|
61
|
+
def heading(msg)
|
62
|
+
|
63
|
+
puts ""
|
64
|
+
puts Paint["----------------------------------------------------------------------------", :cyan]
|
65
|
+
puts Paint["--", :cyan]
|
66
|
+
puts Paint["-- #{ msg }", :cyan]
|
67
|
+
puts Paint["--", :cyan]
|
68
|
+
puts Paint["----------------------------------------------------------------------------", :cyan]
|
69
|
+
puts ""
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
# B.1.4. END
|
74
|
+
|
75
|
+
# B.1.5. PARAGRAPH
|
76
|
+
|
77
|
+
def paragraph(msg)
|
78
|
+
|
79
|
+
puts ""
|
80
|
+
puts Paint[msg, "999999"]
|
81
|
+
puts ""
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
# B.1.5. END
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# B.1. END ----------------------------------------------------------------------------------------------------------
|
90
|
+
|
91
|
+
# B.2. FILE SYSTEM --------------------------------------------------------------------------------------------------
|
92
|
+
|
93
|
+
class FS
|
94
|
+
|
95
|
+
# B.2.1. CHECK FOR EMPTY DIRECTORY
|
96
|
+
|
97
|
+
def isEmpty(path)
|
98
|
+
|
99
|
+
if Dir.entries(path).length > 2
|
100
|
+
result = true
|
101
|
+
else
|
102
|
+
result = false
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
# B.2.1. END
|
108
|
+
|
109
|
+
# B.2.2. CLEAR THE ENTIRE DIRECTORY
|
110
|
+
|
111
|
+
def clear_directory(path)
|
112
|
+
|
113
|
+
msg = Util::Message.new()
|
114
|
+
|
115
|
+
if isEmpty(path)
|
116
|
+
|
117
|
+
msg.warning("Your directory isn't empty! Konstruct can only be installed in an empty directory.");
|
118
|
+
puts Paint["----------------------------------------------------------------------------", :yellow]
|
119
|
+
puts ""
|
120
|
+
puts Paint["DIRECTORY LISTING: #{path}", :yellow]
|
121
|
+
puts ""
|
122
|
+
puts Paint[Dir.entries(path), :yellow]
|
123
|
+
puts ""
|
124
|
+
puts Paint["----------------------------------------------------------------------------", :yellow]
|
125
|
+
puts ""
|
126
|
+
choice = choose("Do you want to clear your working directory?", :yes, :no)
|
127
|
+
|
128
|
+
if choice == :yes
|
129
|
+
`rm -rf *`
|
130
|
+
msg.success("Working directory cleared: #{path}")
|
131
|
+
else
|
132
|
+
msg.error("Konstruct can only be installed in an empty directory.")
|
133
|
+
exit(1)
|
206
134
|
end
|
207
|
-
|
208
|
-
|
209
|
-
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
# B.2.2. END
|
141
|
+
|
142
|
+
# B.2.3. CLEAN DIRECTORY
|
143
|
+
|
144
|
+
def delete_files(path)
|
145
|
+
|
146
|
+
msg = Util::Message.new()
|
147
|
+
FileUtils.rm_rf(path)
|
148
|
+
|
210
149
|
end
|
211
|
-
|
212
|
-
# B.2. END
|
213
|
-
|
150
|
+
|
151
|
+
# B.2.3. END
|
152
|
+
|
153
|
+
# B.2.3. MAKE DIRECTORY
|
154
|
+
|
155
|
+
def make_dir(dir)
|
156
|
+
|
157
|
+
msg = Util::Message.new()
|
158
|
+
|
159
|
+
unless Dir[dir].length > 0
|
160
|
+
|
161
|
+
FileUtils.mkdir(dir)
|
162
|
+
msg.success("Created #{dir}")
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
# B.2.3. END
|
169
|
+
|
170
|
+
# B.2.4. READ JSON FILE
|
171
|
+
|
172
|
+
def read_config
|
173
|
+
|
174
|
+
config_dir = File.expand_path('~/.konstruct')
|
175
|
+
YAML.load_file("#{config_dir}/config.yml")
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
# B.2.4. END
|
180
|
+
|
181
|
+
# B.2.4. READ JSON FILE
|
182
|
+
|
183
|
+
def read_project(path)
|
184
|
+
|
185
|
+
YAML.load_file("#{path}/.konstruct.yml")
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
# B.2.4. END
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
# B.2. END ----------------------------------------------------------------------------------------------------------
|
194
|
+
|
214
195
|
end
|
215
196
|
|
216
197
|
# B. END ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|