richcss 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 09d0e0a3a4e317c7dafce1aa4d3c1fc5cd2b6e1f
4
+ data.tar.gz: 411df6d822124af8ec79443d4afc5c48131518fe
5
+ SHA512:
6
+ metadata.gz: 2877d5bea707c176149564ba298572015a8c13e0bb754bdceaaf475f2ce524fe537b0ea00181cce8aae4455f2a49e888038d126ba3d82a0837fcf87e46ce991a
7
+ data.tar.gz: ff506b25f7dcec0ad306896a2462c2b489081b1353415dbdf6f8b47f56beecfaed9d31ae2de5c367ab194f8d1592237b21379bf0114ef0f8f5e6c829df01fed3
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /*.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in richcss.gemspec
4
+ gemspec
5
+
6
+ gem 'version_kit', git: 'https://github.com/CocoaPods/VersionKit.git', branch: 'master'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 TODO: Write your name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Richcss-cli
2
+
3
+ Richcss CLI is a tool to manage your CSS using the RichCSS framework.
4
+ It also includes a package manager to help install and create your own RichCSS parts for others to use.
5
+
6
+ Both CSS and SASS are supported.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'richcss'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install richcss
23
+
24
+
25
+ ## Usage
26
+
27
+ ### Using RichCSS in your project
28
+
29
+ To start, in the directory where you want to put all your CSS, run
30
+
31
+ $ richcss init
32
+
33
+ to create the skeleton structure. Currently, only CSS is supported by `init`.
34
+
35
+ #### Using RichCSS parts
36
+
37
+ In the directory created using `richcss init`, you can install third-party parts using
38
+
39
+ $ richcss install <PART> [VERSION]
40
+
41
+ The version is optional and will default to the latest version of that part.
42
+
43
+ ### Creating your own RichCSS Part
44
+
45
+ Generate the necessary files for your Part with
46
+
47
+ $ richcss part init <PART_NAME>
48
+
49
+ #### Publishing your Part for others to use
50
+
51
+ Before releasing your Part to the public, you may run
52
+
53
+ $ richcss part check [PART_PATH]
54
+
55
+ to make sure everything is valid. Then publish it to CSSParts with
56
+
57
+ $ richcss part push <PART_NAME>
58
+
59
+
60
+ ## Development
61
+
62
+ After checking out the repo, run `bundle install` to install dependencies.
63
+ To install this gem onto your local machine, run `bundle exec rake install`.
64
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
65
+ which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
66
+
67
+
68
+ ## Contributing
69
+
70
+ Bug reports and pull requests are welcome on GitHub at https://github.com/fdp-A4/richcss-cli
71
+
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
76
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "richcss"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/richcss ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'richcss'
3
+ require 'richcss/cli'
4
+
5
+ RichcssCLI::Cli.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/exe/richcss ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'richcss'
3
+ require 'richcss/cli'
4
+
5
+ RichcssCLI::Cli.start
@@ -0,0 +1,105 @@
1
+ require 'thor'
2
+ require 'richcss'
3
+
4
+ module RichcssCLI
5
+ class Part < Thor
6
+ desc "init <PART_NAME>", "Generate a skeleton directory for your new Rich CSS part"
7
+ # part_name
8
+ # |--- lib
9
+ # | |--- elements
10
+ # | | |--- ...
11
+ # | |--- box
12
+ # | | |--- ...
13
+ # |--- part_name.spec
14
+ # |--- README.md
15
+ def init(part)
16
+ Richcss::Generators::PartTemplate.start([part])
17
+ end
18
+
19
+ desc "check [PART_PATH]", "Validate folder/file structure of the Rich CSS part, optionally passing in a path"
20
+ def check(part_dir_name=nil)
21
+ part_path = "#{Dir.pwd}" + "/" + "#{part_dir_name}" || Dir.pwd
22
+ result = Richcss::Manager.check(part_path)
23
+ Dir.chdir(part_path)
24
+ if !result.nil?
25
+ puts result
26
+ return false
27
+ end
28
+
29
+ partPathSplit = part_path.split("/")
30
+ partName = partPathSplit[partPathSplit.length - 1]
31
+
32
+ puts "Passed all validation checks, part: #{partName} is ready for upload!"
33
+ return true
34
+ end
35
+
36
+ desc "push <PART_PATH>", "Attempt to upload a new Rich CSS part to our servers"
37
+ def push(part_dir_name=nil)
38
+ part_path = "#{Dir.pwd}" + "/" + "#{part_dir_name}" || Dir.pwd
39
+ if check(part_dir_name)
40
+ Richcss::Manager.upload(part_path)
41
+ end
42
+ end
43
+ end
44
+
45
+ class Cli < Thor
46
+ desc "init", "Initialize current directory to follow the Rich CSS framework"
47
+ # elements
48
+ # |--- ...
49
+ # box
50
+ # |--- ...
51
+ # parts
52
+ # |--- ...
53
+ def init()
54
+ Richcss::Generators::Template.start()
55
+ end
56
+
57
+ desc "install <PART> [VERSION]", "Install the part requested into the Parts directory"
58
+ def install(part_name, part_version='')
59
+ installed_parts = Richcss::Part.get_or_create_partfile()
60
+ if part_version.eql?('')
61
+ RestClient.get("http://www.cssparts.com/api/part/#{part_name}") { |response, request, result, &block|
62
+ if response.code == 200
63
+ body = JSON.parse(response.to_str)
64
+ part_version = body["version"]
65
+ elsif response.code == 400
66
+ puts "Part: #{part_name} cannot be found."
67
+ return
68
+ else
69
+ puts "Error #{response.code} retrieving Part: #{part_name}"
70
+ return
71
+ end
72
+ }
73
+ else
74
+ RestClient.get("http://www.cssparts.com/api/part/#{part_name}", {:params => {'version' => part_version}}) { |response, request, result, &block|
75
+ if response.code == 400
76
+ puts "Part: #{part_name} #{part_version} does not exist."
77
+ return
78
+ elsif response.code != 200
79
+ puts "Error #{response.code} retrieving Part: #{part_name} #{part_version}"
80
+ return
81
+ end
82
+ }
83
+ end
84
+
85
+ if installed_parts.key?(part_name) and installed_parts[part_name].eql?(part_version)
86
+ puts "Part #{part_name} v#{part_version} is already installed!"
87
+ return
88
+ end
89
+
90
+ partfileList = ''
91
+ dep_list = Richcss::Part.resolve_dependencies(part_name, part_version, installed_parts)
92
+ dep_list.each do |dep|
93
+ Richcss::Part.fetch(dep.name, dep.version)
94
+ partfileList << dep.name << " " << dep.version.to_s << "\n"
95
+ end
96
+
97
+ File.open('parts/Partfile', 'wb') do |f|
98
+ f.write(partfileList)
99
+ end
100
+ end
101
+
102
+ desc "part", "Commands for creating and uploading your own Rich CSS parts"
103
+ subcommand "part", Part
104
+ end
105
+ end
@@ -0,0 +1,18 @@
1
+ /* Import all your CSS files here */
2
+
3
+ /* Box CSS */
4
+ @import 'box/blocks.scss';
5
+ @import 'box/main.scss';
6
+ @import 'box/positioning.scss';
7
+
8
+ /* Element CSS */
9
+ @import 'elements/buttons.scss';
10
+ @import 'elements/colors.scss';
11
+ @import 'elements/features.scss';
12
+ @import 'elements/fonts.scss';
13
+ @import 'elements/images.scss';
14
+ @import 'elements/inputs.scss';
15
+ @import 'elements/lists.scss';
16
+
17
+ /* Parts CSS */
18
+ @import 'parts/parts.scss';
@@ -0,0 +1,109 @@
1
+ require 'thor/group'
2
+ require 'json'
3
+
4
+ module Richcss
5
+ module Generators
6
+ class Template < Thor::Group
7
+ include Thor::Actions
8
+
9
+ def self.source_root
10
+ File.dirname(__FILE__) + "/generator"
11
+ end
12
+
13
+ def init
14
+ @groups = ['box', 'elements', 'parts']
15
+ @boxFiles = ['blocks', 'main', 'positioning']
16
+ @elementFiles = ['button', 'colors', 'features', 'fonts', 'images', 'inputs', 'lists']
17
+ @partFiles = ['Partfile']
18
+ end
19
+
20
+ def create_folders
21
+ @groups.each do |g|
22
+ empty_directory("#{g}") unless Dir.exists?("#{g}")
23
+ end
24
+ end
25
+
26
+ def create_css_files
27
+ # TODO: add choice of CSS or SCSS files to generate
28
+ # TODO: Make it not hardcode box/elements
29
+ extension = ".css"
30
+ # extension = ".css.scss"
31
+ @boxFiles.each do |filename|
32
+ create_file "box/#{filename}#{extension}" unless File.file?("box/#{filename}#{extension}")
33
+ end
34
+
35
+ @elementFiles.each do |filename|
36
+ create_file "elements/#{filename}#{extension}" unless File.file?("elements/#{filename}#{extension}")
37
+ end
38
+ end
39
+
40
+ def create_partfile
41
+ create_file "parts/Partfile" unless File.file?("parts/Partfile")
42
+ end
43
+ end
44
+
45
+ class PartTemplate < Thor::Group
46
+ include Thor::Actions
47
+
48
+ argument :part_name, :type => :array
49
+ # argument :part, :type => :array
50
+ # argument :part_name, :type => :string
51
+
52
+ def self.source_root
53
+ File.dirname(__FILE__) + "/generator"
54
+ end
55
+
56
+ def init
57
+ @name = part_name.first
58
+ @groups = ['box', 'elements']
59
+ @boxFiles = ['blocks', 'main', 'positioning']
60
+ @elementFiles = ['button', 'colors', 'features', 'fonts', 'images', 'inputs', 'lists']
61
+ end
62
+
63
+ def create_folders
64
+ empty_directory(@name) unless Dir.exists?(@name)
65
+ empty_directory("#{@name}/lib") unless Dir.exists?("#{@name}/lib")
66
+ @groups.each do |g|
67
+ empty_directory("#{@name}/lib/#{g}") unless Dir.exists?("#{@name}/lib/#{g}")
68
+ end
69
+ end
70
+
71
+ def create_css_files
72
+ # TODO: add choice of CSS or SCSS files to generate
73
+ # TODO: Make it not hardcode box/elements
74
+ extension = ".css"
75
+ # extension = ".css.scss"
76
+ @boxFiles.each do |filename|
77
+ create_file "#{@name}/lib/box/#{filename}#{extension}" unless File.file?("#{@name}/lib/box/#{filename}#{extension}")
78
+ end
79
+
80
+ @elementFiles.each do |filename|
81
+ create_file "#{@name}/lib/elements/#{filename}#{extension}" unless File.file?("#{@name}/lib/elements/#{filename}#{extension}")
82
+ end
83
+ end
84
+
85
+ def create_files
86
+ create_file "#{@name}/README.md" unless File.file?("#{@name}/README.md")
87
+
88
+ if !File.file?("#{@name}/#{@name.downcase}.spec")
89
+ create_file "#{@name}/#{@name.downcase}.spec"
90
+ # Write JSON to Test.Spec
91
+ specs = {
92
+ "name" => "#{@name}",
93
+ "authors" => "AUTHOR_NAME",
94
+ "email" => "AUTHOR_EMAIL",
95
+ "description" => "DESCRIPTION",
96
+ "version" => "0.0.0",
97
+ "homepage" => "GITHUB_REPO_URL",
98
+ "dependencies" => {
99
+ "DEPENDECY_NAME" => "DEPENDECY_VERSION"
100
+ }
101
+ }
102
+ File.open("#{@name}/#{@name.downcase}.spec","w") do |f|
103
+ f.write(JSON.pretty_generate(specs))
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,213 @@
1
+ require 'richcss'
2
+ require 'rest-client'
3
+ require 'json'
4
+ require 'active_model'
5
+ require 'email_validator'
6
+
7
+ module Richcss
8
+ class Manager
9
+ # Checks if the folder has the required format for uploading
10
+ def self.check(check_dir)
11
+ Dir.chdir(check_dir)
12
+
13
+ # LEVEL 1
14
+ # Find the spec file and the part name
15
+ part_name = ''
16
+ specFilePath = ''
17
+ Dir.glob("*.spec").each do |f|
18
+ part_name = File.basename(f, '.spec')
19
+ specFilePath = "#{check_dir}/#{f}"
20
+ end
21
+ if part_name.empty?
22
+ return "Rich CSS spec file not found"
23
+ end
24
+
25
+ # Check if readme exists
26
+ if !File.file?("#{check_dir}/README.md")
27
+ return "README.md file not found"
28
+ end
29
+
30
+ if !Dir.exist?('lib')
31
+ return "lib folder not found"
32
+ end
33
+
34
+ # LEVEL 2 / LIB
35
+ Dir.chdir('lib')
36
+ groups = ['box', 'elements']
37
+
38
+ groups.each do |g|
39
+ if !Dir.exist?(g)
40
+ return "#{g} folder not found in lib"
41
+ end
42
+ end
43
+
44
+ # LEVEL 3 BOX/ELEMENTS/PARTS
45
+ # TODO: Don't do this hardcoded for box/elements, use like some hashmap or something..
46
+ boxFiles = ['blocks', 'main', 'positioning']
47
+ elementFiles = ['button', 'colors', 'features', 'fonts', 'images', 'inputs', 'lists']
48
+ validExtensions = ['.css', '.css.scss']
49
+
50
+ fileCount = 0
51
+ Dir.foreach('box') do |filename|
52
+ next if filename == '.' or filename == '..'
53
+ boxFiles.each do |b|
54
+ validExtensions.each do |ext|
55
+ if filename == "#{b}#{ext}"
56
+ fileCount += 1
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ if fileCount < boxFiles.size
63
+ return "Missing css files in box folder, required #{boxFiles}"
64
+ end
65
+
66
+ fileCount = 0
67
+ Dir.foreach('elements') do |filename|
68
+ next if filename == '.' or filename == '..'
69
+ elementFiles.each do |b|
70
+ validExtensions.each do |ext|
71
+ if filename == "#{b}#{ext}"
72
+ fileCount += 1
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ if fileCount < elementFiles.size
79
+ return "Missing css files in elements folder, required #{elementFiles}"
80
+ end
81
+
82
+ # SPEC FILE CHECK
83
+ specFile = "#{part_name}.spec"
84
+
85
+ begin
86
+ jsonData = File.read(specFilePath)
87
+ hash = JSON.parse(jsonData)
88
+ rescue
89
+ return "Invalid Json format in #{specFile}"
90
+ end
91
+
92
+ defaultSpecs = {
93
+ "authors" => "AUTHOR_NAME",
94
+ "email" => "AUTHOR_EMAIL",
95
+ "description" => "DESCRIPTION",
96
+ "homepage" => "GITHUB_REPO_URL"
97
+ }
98
+ requiredSpecs = ['name', 'authors', 'email', 'description', 'version', 'homepage', 'dependencies']
99
+
100
+ # Ensure each spec exist
101
+ requiredSpecs.each do |spec|
102
+ if hash[spec].nil? && spec != 'dependencies'
103
+ return "Missing \"#{spec}\" definition in #{specFile}"
104
+ end
105
+ end
106
+
107
+ # Check for default entries
108
+ defaultSpecs.keys.each do |spec|
109
+ if hash[spec] == defaultSpecs[spec]
110
+ return "Default value for \"#{spec}\" in #{specFile} is being used, please change it to a valid entry"
111
+ end
112
+ end
113
+
114
+ # Check email
115
+ if !EmailValidator.valid?(hash[requiredSpecs[2]])
116
+ return "Email address is invalid"
117
+ end
118
+
119
+ # Check Part_Name
120
+ if (hash[requiredSpecs[0]] != part_name)
121
+ return "Invalid part name: \"#{hash[requiredSpecs[0]]}\" in #{specFile}, should be \"#{part_name}\""
122
+ end
123
+
124
+
125
+ # Check if github url exist
126
+ uri = URI.parse(hash[requiredSpecs[5]])
127
+
128
+ http_object = Net::HTTP.new(uri.host, uri.port)
129
+ http_object.use_ssl = true if uri.scheme == 'https'
130
+ begin
131
+ http_object.start do |http|
132
+ request = Net::HTTP::Get.new uri.request_uri
133
+ http.read_timeout = 500
134
+ http.request request do |response|
135
+ case response
136
+ when Net::HTTPNotFound then
137
+ return "Could not access GitHub url, please use a public repository"
138
+ end
139
+ end
140
+ end
141
+ rescue
142
+ return "Invalid URL for homepage"
143
+ end
144
+
145
+ # Check for version
146
+ begin
147
+ resp = RestClient.get "http://www.cssparts.com/api/part/#{part_name}"
148
+ if resp.code == 200
149
+ body = JSON.parse(resp.to_str)
150
+ current_version = body["version"]
151
+ part_version = hash[requiredSpecs[4]]
152
+ if Gem::Version.new(current_version) >= Gem::Version.new(part_version)
153
+ return "Part version: \"#{part_version}\" in #{specFile} must be greater than existing version: \"#{current_version}\""
154
+ end
155
+ end
156
+ rescue RestClient::ExceptionWithResponse => e
157
+ end
158
+
159
+ # Check dependency existance
160
+ dependencies = hash[requiredSpecs[6]]
161
+ if dependencies.nil? || dependencies.empty?
162
+ return nil
163
+ end
164
+
165
+ begin
166
+ dependencies = dependencies.to_a.map { |x| "#{x[0]}=#{x[1].to_s}" }.join("&")
167
+ resp = RestClient.get "http://www.cssparts.com/api/validateDependencies/#{dependencies}"
168
+ rescue RestClient::ExceptionWithResponse => e
169
+ return e.response
170
+ end
171
+
172
+ return nil
173
+ end
174
+
175
+ # Fetch url and download the part
176
+ def self.getPartData(part_name)
177
+ begin
178
+ resp = RestClient.get "http://www.cssparts.com/api/part/#{part_name}"
179
+ if resp.code == 200
180
+ body = JSON.parse(resp.to_str)
181
+ return body
182
+ else
183
+ puts "Error: Part #{name} cannot be found."
184
+ end
185
+ rescue RestClient::ExceptionWithResponse => e
186
+ puts e.response
187
+ end
188
+ return nil
189
+ end
190
+
191
+ def self.upload(part_path)
192
+ partPathSplit = part_path.split("/")
193
+ partName = partPathSplit[partPathSplit.length - 1]
194
+
195
+ if !File.file?("#{part_path}/#{partName}.spec")
196
+ puts "#{part_path}/#{partName}.spec file not found"
197
+ return
198
+ end
199
+
200
+ specs = File.read("#{part_path}/#{partName}.spec")
201
+ specsJson = JSON.parse(specs)
202
+
203
+ begin
204
+ puts RestClient.post "http://www.cssparts.com/api/upload", :name => partName, :description => specsJson["description"],
205
+ :version => specsJson["version"], :authors => specsJson["authors"], :email => specsJson["email"], :homepage => specsJson["homepage"],
206
+ :dependencies => specsJson["dependencies"]
207
+ rescue RestClient::ExceptionWithResponse => e
208
+ puts e.response
209
+ end
210
+ end
211
+
212
+ end
213
+ end
@@ -0,0 +1,119 @@
1
+ require 'json'
2
+ require 'rest-client'
3
+ require 'uri'
4
+ require 'zipruby'
5
+
6
+ module Richcss
7
+ class Part
8
+ attr_accessor :name
9
+
10
+ # placeholder for latest version is blank
11
+ def self.resolve_dependencies(part_name, version, installed={})
12
+ dep_list = Richcss::Resolver.start(part_name, version, installed)
13
+ end
14
+
15
+ def self.get_or_create_partfile()
16
+ if !Dir.exists?('parts')
17
+ FileUtils.mkdir_p('parts')
18
+ end
19
+
20
+ parts = Hash.new
21
+ Dir.chdir('parts') do
22
+ part_file = "Partfile"
23
+
24
+ begin
25
+ File.open(part_file, "r") do |f|
26
+ f.each_line do |line|
27
+ part, version = line.split(" ")
28
+ parts[part] = version
29
+ end
30
+ end
31
+ rescue
32
+ File.new(part_file, "w")
33
+ end
34
+ end
35
+
36
+ return parts
37
+ end
38
+
39
+ # Fetch url and download the part
40
+ def self.fetch(part_name, version)
41
+ puts "Fetching part #{part_name}"
42
+
43
+ begin
44
+ resp = RestClient.get "http://www.cssparts.com/api/part/#{part_name}"
45
+ if resp.code == 200
46
+ body = JSON.parse(resp.to_str)
47
+ homepage = body["homepage"]
48
+ homepage.slice! "https:\/\/github.com\/"
49
+ homepage = homepage.split("\/")
50
+ repo_owner = homepage[0]
51
+ repo_name = homepage[1]
52
+ jsonResponse = JSON.parse(Net::HTTP.get(URI("https://api.github.com/repos/#{repo_owner}/#{repo_name}/releases/tags/v#{body["version"]}")))
53
+ downloadLink = jsonResponse["zipball_url"]
54
+ install(part_name, body["version"], downloadLink)
55
+ else
56
+ puts "Error: Part #{name} cannot be found."
57
+ end
58
+ rescue RestClient::ExceptionWithResponse => e
59
+ puts e.response
60
+ end
61
+ end
62
+
63
+ # Install this part
64
+ def self.install(part_name, version, resource)
65
+ uri = URI.parse(resource)
66
+
67
+ http_object = Net::HTTP.new(uri.host, uri.port)
68
+ http_object.use_ssl = true if uri.scheme == 'https'
69
+ begin
70
+ http_object.start do |http|
71
+ request = Net::HTTP::Get.new uri.request_uri
72
+ http.read_timeout = 500
73
+ http.request request do |response|
74
+ case response
75
+ when Net::HTTPRedirection then
76
+ location = response['location']
77
+ install(part_name, version, location)
78
+ else
79
+ puts "Installing part..."
80
+
81
+ if !Dir.exists?('parts')
82
+ FileUtils.mkdir_p('parts')
83
+ end
84
+
85
+ Dir.chdir('parts') do
86
+ if Dir.exists?(part_name)
87
+ FileUtils.remove_dir(part_name)
88
+ end
89
+ Zip::Archive.open_buffer(response.body) do |ar|
90
+ #save the directory name for rename later
91
+ oldDirName = ar.get_name(0)
92
+
93
+ ar.each do |zf|
94
+ if zf.directory?
95
+ FileUtils.mkdir_p(zf.name)
96
+ else
97
+ dirname = File.dirname(zf.name)
98
+ FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
99
+ open(zf.name, 'wb') do |f|
100
+ f << zf.read
101
+ end
102
+ end
103
+ end
104
+
105
+ FileUtils.mv oldDirName, part_name
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ RestClient.post "http://www.cssparts.com/api/part/downloaded", :name => part_name, :version => version
113
+ rescue Exception => e
114
+ puts e
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,27 @@
1
+ require 'molinillo'
2
+ require 'version_kit'
3
+
4
+ module Richcss
5
+ class Resolver
6
+
7
+ def self.start(part_name, version, installed = {})
8
+ requirements = [VersionKit::Dependency.new(part_name, version)]
9
+ installed.each do | p, v |
10
+ requirements.push(VersionKit::Dependency.new(p, v))
11
+ end
12
+ @resolver = Molinillo::Resolver.new(RichSpecificationProvider.new(part_name, version), RichUI.new)
13
+ @base_dg = Molinillo::DependencyGraph.new
14
+ dg = @resolver.resolve(requirements, @base_dg)
15
+ puts "Succesfully resolved dependencies:\n"
16
+ dg.map(&:payload).flatten
17
+ rescue Molinillo::VersionConflict => e
18
+ puts e
19
+ rescue Molinillo::CircularDependencyError => e
20
+ names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
21
+ puts "Your RichCSS part requires parts that depend" \
22
+ " on each other, creating an circular loop. Please remove" \
23
+ " #{names.count > 1 ? "either " : ""}#{names.join(" or ")}" \
24
+ " and try again."
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,75 @@
1
+ require 'version_kit'
2
+ require 'molinillo'
3
+
4
+ module Richcss
5
+ class RichSpecificationProvider
6
+ attr_accessor :specs
7
+ attr_accessor :part_name
8
+ attr_accessor :version
9
+
10
+ include Molinillo::SpecificationProvider
11
+
12
+ def initialize(name, version)
13
+ self.part_name = name
14
+ self.version = version
15
+ response = RestClient.get "http://www.cssparts.com/api/part/#{name}/dependency", {:params => {'version' => version}}
16
+ if response.code == 200
17
+ self.specs = JSON.load(response.body).reduce(Hash.new([])) do |specs_by_name, (dep_name, dep_versions)|
18
+ specs_by_name.tap do |specs|
19
+ specs[dep_name] = dep_versions.map { |s| Richcss::TestSpecification.new s }.sort_by(&:version)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def requirement_satisfied_by?(requirement, _activated, spec)
26
+ requirement.satisfied_by?(spec.version)
27
+ end
28
+
29
+ def search_for(dependency)
30
+ @search_for ||= {}
31
+ @search_for[dependency] ||= begin
32
+ pre_release = dependency_pre_release?(dependency)
33
+ specs[dependency.name].select do |spec|
34
+ (pre_release ? true : !spec.version.pre_release?) &&
35
+ dependency.satisfied_by?(spec.version)
36
+ end
37
+ end
38
+ end
39
+
40
+ def name_for(dependency)
41
+ dependency.name
42
+ end
43
+
44
+ def name_for_explicit_dependency_source
45
+ 'Partfile'
46
+ end
47
+
48
+ def name_for_locking_dependency_source
49
+ 'Partfile.lock'
50
+ end
51
+
52
+ def dependencies_for(dependency)
53
+ dependency.dependencies
54
+ end
55
+
56
+ def sort_dependencies(dependencies, activated, conflicts)
57
+ dependencies.sort_by do |d|
58
+ [
59
+ activated.vertex_named(d.name).payload ? 0 : 1,
60
+ dependency_pre_release?(d) ? 0 : 1,
61
+ conflicts[d.name] ? 0 : 1,
62
+ activated.vertex_named(d.name).payload ? 0 : search_for(d).count,
63
+ ]
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def dependency_pre_release?(dependency)
70
+ dependency.requirement_list.requirements.any? do |r|
71
+ VersionKit::Version.new(r.reference_version).pre_release?
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,22 @@
1
+ module Richcss
2
+ class TestSpecification
3
+ attr_accessor :name, :version, :dependencies
4
+ def initialize(hash)
5
+ self.name = hash['name']
6
+ self.version = VersionKit::Version.new(hash['version'])
7
+ self.dependencies = hash['dependencies'].map do |(name, requirement)|
8
+ VersionKit::Dependency.new(name, requirement.split(',').map(&:chomp))
9
+ end
10
+ end
11
+
12
+ def ==(other)
13
+ name == other.name &&
14
+ version == other.version &&
15
+ dependencies == other.dependencies
16
+ end
17
+
18
+ def to_s
19
+ "#{name} (#{version})"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ require 'molinillo'
2
+
3
+ module Richcss
4
+ class RichUI
5
+ include Molinillo::UI
6
+ # Conveys debug information to the user.
7
+ #
8
+ # @param [Integer] depth the current depth of the resolution process.
9
+ # @return [void]
10
+ def debug(depth = 0)
11
+ if debug?
12
+ debug_info = yield
13
+ debug_info = debug_info.inspect unless debug_info.is_a?(String)
14
+ STDERR.puts debug_info.split("\n").map {|s| " " * depth + s }
15
+ end
16
+ end
17
+
18
+ def debug?
19
+ ENV["DEBUG_RESOLVER"] || ENV["DEBUG_RESOLVER_TREE"]
20
+ end
21
+
22
+ def before_resolution
23
+ Bundler.ui.info "Resolving dependencies...", false
24
+ end
25
+
26
+ def after_resolution
27
+ Bundler.ui.info ""
28
+ end
29
+
30
+ def indicate_progress
31
+ Bundler.ui.info ".", false
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Richcss
2
+ VERSION = "0.1.0"
3
+ end
data/lib/richcss.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'richcss/version'
2
+
3
+ module Richcss
4
+ autoload :Generators, 'richcss/generators'
5
+ autoload :Part, 'richcss/part'
6
+ autoload :Manager, 'richcss/manager'
7
+ autoload :Resolver, 'richcss/resolver'
8
+ autoload :RichSpecificationProvider, 'richcss/richcss_specification_provider'
9
+ autoload :RichUI, 'richcss/richcss_ui'
10
+ autoload :TestSpecification, 'richcss/richcss_test_specification'
11
+
12
+ class << self
13
+ # TODO
14
+ end
15
+ end
data/richcss.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'richcss/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "richcss"
8
+ spec.version = Richcss::VERSION
9
+ spec.authors = ["Nicholas Lo, Gabriel Cheng, Bill Xu, Jonathan Lai, David Zhu"]
10
+ spec.email = ["richcssa4@gmail.com"]
11
+
12
+ spec.summary = %q{This is a command line package manager for the RichCSS framework}
13
+ spec.homepage = "https://github.com/fdp-A4/richcss-cli"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = "richcss"
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "pry"
25
+
26
+ spec.add_dependency "thor"
27
+ spec.add_dependency "molinillo"
28
+ spec.add_dependency "rest-client"
29
+ spec.add_dependency "zipruby"
30
+ spec.add_dependency "email_validator"
31
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: richcss
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas Lo, Gabriel Cheng, Bill Xu, Jonathan Lai, David Zhu
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: molinillo
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rest-client
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: zipruby
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: email_validator
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description:
140
+ email:
141
+ - richcssa4@gmail.com
142
+ executables:
143
+ - richcss
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - Gemfile
150
+ - LICENSE.txt
151
+ - README.md
152
+ - Rakefile
153
+ - bin/console
154
+ - bin/richcss
155
+ - bin/setup
156
+ - exe/richcss
157
+ - lib/richcss.rb
158
+ - lib/richcss/cli.rb
159
+ - lib/richcss/generator/routes.scss
160
+ - lib/richcss/generators.rb
161
+ - lib/richcss/manager.rb
162
+ - lib/richcss/part.rb
163
+ - lib/richcss/resolver.rb
164
+ - lib/richcss/richcss_specification_provider.rb
165
+ - lib/richcss/richcss_test_specification.rb
166
+ - lib/richcss/richcss_ui.rb
167
+ - lib/richcss/version.rb
168
+ - richcss.gemspec
169
+ homepage: https://github.com/fdp-A4/richcss-cli
170
+ licenses:
171
+ - MIT
172
+ metadata: {}
173
+ post_install_message:
174
+ rdoc_options: []
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubyforge_project:
189
+ rubygems_version: 2.2.2
190
+ signing_key:
191
+ specification_version: 4
192
+ summary: This is a command line package manager for the RichCSS framework
193
+ test_files: []