ginatra 4.0.2 → 4.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -2
  3. data/CHANGELOG.md +10 -0
  4. data/README.md +16 -9
  5. data/bin/ginatra +1 -1
  6. data/config.ru +13 -2
  7. data/ginatra.gemspec +7 -4
  8. data/lib/ginatra.rb +2 -0
  9. data/lib/ginatra/config.rb +15 -5
  10. data/lib/ginatra/helpers.rb +9 -9
  11. data/lib/ginatra/logger.rb +33 -0
  12. data/lib/ginatra/repo.rb +5 -2
  13. data/lib/ginatra/repo_list.rb +3 -1
  14. data/lib/ginatra/version.rb +2 -2
  15. data/public/css/application.css +1 -2
  16. data/public/css/custom.css +14 -14
  17. data/public/css/twbs.sass +8 -0
  18. data/public/img/asterisk.svg +6 -0
  19. data/public/img/download.svg +6 -0
  20. data/public/img/edit.svg +6 -0
  21. data/public/img/exclamation-circle.svg +6 -0
  22. data/public/img/file.svg +6 -0
  23. data/public/img/folder.svg +6 -0
  24. data/public/img/hdd-o.svg +6 -0
  25. data/public/img/loader.svg +33 -0
  26. data/public/img/mail-forward.svg +6 -0
  27. data/public/img/minus-square.svg +6 -0
  28. data/public/img/plus-square.svg +6 -0
  29. data/public/js/custom.js +1 -1
  30. data/spec/ginatra/helpers_spec.rb +4 -4
  31. data/spec/ginatra/logger_spec.rb +9 -0
  32. data/spec/spec_helper.rb +2 -0
  33. data/views/_footer.erb +2 -6
  34. data/views/_tree_nav.erb +45 -41
  35. data/views/blob.erb +6 -4
  36. data/views/commit.erb +20 -18
  37. data/views/empty_repo.erb +3 -5
  38. data/views/index.erb +16 -14
  39. data/views/layout.erb +4 -3
  40. data/views/log.erb +25 -23
  41. data/views/stats.erb +26 -24
  42. data/views/tree.erb +12 -19
  43. metadata +39 -15
  44. data/public/css/lib/bootstrap-responsive.min.css +0 -9
  45. data/public/css/lib/bootstrap.min.css +0 -9
  46. data/public/img/glyphicons-halflings-white.png +0 -0
  47. data/public/img/glyphicons-halflings.png +0 -0
  48. data/public/img/spin.gif +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7486b2e308bef06b35966a5b283ed57583769b56
4
- data.tar.gz: 595c3170a2f8cd8633a4bd036fe81bd599c8fd1e
3
+ metadata.gz: 5f2109eb19ee364f25ded4abeb264b2398b74c99
4
+ data.tar.gz: 341a3c3c640d790bfdb185122ebf32ce45acc3aa
5
5
  SHA512:
6
- metadata.gz: aeef96eb4c2bc7ea2b6130dbd8000beb76d7ef70f7181787dcfdb98dd3cf5850b1281e224cb667e42d7ba7df522589c37548201c27ae4fc77f65be2b8aac8bf7
7
- data.tar.gz: 16af836e42d6d06c25783311e1dc332a9a6ea4f4e3d60cc7a417fa0a4a31826347dbb988fe32327f43887e893a0a9ad68c42a6cfcaa3e1dfff06394005f98ff4
6
+ metadata.gz: 0bceaa52a1f6b49c0ab81ade0dc316277d9959232aa8f322ff72ae00e2dc2c9a3ca1b48c3ded00a8d79dc2b00f3136abe570e92ae52c260cbf962cc49980abc4
7
+ data.tar.gz: a6c703be9047fb390d65e3130b2b315e95ce2aa89618facd46ee0d3df56e1b9bb2e2684a10ec1d7fc036f1e613974f1a08e6527a9b036b8cbe3a61b9fed4a951
@@ -1,7 +1,8 @@
1
1
  rvm:
2
2
  - 1.9.3
3
- - 2.0.0
4
- - 2.1.0
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
5
6
  notifications:
6
7
  email:
7
8
  on_success: never # default: change
@@ -2,6 +2,16 @@
2
2
 
3
3
  * Your contribution here.
4
4
 
5
+ ## 4.1.0 (2015-04-19)
6
+
7
+ * Log warnings and errors. Add a new setting: `log_file` to customize log file
8
+ location.
9
+ * Fix server startup when using Ruby 1.9
10
+ * Upgrade to Twitter Bootstrap 3. Make interface mobile-friendly and
11
+ responsive.
12
+ * Introduce a new setting: `sitename` to customize title.
13
+ * Improve error handling for invalid custom configuration. (@rogermarlow)
14
+
5
15
  ## 4.0.2 (2015-01-15)
6
16
 
7
17
  * Ignore files in `git_dirs` by default and remove `ignored_files` setting.
data/README.md CHANGED
@@ -1,18 +1,19 @@
1
1
  # Ginatra
2
2
 
3
- [![Build Status](https://img.shields.io/travis/NARKOZ/ginatra/master.svg?style=flat)](https://travis-ci.org/NARKOZ/ginatra)
4
- [![Code Climate](https://img.shields.io/codeclimate/github/NARKOZ/ginatra.svg?style=flat)](https://codeclimate.com/github/NARKOZ/ginatra)
5
- [![Gem Version](https://img.shields.io/gem/v/ginatra.svg?style=flat)](https://rubygems.org/gems/ginatra)
6
- [![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/NARKOZ/ginatra/blob/master/LICENSE.txt)
3
+ [![Build Status](https://img.shields.io/travis/NARKOZ/ginatra/master.svg)](https://travis-ci.org/NARKOZ/ginatra)
4
+ [![Code Climate](https://img.shields.io/codeclimate/github/NARKOZ/ginatra.svg)](https://codeclimate.com/github/NARKOZ/ginatra)
5
+ [![Gem Version](https://img.shields.io/gem/v/ginatra.svg)](https://rubygems.org/gems/ginatra)
6
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/NARKOZ/ginatra/blob/master/LICENSE.txt)
7
7
 
8
8
  **Ginatra** is a simple web-based git repository browser built on Ruby Sinatra.
9
9
 
10
10
  [ [website](http://narkoz.github.io/ginatra) |
11
- [screenshots](http://narkoz.github.io/ginatra/screenshots) ]
11
+ [screenshots](http://narkoz.github.io/ginatra/screenshots) |
12
+ [demo](http://narkoz.github.io/ginatra/demo) ]
12
13
 
13
14
  ## Features
14
15
 
15
- + Hassle free installation
16
+ + Easy installation
16
17
  + Multiple repository support
17
18
  + Multiple branch/tag support
18
19
  + Commit history, diff, patch
@@ -32,7 +33,7 @@ It's recommended to install it as a ruby gem, unless you know what you're doing.
32
33
  Run the following command to install Ginatra from RubyGems:
33
34
 
34
35
  ```sh
35
- gem install ginatra -v 4.0.1
36
+ gem install ginatra -v 4.1.0
36
37
  ```
37
38
 
38
39
  Create config file (see [Configuration](#configuration) section in README).
@@ -52,7 +53,7 @@ Run the following commands to install Ginatra from source:
52
53
  ```sh
53
54
  git clone git://github.com/NARKOZ/ginatra.git
54
55
  cd ginatra/
55
- git checkout v4.0.1
56
+ git checkout v4.1.0
56
57
  bundle
57
58
  ```
58
59
 
@@ -74,6 +75,8 @@ Create `~/.ginatra/config.yml` file with your own settings. See
74
75
  `git_dirs` - Ginatra will look into these folders for git repositories. It's
75
76
  required to append `*` at the end of path. Example: `/home/Development/repos/*`
76
77
 
78
+ `sitename` - name of the site. Used in the page title and header.
79
+
77
80
  `description` - description of web interface. Used in index page.
78
81
 
79
82
  `port` - port that Ginatra server will run at.
@@ -84,7 +87,11 @@ required to append `*` at the end of path. Example: `/home/Development/repos/*`
84
87
  in subdirectory.
85
88
 
86
89
  `git_clone_enabled?` - enables smart HTTP support and allows to clone git
87
- repopsitories.
90
+ repositories.
91
+
92
+ `log_file` - location of the log file where Ginatra will log warnings and
93
+ errors. If this setting doesn't present Ginatra will log out to the standard
94
+ output (stdout).
88
95
 
89
96
  If you installed Ginatra as an app, you can change settings by editing
90
97
  `config.yml` file in root folder.
@@ -4,7 +4,7 @@ $:.unshift File.expand_path('../../lib', __FILE__)
4
4
 
5
5
  ENV['RACK_ENV'] ||= 'production'
6
6
 
7
- require 'ginatra'
7
+ require 'ginatra/config'
8
8
  require 'optparse'
9
9
 
10
10
  options = {
data/config.ru CHANGED
@@ -1,11 +1,18 @@
1
1
  require 'ginatra'
2
2
  require 'sprockets'
3
+ require 'bootstrap-sass'
3
4
 
4
5
  map '/assets' do
5
6
  environment = Sprockets::Environment.new
6
7
  root_path = File.dirname __FILE__
7
8
  environment.append_path "#{root_path}/public/js"
8
9
  environment.append_path "#{root_path}/public/css"
10
+
11
+ environment.context_class.class_eval do
12
+ def asset_path(path, options = {})
13
+ end
14
+ end
15
+
9
16
  run environment
10
17
  end
11
18
 
@@ -13,8 +20,12 @@ if Ginatra.config.git_clone_enabled?
13
20
  require 'mkmf'
14
21
  require 'git/webby'
15
22
 
16
- # Make the MakeMakefile logger write file output to null
17
- module MakeMakefile::Logging; @logfile = File::NULL; end
23
+ # Make the mkmf logger write file output to null
24
+ if RUBY_VERSION[0] == '1'
25
+ module Logging; @logfile = File::NULL; end
26
+ else
27
+ module MakeMakefile::Logging; @logfile = File::NULL; end
28
+ end
18
29
 
19
30
  git_executable = find_executable 'git'
20
31
  raise 'Git executable not found in PATH' if git_executable.nil?
@@ -18,10 +18,13 @@ Gem::Specification.new do |gem|
18
18
 
19
19
  gem.required_ruby_version = ">= 1.9"
20
20
 
21
- gem.add_dependency 'sinatra', '~> 1.4.5'
22
- gem.add_dependency 'rugged', '~> 0.21.3'
23
- gem.add_dependency 'rouge', '~> 1.7.7'
24
- gem.add_dependency 'sprockets', '~> 2.0'
21
+ gem.add_dependency 'sinatra', '~> 1.4.6'
22
+ gem.add_dependency 'rugged', '~> 0.21.4'
23
+ gem.add_dependency 'rouge', '~> 1.8.0'
24
+ gem.add_dependency 'sprockets', '~> 3.0'
25
+
26
+ # Assets
27
+ gem.add_dependency 'bootstrap-sass', '3.3.3'
25
28
 
26
29
  gem.add_development_dependency 'rake'
27
30
  gem.add_development_dependency 'rspec'
@@ -3,6 +3,7 @@ require 'sinatra/partials'
3
3
  require 'rouge'
4
4
  require 'ginatra/config'
5
5
  require 'ginatra/errors'
6
+ require 'ginatra/logger'
6
7
  require 'ginatra/helpers'
7
8
  require 'ginatra/repo'
8
9
  require 'ginatra/repo_list'
@@ -12,6 +13,7 @@ module Ginatra
12
13
  # The main application class.
13
14
  # Contains all the core application logic and mounted in +config.ru+ file.
14
15
  class App < Sinatra::Base
16
+ include Logger
15
17
  helpers Helpers, Sinatra::Partials
16
18
 
17
19
  configure do
@@ -15,13 +15,23 @@ module Ginatra
15
15
  custom_config_file = File.expand_path("~/.ginatra/config.yml")
16
16
  default_config_file = File.expand_path("#{current_path}/../../config.yml")
17
17
 
18
- config = YAML.load_file(default_config_file)
18
+ # Our own file should be there and we don't need to check its syntax
19
+ abort 'ginatra config file #{default_config_file} is missing.' unless File.exists?(default_config_file)
20
+ final_config = YAML.load_file(default_config_file)
19
21
 
20
- if File.exist?(custom_config_file)
21
- custom_config = YAML.load_file(custom_config_file)
22
- config.merge!(custom_config)
22
+ # User config file may not exist or be broken
23
+ if File.exists?(custom_config_file)
24
+ begin
25
+ custom_config = YAML.load_file(custom_config_file)
26
+ rescue Psych::SyntaxError => ex
27
+ puts "Cannot parse your config file #{ex.message}."
28
+ custom_config = {}
29
+ end
30
+ final_config.merge!(custom_config)
31
+ else
32
+ puts "User config file #{custom_config_file} absent. Will only see repos in #{final_config["git_dirs"].join(", ")}."
23
33
  end
24
34
 
25
- config
35
+ final_config
26
36
  end
27
37
  end
@@ -16,7 +16,7 @@ module Ginatra
16
16
  # Sets title for pages
17
17
  def title(*args)
18
18
  @title ||= []
19
- @title_options ||= { headline: nil, sitename: nil }
19
+ @title_options ||= { headline: nil, sitename: h(Ginatra.config.sitename) }
20
20
  options = args.last.is_a?(Hash) ? args.pop : {}
21
21
 
22
22
  @title += args
@@ -43,17 +43,17 @@ module Ginatra
43
43
  def empty_description_hint_for(repo)
44
44
  return '' unless repo.description.empty?
45
45
  hint_text = "Edit `#{repo.path}description` file to set the repository description."
46
- "<span class='icon-exclamation-sign' title='#{hint_text}'></span>"
46
+ "<img src='/img/exclamation-circle.svg' title='#{hint_text}' alt='hint' class='icon'>"
47
47
  end
48
48
 
49
49
  # Returns file icon depending on filemode
50
50
  def file_icon(filemode)
51
51
  case filemode
52
52
  # symbolic link (120000)
53
- when 40960 then "<span class='icon-share-alt'></span>"
53
+ when 40960 then "<img src='/img/mail-forward.svg' alt='symbolic link' class='icon'>"
54
54
  # executable file (100755)
55
- when 33261 then "<span class='icon-asterisk'></span>"
56
- else "<span class='icon-file'></span>"
55
+ when 33261 then "<img src='/img/asterisk.svg' alt='executable file' class='icon'>"
56
+ else "<img src='/img/file.svg' alt='file' class='icon'>"
57
57
  end
58
58
  end
59
59
 
@@ -138,14 +138,14 @@ module Ginatra
138
138
  list = []
139
139
  diff.deltas.each_with_index do |delta, index|
140
140
  if delta.deleted?
141
- list << "<li class='deleted'><span class='icon-remove' title='deleted'></span> <a href='#file-#{index + 1}'>#{delta.new_file[:path]}</a></li>"
141
+ list << "<li class='deleted'><img src='/img/minus-square.svg' alt='deleted' class='icon'> <a href='#file-#{index + 1}'>#{delta.new_file[:path]}</a></li>"
142
142
  elsif delta.added?
143
- list << "<li class='added'><span class='icon-ok' title='added'></span> <a href='#file-#{index + 1}'>#{delta.new_file[:path]}</a></li>"
143
+ list << "<li class='added'><img src='/img/plus-square.svg' alt='added' class='icon'> <a href='#file-#{index + 1}'>#{delta.new_file[:path]}</a></li>"
144
144
  elsif delta.modified?
145
- list << "<li class='changed'><span class='icon-edit' title='modified'></span> <a href='#file-#{index + 1}'>#{delta.new_file[:path]}</a></li>"
145
+ list << "<li class='changed'><img src='/img/edit.svg' alt='modified' class='icon'> <a href='#file-#{index + 1}'>#{delta.new_file[:path]}</a></li>"
146
146
  end
147
147
  end
148
- "<ul class='unstyled'>#{list.join}</ul>"
148
+ "<ul class='list-unstyled'>#{list.join}</ul>"
149
149
  end
150
150
 
151
151
  # Highlights commit diff
@@ -0,0 +1,33 @@
1
+ require 'logger'
2
+ require 'fileutils'
3
+
4
+ module Ginatra
5
+ module Logger
6
+ def logger
7
+ Logger.logger
8
+ end
9
+
10
+ def self.logger
11
+ return @logger if @logger
12
+
13
+ if Ginatra.config.log_file
14
+ log_file = File.expand_path(Ginatra.config.log_file)
15
+ else
16
+ log_file = STDOUT
17
+ end
18
+
19
+ unless log_file == STDOUT
20
+ parent_dir, _separator, _filename = log_file.rpartition('/')
21
+ FileUtils.mkdir_p parent_dir
22
+ FileUtils.touch log_file
23
+ end
24
+
25
+ @logger = ::Logger.new log_file
26
+ @logger.level = ::Logger::WARN
27
+ @logger.formatter = proc do |severity, datetime, progname, msg|
28
+ "[#{datetime} ##{Process.pid}] #{severity}: #{msg}\n"
29
+ end
30
+ @logger
31
+ end
32
+ end
33
+ end
@@ -13,8 +13,11 @@ module Ginatra
13
13
  @repo = Rugged::Repository.new(path)
14
14
  @param = File.split(path).last
15
15
  @name = @param
16
- @description = File.read("#{@repo.path}description").strip
17
- @description = '' if @description.match(/\AUnnamed repository;/)
16
+ @description = ''
17
+ if File.exists?("#{@repo.path}description")
18
+ @description = File.read("#{@repo.path}description").strip
19
+ @description = '' if @description.match(/\AUnnamed repository;/)
20
+ end
18
21
  end
19
22
 
20
23
  # Return a commit corresponding to sha in the repo.
@@ -4,6 +4,7 @@ module Ginatra
4
4
  # A singleton class that lets us make and use a constantly updating
5
5
  # list of repositories.
6
6
  class RepoList
7
+ include Logger
7
8
  include Singleton
8
9
  attr_accessor :list
9
10
 
@@ -29,7 +30,7 @@ module Ginatra
29
30
  def refresh
30
31
  list.clear
31
32
 
32
- Ginatra.config.git_dirs.map do |git_dir|
33
+ Ginatra.load_config["git_dirs"].map do |git_dir|
33
34
  if Dir.exist?(git_dir.chop)
34
35
  dirs = Dir.glob(git_dir).sort
35
36
  else
@@ -55,6 +56,7 @@ module Ginatra
55
56
  begin
56
57
  list << Repo.new(path)
57
58
  rescue Rugged::RepositoryError
59
+ logger.warn "SKIPPING '#{path}' - not a git repository"
58
60
  end
59
61
  end
60
62
  list
@@ -1,4 +1,4 @@
1
1
  module Ginatra
2
- VERSION = "4.0.2"
3
- RELEASE_NAME = "Aurora"
2
+ VERSION = "4.1.0"
3
+ RELEASE_NAME = "Baku"
4
4
  end
@@ -1,6 +1,5 @@
1
1
  /*
2
- *= require ./lib/bootstrap.min
3
- *= require ./lib/bootstrap-responsive.min
2
+ *= require twbs
4
3
  *= require ./lib/highlight
5
4
  *= require custom
6
5
  */
@@ -1,13 +1,9 @@
1
- .push { padding-bottom: 40px; }
2
- footer p { margin: 10px 0; }
3
- .header { margin-top: 15px; box-shadow: none; }
4
- .filter { margin-top: -20px; }
1
+ .header { margin: 15px 0 -20px 0; }
2
+ .filter { margin-top: -10px; padding-bottom: 10px; }
5
3
  .author-box { padding-top: 10px; }
6
- #loader { margin-top: -20px; }
4
+ #loader { display:none; padding-bottom: 20px; }
7
5
  pre { white-space: pre; }
8
6
  .btn .caret { margin-left: 3px; }
9
- .btn-small .caret { margin-top: 8px; }
10
- .dropdown-menu { border-radius: 3px; }
11
7
  .img-rounded { border-radius: 4px; }
12
8
  .clone-hint { font-style: italic; }
13
9
  .dropdown-hint { padding: 3px 20px; }
@@ -16,11 +12,22 @@ pre { white-space: pre; }
16
12
  .highlight table td { padding: 0; }
17
13
  .highlight table .gutter { border-right: 1px solid #c0c0c0; }
18
14
 
15
+ .diff-files-list { display: none; }
16
+ .repo-list a { color: #337ab7; }
17
+ .repo-list a:hover, a:focus { color: #23527c; }
18
+ .nav { padding-bottom: 10px; }
19
+ .nav > li > a { padding: 7px 15px; }
20
+
19
21
  #diff { padding-top: 20px; }
20
22
  #diff .added a { color: #468847; }
21
23
  #diff .changed a { color: #3a87ad; }
22
24
  #diff .deleted a { color: #b94a48; }
23
25
 
26
+ .icon {
27
+ height: 16px;
28
+ width: 16px;
29
+ }
30
+
24
31
  .service-page {
25
32
  width: 50%;
26
33
  margin: 0 auto;
@@ -28,13 +35,6 @@ pre { white-space: pre; }
28
35
  padding-top: 10%;
29
36
  }
30
37
 
31
- .btn {
32
- text-shadow: none;
33
- background-image: none;
34
- border-radius: 3px;
35
- box-shadow: none;
36
- }
37
-
38
38
  .info-box {
39
39
  padding: 20px;
40
40
  background-color: #eee;
@@ -0,0 +1,8 @@
1
+ @import 'bootstrap-sprockets'
2
+ @import 'bootstrap'
3
+
4
+ h1, h2
5
+ font-weight: bold
6
+
7
+ small
8
+ font-weight: normal
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generated by IcoMoon.io -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="119" height="128" viewBox="0 0 119 128">
5
+ <path d="M105.857 75q3.286 1.857 4.25 5.536t-0.893 6.964l-4.571 7.857q-1.857 3.286-5.536 4.25t-6.964-0.893l-19-10.929v21.929q0 3.714-2.714 6.429t-6.429 2.714h-9.143q-3.714 0-6.429-2.714t-2.714-6.429v-21.929l-19 10.929q-3.286 1.857-6.964 0.893t-5.536-4.25l-4.571-7.857q-1.857-3.286-0.893-6.964t4.25-5.536l19-11-19-11q-3.286-1.857-4.25-5.536t0.893-6.964l4.571-7.857q1.857-3.286 5.536-4.25t6.964 0.893l19 10.929v-21.929q0-3.714 2.714-6.429t6.429-2.714h9.143q3.714 0 6.429 2.714t2.714 6.429v21.929l19-10.929q3.286-1.857 6.964-0.893t5.536 4.25l4.571 7.857q1.857 3.286 0.893 6.964t-4.25 5.536l-19 11z" fill="#444444"></path>
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generated by IcoMoon.io -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="119" height="128" viewBox="0 0 119 128">
5
+ <path d="M91.429 96q0-1.857-1.357-3.214t-3.214-1.357-3.214 1.357-1.357 3.214 1.357 3.214 3.214 1.357 3.214-1.357 1.357-3.214zM109.714 96q0-1.857-1.357-3.214t-3.214-1.357-3.214 1.357-1.357 3.214 1.357 3.214 3.214 1.357 3.214-1.357 1.357-3.214zM118.857 80v22.857q0 2.857-2 4.857t-4.857 2h-105.143q-2.857 0-4.857-2t-2-4.857v-22.857q0-2.857 2-4.857t4.857-2h33.214l9.643 9.714q4.143 4 9.714 4t9.714-4l9.714-9.714h33.143q2.857 0 4.857 2t2 4.857zM95.643 39.357q1.214 2.929-1 5l-32 32q-1.286 1.357-3.214 1.357t-3.214-1.357l-32-32q-2.214-2.071-1-5 1.214-2.786 4.214-2.786h18.286v-32q0-1.857 1.357-3.214t3.214-1.357h18.286q1.857 0 3.214 1.357t1.357 3.214v32h18.286q3 0 4.214 2.786z" fill="#444444"></path>
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generated by IcoMoon.io -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128" viewBox="0 0 128 128">
5
+ <path d="M63.429 84.571l8.286-8.286-10.857-10.857-8.286 8.286v4h6.857v6.857h4zM94.857 33.143q-1.143-1.143-2.357 0.071l-25 25q-1.214 1.214-0.071 2.357t2.357-0.071l25-25q1.214-1.214 0.071-2.357zM100.571 75.571v13.571q0 8.5-6.036 14.536t-14.536 6.036h-59.429q-8.5 0-14.536-6.036t-6.036-14.536v-59.429q0-8.5 6.036-14.536t14.536-6.036h59.429q4.5 0 8.357 1.786 1.071 0.5 1.286 1.643 0.214 1.214-0.643 2.071l-3.5 3.5q-1 1-2.286 0.571-1.643-0.429-3.214-0.429h-59.429q-4.714 0-8.071 3.357t-3.357 8.071v59.429q0 4.714 3.357 8.071t8.071 3.357h59.429q4.714 0 8.071-3.357t3.357-8.071v-9q0-0.929 0.643-1.571l4.571-4.571q1.071-1.071 2.5-0.5t1.429 2.071zM93.714 22.857l20.571 20.571-48 48h-20.571v-20.571zM125.429 32.286l-6.571 6.571-20.571-20.571 6.571-6.571q2-2 4.857-2t4.857 2l10.857 10.857q2 2 2 4.857t-2 4.857z" fill="#444444"></path>
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generated by IcoMoon.io -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128" viewBox="0 0 128 128">
5
+ <path d="M54.857 9.143q14.929 0 27.536 7.357t19.964 19.964 7.357 27.536-7.357 27.536-19.964 19.964-27.536 7.357-27.536-7.357-19.964-19.964-7.357-27.536 7.357-27.536 19.964-19.964 27.536-7.357zM64 98.214v-13.571q0-1-0.643-1.679t-1.571-0.679h-13.714q-0.929 0-1.643 0.714t-0.714 1.643v13.571q0 0.929 0.714 1.643t1.643 0.714h13.714q0.929 0 1.571-0.679t0.643-1.679zM63.857 73.643l1.286-44.357q0-0.857-0.714-1.286-0.714-0.571-1.714-0.571h-15.714q-1 0-1.714 0.571-0.714 0.429-0.714 1.286l1.214 44.357q0 0.714 0.714 1.25t1.714 0.536h13.214q1 0 1.679-0.536t0.75-1.25z" fill="#444444"></path>
6
+ </svg>