ginatra 4.0.2 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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>