diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a8da3de83f87ee327e84aa41c2fcb00753acb9f1..c23a7a3bf0ecd5615d8282a557349c1cdec2b2d1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,6 +12,7 @@ before_script:
 
 spec:feature:
   script:
+    - RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
     - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature
   tags:
     - ruby
diff --git a/.rubocop.yml b/.rubocop.yml
index b4ca11c83439517a461decd5de71dc98c88fd8c5..89aa0591c3135ce26db65e2ef769c74b2b0812ff 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -76,7 +76,7 @@ Style/BlockEndNewline:
   Description: 'Put end statement of multiline block on its own line.'
   Enabled: true
 
-Style/Blocks:
+Style/BlockDelimiters:
   Description: >-
                 Avoid using {...} for multi-line blocks (multiline chaining is
                 always ugly).
@@ -232,6 +232,10 @@ Style/EvenOdd:
   StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#predicate-methods'
   Enabled: false
 
+Style/ExtraSpacing:
+  Description: 'Do not use unnecessary spacing.'
+  Enabled: false
+
 Style/FileName:
   Description: 'Use snake_case for source file names.'
   StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#snake-case-files'
@@ -431,6 +435,14 @@ Style/OpMethod:
   StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg'
   Enabled: false
 
+Style/ParallelAssignment:
+  Description: >-
+                  Check for simple usages of parallel assignment.
+                  It will only warn when the number of variables
+                  matches on both sides of the assignment.
+  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#parallel-assignment'
+  Enabled: false
+
 Style/ParenthesesAroundCondition:
   Description: >-
                  Don't use parentheses around the condition of an
@@ -669,6 +681,13 @@ Style/TrailingWhitespace:
   StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace'
   Enabled: false
 
+Style/TrailingUnderscoreVariable:
+  Description: >-
+                 Checks for the usage of unneeded trailing underscores at the
+                 end of parallel variable assignment.
+  AllowNamedUnderscoreVariables: true
+  Enabled: false
+
 Style/TrivialAccessors:
   Description: 'Prefer attr_* methods to trivial readers/writers.'
   StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#attr_family'
@@ -690,11 +709,6 @@ Style/UnneededPercentQ:
   StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-q'
   Enabled: false
 
-Style/UnneededPercentX:
-  Description: 'Checks for %x when `` would do.'
-  StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#percent-x'
-  Enabled: false
-
 Style/VariableInterpolation:
   Description: >-
                  Don't interpolate global, instance and class variables
@@ -778,6 +792,10 @@ Metrics/MethodLength:
   StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods'
   Enabled: false
 
+Metrics/ModuleLength:
+  Description: 'Avoid modules longer than 100 lines of code.'
+  Enabled: false
+
 #################### Lint ################################
 ### Warnings
 
@@ -961,6 +979,12 @@ Rails/ActionFilter:
   Description: 'Enforces consistent use of action filter methods.'
   Enabled: true
 
+Rails/Date:
+  Description: >-
+                  Checks the correct usage of date aware methods,
+                  such as Date.today, Date.current etc.
+  Enabled: false
+
 Rails/DefaultScope:
   Description: 'Checks if the argument passed to default_scope is a block.'
   Enabled: false
@@ -987,6 +1011,12 @@ Rails/ScopeArgs:
   Description: 'Checks the arguments of ActiveRecord scopes.'
   Enabled: false
 
+Rails/TimeZone:
+  Description: 'Checks the correct usage of time zone aware methods.'
+  StyleGuide: 'https://github.com/bbatsov/rails-style-guide#time'
+  Reference: 'http://danilenko.org/2012/7/6/rails_timezones'
+  Enabled: false
+
 Rails/Validation:
   Description: 'Use validates :attribute, hash of validations.'
   Enabled: false
diff --git a/CHANGELOG b/CHANGELOG
index 7f9dfd98cd7a5659511e8869f0da9ea4938bd2c0..ea403642e322afaa83330de79e0f4a1d50980a36 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,11 +1,43 @@
 Please view this file on the master branch, on stable branches it's out of date.
 
-v 8.3.0 (unreleased)
+v 8.4.0 (unreleased)
+  - Implement new UI for group page
+  - Implement search inside emoji picker
+  - Add API support for looking up a user by username (Stan Hu)
+  - Add project permissions to all project API endpoints (Stan Hu)
+  - Only allow group/project members to mention `@all`
+  - Expose Git's version in the admin area (Trey Davis)
+  - Add "Frequently used" category to emoji picker
+  - Add CAS support (tduehr)
+  - Add link to merge request on build detail page
+  - Revert back upvote and downvote button to the issue and MR pages
+  - Swap position of Assignee and Author selector on Issuables (Zeger-Jan van de Weg)
+
+v 8.3.3 (unreleased)
+  - Fix project transfer e-mail sending incorrect paths in e-mail notification (Stan Hu)
+  - Enable "Add key" button when user fills in a proper key (Stan Hu)
+
+v 8.3.2
+  - Disable --follow in `git log` to avoid loading duplicate commit data in infinite scroll (Stan Hu)
+  - Add support for Google reCAPTCHA in user registration
+
+v 8.3.1
+  - Fix Error 500 when global milestones have slashes (Stan Hu)
+  - Fix Error 500 when doing a search in dashboard before visiting any project (Stan Hu)
+  - Fix LDAP identity and user retrieval when special characters are used
+  - Move Sidekiq-cron configuration to gitlab.yml
+  - Enable forcing Two-Factor authentication sitewide, with optional grace period
+
+v 8.3.0
+  - Bump rack-attack to 4.3.1 for security fix (Stan Hu)
+  - API support for starred projects for authorized user (Zeger-Jan van de Weg)
+  - Add open_issues_count to project API (Stan Hu)
   - Expand character set of usernames created by Omniauth (Corey Hinshaw)
   - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg)
-  - Merge when build succeeds (Zeger-Jan van de Weg)
   - Provide better diagnostic message upon project creation errors (Stan Hu)
   - Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu)
+  - Remove api credentials from link to build_page
+  - Deprecate GitLabCiService making it to always be inactive
   - Bump gollum-lib to 4.1.0 (Stan Hu)
   - Fix broken group avatar upload under "New group" (Stan Hu)
   - Update project repositorize size and commit count during import:repos task (Stan Hu)
@@ -17,13 +49,16 @@ v 8.3.0 (unreleased)
   - Fix 500 error when update group member permission
   - Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera)
   - Recognize issue/MR/snippet/commit links as references
+  - Backport JIRA features from EE to CE
   - Add ignore whitespace change option to commit view
   - Fire update hook from GitLab
+  - Allow account unlock via email
   - Style warning about mentioning many people in a comment
   - Fix: sort milestones by due date once again (Greg Smethells)
   - Migrate all CI::Services and CI::WebHooks to Services and WebHooks
   - Don't show project fork event as "imported"
   - Add API endpoint to fetch merge request commits list
+  - Don't create CI status for refs that doesn't have .gitlab-ci.yml, even if the builds are enabled
   - Expose events API with comment information and author info
   - Fix: Ensure "Remove Source Branch" button is not shown when branch is being deleted. #3583
   - Run custom Git hooks when branch is created or deleted.
@@ -62,8 +97,6 @@ v 8.2.3
   - Update documentation for "Guest" permissions
   - Properly convert Emoji-only comments into Award Emojis
   - Enable devise paranoid mode to prevent user enumeration attack
-
-v 8.2.3
   - Webhook payload has an added, modified and removed properties for each commit
   - Fix 500 error when creating a merge request that removes a submodule
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7ced7c57889557f6da23e60a3a7c7e29fdfa3000..b9c2b3d2f8e8242009998736c80c1303a90a2c9d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -155,6 +155,28 @@ sudo -u git -H bundle exec rake gitlab:env:info)
 
 ```
 
+### Issue weight
+
+Issue weight allows us to get an idea of the amount of work required to solve
+one or multiple issues. This makes it possible to schedule work more accurately.
+
+You are encouraged to set the weight of any issue. Following the guidelines
+below will make it easy to manage this, without unnecessary overhead.
+
+1. Set weight for any issue at the earliest possible convenience
+1. If you don't agree with a set weight, discuss with other developers until
+consensus is reached about the weight
+1. Issue weights are an abstract measurement of complexity of the issue. Do not
+relate issue weight directly to time. This is called [anchoring](https://en.wikipedia.org/wiki/Anchoring)
+and something you want to avoid.
+1. Something that has a weight of 1 (or no weight) is really small and simple.
+Something that is 9 is rewriting a large fundamental part of GitLab,
+which might lead to many hard problems to solve. Changing some text in GitLab
+is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
+1. If something is very large, it should probably be split up in multiple
+issues or chunks. You can simply not set the weight of a parent issue and set
+weights to children issues.
+
 ## Merge requests
 
 We welcome merge requests with fixes and improvements to GitLab code, tests,
@@ -358,7 +380,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
 [core team]: https://about.gitlab.com/core-team/
 [getting help page]: https://about.gitlab.com/getting-help/
 [Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
-[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up+for+grabs
+[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs
 [medium-up-for-grabs]: https://medium.com/@kentcdodds/first-timers-only-78281ea47455
 [ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
 [ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 743af5e1251c4fc79e10f34ef7c9f24b1367ab72..d48d3702aed9c6d03de90d13d12199015ce4740e 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-2.6.8
+2.6.9
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index 2b7c5ae01848a77d95e2792eb83ab605c9aed91a..4b9fcbec101a6ff8ec68e0f95131ccda4861407f 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-0.4.2
+0.5.1
diff --git a/Gemfile b/Gemfile
index 7298e21ce6634a165299c3badc79d50da785f633..2a1c4f7d73a0b2de1fb10c4c153772f4c2148ef4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -23,6 +23,7 @@ gem 'devise-async',           '~> 0.9.0'
 gem 'doorkeeper',             '~> 2.2.0'
 gem 'omniauth',               '~> 1.2.2'
 gem 'omniauth-bitbucket',     '~> 0.0.2'
+gem 'omniauth-cas3',          '~> 1.1.2'
 gem 'omniauth-facebook',      '~> 3.0.0'
 gem 'omniauth-github',        '~> 1.1.1'
 gem 'omniauth-gitlab',        '~> 1.0.0'
@@ -34,6 +35,9 @@ gem 'omniauth-twitter',       '~> 1.2.0'
 gem 'omniauth_crowd'
 gem 'rack-oauth2',            '~> 1.2.1'
 
+# reCAPTCHA protection
+gem 'recaptcha', require: 'recaptcha/rails'
+
 # Two-factor authentication
 gem 'devise-two-factor', '~> 2.0.0'
 gem 'rqrcode-rails3', '~> 0.1.7'
@@ -101,6 +105,9 @@ gem 'wikicloth',     '0.8.1'
 gem 'asciidoctor',   '~> 1.5.2'
 gem 'rouge',         '~> 1.10.1'
 
+# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
+gem 'nokogiri', '1.6.7.1'
+
 # Diffs
 gem 'diffy', '~> 3.0.3'
 
@@ -168,14 +175,14 @@ gem 'd3_rails', '~> 3.5.5'
 gem "cal-heatmap-rails", "~> 0.0.1"
 
 # underscore-rails
-gem "underscore-rails", "~> 1.4.4"
+gem "underscore-rails", "~> 1.8.0"
 
 # Sanitize user input
 gem "sanitize", '~> 2.0'
 gem 'babosa', '~> 1.0.2'
 
 # Protect against bruteforcing
-gem "rack-attack", '~> 4.3.0'
+gem "rack-attack", '~> 4.3.1'
 
 # Ace editor
 gem 'ace-rails-ap', '~> 2.0.1'
@@ -186,7 +193,7 @@ gem 'mousetrap-rails', '~> 1.4.6'
 # Detect and convert string character encoding
 gem 'charlock_holmes', '~> 0.7.3'
 
-gem "sass-rails", '~> 4.0.5'
+gem "sass-rails", '~> 5.0.0'
 gem "coffee-rails", '~> 4.1.0'
 gem "uglifier", '~> 2.7.2'
 gem 'turbolinks', '~> 2.5.0'
@@ -198,9 +205,9 @@ gem 'font-awesome-rails', '~> 4.2'
 gem 'gitlab_emoji',       '~> 0.2.0'
 gem 'gon',                '~> 6.0.1'
 gem 'jquery-atwho-rails', '~> 1.3.2'
-gem 'jquery-rails',       '~> 3.1.3'
+gem 'jquery-rails',       '~> 4.0.0'
 gem 'jquery-scrollto-rails', '~> 1.4.3'
-gem 'jquery-ui-rails',    '~> 4.2.1'
+gem 'jquery-ui-rails',    '~> 5.0.0'
 gem 'nprogress-rails',    '~> 0.1.6.7'
 gem 'raphael-rails',      '~> 2.1.2'
 gem 'request_store',      '~> 1.2.0'
@@ -208,14 +215,22 @@ gem 'select2-rails',      '~> 3.5.9'
 gem 'virtus',             '~> 1.0.1'
 gem 'net-ssh',            '~> 3.0.1'
 
+# Metrics
+group :metrics do
+  gem 'allocations', '~> 1.0', require: false, platform: :mri
+  gem 'method_source', '~> 0.8', require: false
+  gem 'influxdb', '~> 0.2', require: false
+  gem 'connection_pool', '~> 2.0', require: false
+end
+
 group :development do
   gem "foreman"
-  gem 'brakeman', '3.0.1', require: false
+  gem 'brakeman', '~> 3.1.0', require: false
 
   gem "annotate", "~> 2.6.0"
   gem "letter_opener", '~> 1.1.2'
   gem 'quiet_assets', '~> 1.0.2'
-  gem 'rerun', '~> 0.10.0'
+  gem 'rerun', '~> 0.11.0'
   gem 'bullet', require: false
   gem 'rblineprof', platform: :mri, require: false
   gem 'web-console', '~> 2.0'
@@ -251,7 +266,7 @@ group :development, :test do
 
   gem 'capybara',            '~> 2.4.0'
   gem 'capybara-screenshot', '~> 1.0.0'
-  gem 'poltergeist',         '~> 1.6.0'
+  gem 'poltergeist',         '~> 1.8.1'
 
   gem 'teaspoon', '~> 1.0.0'
   gem 'teaspoon-jasmine', '~> 2.2.0'
@@ -261,7 +276,7 @@ group :development, :test do
   gem 'spring-commands-spinach',  '~> 1.0.0'
   gem 'spring-commands-teaspoon', '~> 0.0.2'
 
-  gem 'rubocop',  '~> 0.28.0',  require: false
+  gem 'rubocop', '~> 0.35.0', require: false
   gem 'coveralls',  '~> 0.8.2', require: false
   gem 'simplecov', '~> 0.10.0', require: false
   gem 'flog', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index ff57460f5bb5f55e5156c7b1145ac658d23a5d21..9769ae80a7dfa84f11518c1a1f1e954f240e3c3f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -49,6 +49,7 @@ GEM
     addressable (2.3.8)
     after_commit_queue (1.3.0)
       activerecord (>= 3.0)
+    allocations (1.0.3)
     annotate (2.6.10)
       activerecord (>= 3.2, <= 4.3)
       rake (~> 10.4)
@@ -65,7 +66,7 @@ GEM
     attr_encrypted (1.3.4)
       encryptor (>= 1.3.0)
     attr_required (1.0.0)
-    autoprefixer-rails (6.1.1)
+    autoprefixer-rails (6.1.2)
       execjs
       json
     awesome_print (1.2.0)
@@ -84,15 +85,17 @@ GEM
     bootstrap-sass (3.3.5)
       autoprefixer-rails (>= 5.0.0.1)
       sass (>= 3.2.19)
-    brakeman (3.0.1)
+    brakeman (3.1.4)
       erubis (~> 2.6)
       fastercsv (~> 1.5)
       haml (>= 3.0, < 5.0)
-      highline (~> 1.6.20)
+      highline (>= 1.6.20, < 2.0)
       multi_json (~> 1.2)
-      ruby2ruby (~> 2.1.1)
-      ruby_parser (~> 3.5.0)
+      ruby2ruby (>= 2.1.1, < 2.3.0)
+      ruby_parser (~> 3.7.0)
+      safe_yaml (>= 1.0)
       sass (~> 3.0)
+      slim (>= 1.3.6, < 4.0)
       terminal-table (~> 1.4)
     browser (1.0.1)
     builder (3.2.2)
@@ -102,7 +105,7 @@ GEM
     bundler-audit (0.4.0)
       bundler (~> 1.2)
       thor (~> 0.18)
-    byebug (8.2.0)
+    byebug (8.2.1)
     cal-heatmap-rails (0.0.1)
     capybara (2.4.4)
       mime-types (>= 1.16)
@@ -117,23 +120,7 @@ GEM
       activemodel (>= 3.2.0)
       activesupport (>= 3.2.0)
       json (>= 1.7)
-    celluloid (0.17.2)
-      celluloid-essentials
-      celluloid-extras
-      celluloid-fsm
-      celluloid-pool
-      celluloid-supervision
-      timers (>= 4.1.1)
-    celluloid-essentials (0.20.5)
-      timers (>= 4.1.1)
-    celluloid-extras (0.20.5)
-      timers (>= 4.1.1)
-    celluloid-fsm (0.20.5)
-      timers (>= 4.1.1)
-    celluloid-pool (0.20.5)
-      timers (>= 4.1.1)
-    celluloid-supervision (0.20.5)
-      timers (>= 4.1.1)
+    cause (0.1)
     charlock_holmes (0.7.3)
     chunky_png (1.3.5)
     cliver (0.3.2)
@@ -157,10 +144,10 @@ GEM
       term-ansicolor (~> 1.3)
       thor (~> 0.19.1)
       tins (~> 1.6.0)
-    crack (0.4.2)
+    crack (0.4.3)
       safe_yaml (~> 1.0.0)
     creole (0.5.0)
-    d3_rails (3.5.6)
+    d3_rails (3.5.11)
       railties (>= 3.1.0)
     daemons (1.2.3)
     database_cleaner (1.4.1)
@@ -247,7 +234,7 @@ GEM
       ipaddress (~> 0.5)
       nokogiri (~> 1.5, >= 1.5.11)
       opennebula
-    fog-brightbox (0.9.0)
+    fog-brightbox (0.10.1)
       fog-core (~> 1.22)
       fog-json
       inflecto (~> 0.0.2)
@@ -266,7 +253,7 @@ GEM
       fog-core (>= 1.21.0)
       fog-json
       fog-xml (>= 0.0.1)
-    fog-sakuracloud (1.4.0)
+    fog-sakuracloud (1.5.0)
       fog-core
       fog-json
     fog-softlayer (1.0.2)
@@ -294,11 +281,11 @@ GEM
       ruby-progressbar (~> 1.4)
     gemnasium-gitlab-service (0.2.6)
       rugged (~> 0.21)
-    gemojione (2.1.0)
+    gemojione (2.1.1)
       json
     get_process_mem (0.2.0)
     gherkin-ruby (0.3.2)
-    github-linguist (4.7.2)
+    github-linguist (4.7.3)
       charlock_holmes (~> 0.7.3)
       escape_utils (~> 1.1.0)
       mime-types (>= 1.19)
@@ -315,7 +302,7 @@ GEM
       posix-spawn (~> 0.3)
     gitlab_emoji (0.2.0)
       gemojione (~> 2.1)
-    gitlab_git (7.2.21)
+    gitlab_git (7.2.22)
       activesupport (~> 4.0)
       charlock_holmes (~> 0.7.3)
       github-linguist (~> 4.7.0)
@@ -364,12 +351,11 @@ GEM
       html2haml (>= 1.0.1)
       railties (>= 4.0.1)
     hashie (3.4.3)
-    highline (1.6.21)
+    highline (1.7.8)
     hike (1.2.3)
     hipchat (1.5.2)
       httparty
       mimemagic
-    hitimes (1.2.3)
     html-pipeline (1.11.0)
       activesupport (>= 2)
       nokogiri (~> 1.4)
@@ -388,17 +374,21 @@ GEM
     i18n (0.7.0)
     ice_nine (0.11.1)
     inflecto (0.0.2)
+    influxdb (0.2.3)
+      cause
+      json
     ipaddress (0.8.0)
     jquery-atwho-rails (1.3.2)
-    jquery-rails (3.1.4)
-      railties (>= 3.0, < 5.0)
+    jquery-rails (4.0.5)
+      rails-dom-testing (~> 1.0)
+      railties (>= 4.2.0)
       thor (>= 0.14, < 2.0)
     jquery-scrollto-rails (1.4.3)
       railties (> 3.1, < 5.0)
     jquery-turbolinks (2.1.0)
       railties (>= 3.1.0)
       turbolinks
-    jquery-ui-rails (4.2.1)
+    jquery-ui-rails (5.0.5)
       railties (>= 3.2.16)
     json (1.8.3)
     jwt (1.5.2)
@@ -410,8 +400,7 @@ GEM
       addressable (~> 2.3)
     letter_opener (1.1.2)
       launchy (~> 2.2)
-    listen (2.9.0)
-      celluloid (>= 0.15.2)
+    listen (3.0.5)
       rb-fsevent (>= 0.9.3)
       rb-inotify (>= 0.9)
     loofah (2.0.3)
@@ -424,7 +413,7 @@ GEM
     method_source (0.8.2)
     mime-types (1.25.1)
     mimemagic (0.3.0)
-    mini_portile (0.6.2)
+    mini_portile2 (2.0.0)
     minitest (5.7.0)
     mousetrap-rails (1.4.6)
     multi_json (1.11.2)
@@ -435,12 +424,12 @@ GEM
     net-ldap (0.12.1)
     net-ssh (3.0.1)
     netrc (0.11.0)
-    newrelic-grape (2.0.0)
+    newrelic-grape (2.1.0)
       grape
       newrelic_rpm
     newrelic_rpm (3.9.4.245)
-    nokogiri (1.6.6.4)
-      mini_portile (~> 0.6.0)
+    nokogiri (1.6.7.1)
+      mini_portile2 (~> 2.0.0.rc2)
     nprogress-rails (0.1.6.7)
     oauth (0.4.7)
     oauth2 (1.0.0)
@@ -458,6 +447,10 @@ GEM
       multi_json (~> 1.7)
       omniauth (~> 1.1)
       omniauth-oauth (~> 1.0)
+    omniauth-cas3 (1.1.3)
+      addressable (~> 2.3)
+      nokogiri (~> 1.6.6)
+      omniauth (~> 1.2)
     omniauth-facebook (3.0.0)
       omniauth-oauth2 (~> 1.2)
     omniauth-github (1.1.2)
@@ -507,13 +500,13 @@ GEM
     parser (2.2.3.0)
       ast (>= 1.1, < 3.0)
     pg (0.18.4)
-    poltergeist (1.6.0)
+    poltergeist (1.8.1)
       capybara (~> 2.1)
       cliver (~> 0.3.1)
       multi_json (~> 1.0)
       websocket-driver (>= 0.2.0)
     posix-spawn (0.3.11)
-    powerpack (0.0.9)
+    powerpack (0.1.1)
     pry (0.10.3)
       coderay (~> 1.1.0)
       method_source (~> 0.8.1)
@@ -526,7 +519,7 @@ GEM
     rack (1.6.4)
     rack-accept (0.4.5)
       rack (>= 0.4)
-    rack-attack (4.3.0)
+    rack-attack (4.3.1)
       rack
     rack-cors (0.4.0)
     rack-mount (0.8.3)
@@ -580,6 +573,8 @@ GEM
       trollop
     rdoc (3.12.2)
       json (~> 1.4)
+    recaptcha (1.0.2)
+      json
     redcarpet (3.3.3)
     redis (3.2.2)
     redis-actionpack (4.0.1)
@@ -601,8 +596,8 @@ GEM
     redis-store (1.1.7)
       redis (>= 2.2)
     request_store (1.2.1)
-    rerun (0.10.0)
-      listen (~> 2.7, >= 2.7.3)
+    rerun (0.11.0)
+      listen (~> 3.0)
     responders (2.1.0)
       railties (>= 4.2.0, < 5)
     rest-client (1.8.0)
@@ -637,22 +632,23 @@ GEM
       rspec-mocks (~> 3.3.0)
       rspec-support (~> 3.3.0)
     rspec-support (3.3.0)
-    rubocop (0.28.0)
+    rubocop (0.35.1)
       astrolabe (~> 1.3)
-      parser (>= 2.2.0.pre.7, < 3.0)
-      powerpack (~> 0.0.6)
+      parser (>= 2.2.3.0, < 3.0)
+      powerpack (~> 0.1)
       rainbow (>= 1.99.1, < 3.0)
-      ruby-progressbar (~> 1.4)
+      ruby-progressbar (~> 1.7)
+      tins (<= 1.6.0)
     ruby-fogbugz (0.2.1)
       crack (~> 0.4)
     ruby-progressbar (1.7.5)
     ruby-saml (1.0.0)
       nokogiri (>= 1.5.10)
       uuid (~> 2.3)
-    ruby2ruby (2.1.4)
+    ruby2ruby (2.2.0)
       ruby_parser (~> 3.1)
       sexp_processor (~> 4.0)
-    ruby_parser (3.5.0)
+    ruby_parser (3.7.2)
       sexp_processor (~> 4.1)
     rubyntlm (0.5.2)
     rubypants (0.2.0)
@@ -661,12 +657,13 @@ GEM
     safe_yaml (1.0.4)
     sanitize (2.1.0)
       nokogiri (>= 1.4.4)
-    sass (3.2.19)
-    sass-rails (4.0.5)
+    sass (3.4.20)
+    sass-rails (5.0.4)
       railties (>= 4.0.0, < 5.0)
-      sass (~> 3.2.2)
-      sprockets (~> 2.8, < 3.0)
-      sprockets-rails (~> 2.0)
+      sass (~> 3.1)
+      sprockets (>= 2.8, < 4.0)
+      sprockets-rails (>= 2.0, < 4.0)
+      tilt (>= 1.1, < 3)
     sawyer (0.6.0)
       addressable (~> 2.3.5)
       faraday (~> 0.8, < 0.10)
@@ -705,6 +702,9 @@ GEM
       tilt (>= 1.3, < 3)
     six (0.2.0)
     slack-notifier (1.2.1)
+    slim (3.0.6)
+      temple (~> 0.7.3)
+      tilt (>= 1.3.3, < 2.1)
     slop (3.6.0)
     spinach (0.8.10)
       colorize
@@ -746,6 +746,7 @@ GEM
       railties (>= 3.2.5, < 5)
     teaspoon-jasmine (2.2.0)
       teaspoon (>= 1.0.0)
+    temple (0.7.6)
     term-ansicolor (1.3.2)
       tins (~> 1.0)
     terminal-table (1.5.2)
@@ -758,8 +759,6 @@ GEM
     thor (0.19.1)
     thread_safe (0.3.5)
     tilt (1.4.1)
-    timers (4.1.1)
-      hitimes
     timfel-krb5-auth (0.8.3)
     tinder (1.10.1)
       eventmachine (~> 1.0)
@@ -783,7 +782,7 @@ GEM
     uglifier (2.7.2)
       execjs (>= 0.3.0)
       json (>= 1.8.0)
-    underscore-rails (1.4.4)
+    underscore-rails (1.8.3)
     unf (0.1.4)
       unf_ext
     unf_ext (0.0.7.1)
@@ -803,7 +802,7 @@ GEM
       coercible (~> 1.0)
       descendants_tracker (~> 0.0, >= 0.0.3)
       equalizer (~> 0.0, >= 0.0.9)
-    warden (1.2.3)
+    warden (1.2.4)
       rack (>= 1.0)
     web-console (2.2.1)
       activemodel (>= 4.0)
@@ -834,6 +833,7 @@ DEPENDENCIES
   acts-as-taggable-on (~> 3.4)
   addressable (~> 2.3.8)
   after_commit_queue
+  allocations (~> 1.0)
   annotate (~> 2.6.0)
   asana (~> 0.4.0)
   asciidoctor (~> 1.5.2)
@@ -844,7 +844,7 @@ DEPENDENCIES
   better_errors (~> 1.0.1)
   binding_of_caller (~> 0.7.2)
   bootstrap-sass (~> 3.0)
-  brakeman (= 3.0.1)
+  brakeman (~> 3.1.0)
   browser (~> 1.0.0)
   bullet
   bundler-audit
@@ -856,6 +856,7 @@ DEPENDENCIES
   charlock_holmes (~> 0.7.3)
   coffee-rails (~> 4.1.0)
   colorize (~> 0.7.0)
+  connection_pool (~> 2.0)
   coveralls (~> 0.8.2)
   creole (~> 0.5.0)
   d3_rails (~> 3.5.5)
@@ -893,14 +894,16 @@ DEPENDENCIES
   hipchat (~> 1.5.0)
   html-pipeline (~> 1.11.0)
   httparty (~> 0.13.3)
+  influxdb (~> 0.2)
   jquery-atwho-rails (~> 1.3.2)
-  jquery-rails (~> 3.1.3)
+  jquery-rails (~> 4.0.0)
   jquery-scrollto-rails (~> 1.4.3)
   jquery-turbolinks (~> 2.1.0)
-  jquery-ui-rails (~> 4.2.1)
+  jquery-ui-rails (~> 5.0.0)
   kaminari (~> 0.16.3)
   letter_opener (~> 1.1.2)
   mail_room (~> 0.6.1)
+  method_source (~> 0.8)
   minitest (~> 5.7.0)
   mousetrap-rails (~> 1.4.6)
   mysql2 (~> 0.3.16)
@@ -908,11 +911,13 @@ DEPENDENCIES
   net-ssh (~> 3.0.1)
   newrelic-grape
   newrelic_rpm (~> 3.9.4.245)
+  nokogiri (= 1.6.7.1)
   nprogress-rails (~> 0.1.6.7)
   oauth2 (~> 1.0.0)
   octokit (~> 3.7.0)
   omniauth (~> 1.2.2)
   omniauth-bitbucket (~> 0.0.2)
+  omniauth-cas3 (~> 1.1.2)
   omniauth-facebook (~> 3.0.0)
   omniauth-github (~> 1.1.1)
   omniauth-gitlab (~> 1.0.0)
@@ -925,10 +930,10 @@ DEPENDENCIES
   org-ruby (~> 0.9.12)
   paranoia (~> 2.0)
   pg (~> 0.18.2)
-  poltergeist (~> 1.6.0)
+  poltergeist (~> 1.8.1)
   pry-rails
   quiet_assets (~> 1.0.2)
-  rack-attack (~> 4.3.0)
+  rack-attack (~> 4.3.1)
   rack-cors (~> 0.4.0)
   rack-oauth2 (~> 1.2.1)
   rails (= 4.2.4)
@@ -936,19 +941,20 @@ DEPENDENCIES
   raphael-rails (~> 2.1.2)
   rblineprof
   rdoc (~> 3.6)
+  recaptcha
   redcarpet (~> 3.3.3)
   redis-namespace
   redis-rails (~> 4.0.0)
   request_store (~> 1.2.0)
-  rerun (~> 0.10.0)
+  rerun (~> 0.11.0)
   responders (~> 2.0)
   rouge (~> 1.10.1)
   rqrcode-rails3 (~> 0.1.7)
   rspec-rails (~> 3.3.0)
-  rubocop (~> 0.28.0)
+  rubocop (~> 0.35.0)
   ruby-fogbugz (~> 0.2.1)
   sanitize (~> 2.0)
-  sass-rails (~> 4.0.5)
+  sass-rails (~> 5.0.0)
   sdoc (~> 0.3.20)
   seed-fu (~> 2.3.5)
   select2-rails (~> 3.5.9)
@@ -977,7 +983,7 @@ DEPENDENCIES
   tinder (~> 1.10.0)
   turbolinks (~> 2.5.0)
   uglifier (~> 2.7.2)
-  underscore-rails (~> 1.4.4)
+  underscore-rails (~> 1.8.0)
   unf (~> 0.1.4)
   unicorn (~> 4.8.2)
   unicorn-worker-killer (~> 0.4.2)
diff --git a/VERSION b/VERSION
index 8d0676ff07ba5372063bb36af9529a8d976c16ad..ce669730119df83f8d693ec9e7401baf55b9245a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-8.3.0.pre
+8.4.0.pre
diff --git a/app/assets/images/brand_logo.png b/app/assets/images/brand_logo.png
deleted file mode 100644
index 9c564bb61411bf4f0dec3e21aa86848ac70cbcb8..0000000000000000000000000000000000000000
Binary files a/app/assets/images/brand_logo.png and /dev/null differ
diff --git a/app/assets/images/emoji.png b/app/assets/images/emoji.png
new file mode 100644
index 0000000000000000000000000000000000000000..a8ad7b6eab612af71df106bf8ac26541a92fe217
Binary files /dev/null and b/app/assets/images/emoji.png differ
diff --git a/app/assets/images/gitlab_logo.png b/app/assets/images/gitlab_logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c157546b9cf87d9aaf9a404c01f8a623f7c24c7
Binary files /dev/null and b/app/assets/images/gitlab_logo.png differ
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 1539eba0faa9e0ad0bb136cca26533492669c3e0..affab5bb030d8c72eba0fb7295f700cca0aecf1a 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -5,7 +5,7 @@
 # the compiled file.
 #
 #= require jquery
-#= require jquery.ui.all
+#= require jquery-ui
 #= require jquery_ujs
 #= require jquery.cookie
 #= require jquery.endless-scroll
diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee
index 3ff9ba77dfc7fd77187b66aacfdaf73877f6390b..619abb1fb071367785e20e80b975d8c4199a8af4 100644
--- a/app/assets/javascripts/awards_handler.coffee
+++ b/app/assets/javascripts/awards_handler.coffee
@@ -1,12 +1,28 @@
 class @AwardsHandler
   constructor: (@post_emoji_url, @noteable_type, @noteable_id, @aliases) ->
+    $(".add-award").click (event)->
+      event.stopPropagation()
+      event.preventDefault()
+      $(".emoji-menu").show()
+
+    $("html").click ->
+      if !$(event.target).closest(".emoji-menu").length
+        if $(".emoji-menu").is(":visible")
+          $(".emoji-menu").hide()
+
+    @renderFrequentlyUsedBlock()
+    @setupSearch()
 
   addAward: (emoji) ->
     emoji = @normilizeEmojiName(emoji)
     @postEmoji emoji, =>
       @addAwardToEmojiBar(emoji)
+
+    $(".emoji-menu").hide()
     
-  addAwardToEmojiBar: (emoji, custom_path = '') ->
+  addAwardToEmojiBar: (emoji) ->
+    @addEmojiToFrequentlyUsedList(emoji)
+
     emoji = @normilizeEmojiName(emoji)
     if @exist(emoji)
       if @isActive(emoji)
@@ -17,7 +33,7 @@ class @AwardsHandler
         counter.parent().addClass("active")
         @addMeToAuthorList(emoji)
     else
-      @createEmoji(emoji, custom_path)
+      @createEmoji(emoji)
 
   exist: (emoji) ->
     @findEmojiIcon(emoji).length > 0
@@ -27,15 +43,19 @@ class @AwardsHandler
 
   decrementCounter: (emoji) ->
     counter = @findEmojiIcon(emoji).siblings(".counter")
+    emojiIcon = counter.parent()
 
     if parseInt(counter.text()) > 1
       counter.text(parseInt(counter.text()) - 1)
-      counter.parent().removeClass("active")
+      emojiIcon.removeClass("active")
       @removeMeFromAuthorList(emoji)
+    else if emoji =="thumbsup" || emoji == "thumbsdown"
+      emojiIcon.tooltip("destroy")
+      counter.text(0)
+      emojiIcon.removeClass("active")
     else
-      award = counter.parent()
-      award.tooltip("destroy")
-      award.remove()
+      emojiIcon.tooltip("destroy")
+      emojiIcon.remove()
 
   removeMeFromAuthorList: (emoji) ->
     award_block = @findEmojiIcon(emoji).parent()
@@ -54,35 +74,39 @@ class @AwardsHandler
   resetTooltip: (award) ->
     award.tooltip("destroy")
 
-    # "destroy" call is asynchronous, this is why we need to set timeout.
+    # "destroy" call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout.
     setTimeout (->
       award.tooltip()
     ), 200
     
 
-  createEmoji: (emoji, custom_path) ->
+  createEmoji: (emoji) ->
+    emojiCssClass = @resolveNameToCssClass(emoji)
+
     nodes = []
     nodes.push("<div class='award active' title='me'>")
-    nodes.push("<div class='icon' data-emoji='" + emoji + "'>")
-    nodes.push(@getImage(emoji, custom_path))
+    nodes.push("<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>")
+    nodes.push("<div class='counter'>1</div>")
     nodes.push("</div>")
-    nodes.push("<div class='counter'>1")
-    nodes.push("</div></div>")
 
-    $(".awards-controls").before(nodes.join("\n"))
+    emoji_node = $(nodes.join("\n")).insertBefore(".awards-controls").find(".emoji-icon").data("emoji", emoji)
 
     $(".award").tooltip()
 
-  getImage: (emoji, custom_path) ->
-    if custom_path
-      $("<img>").attr({src: custom_path, width: 20, height: 20}).wrap("<div>").parent().html()
+  resolveNameToCssClass: (emoji) ->
+    emoji_icon = $(".emoji-menu-content [data-emoji='#{emoji}']")
+
+    if emoji_icon.length > 0
+      unicodeName = emoji_icon.data("unicode-name")
     else
-      $("li[data-emoji='" + emoji + "']").html()
+      # Find by alias
+      unicodeName = $(".emoji-menu-content [data-aliases*=':#{emoji}:']").data("unicode-name")
 
+    "emoji-#{unicodeName}"
 
   postEmoji: (emoji, callback) ->
     $.post @post_emoji_url, { note: {
-      note: ":" + emoji + ":"
+      note: ":#{emoji}:"
       noteable_type: @noteable_type
       noteable_id: @noteable_id
     }},(data) ->
@@ -90,7 +114,7 @@ class @AwardsHandler
         callback.call()
 
   findEmojiIcon: (emoji) ->
-    $(".icon[data-emoji='" + emoji + "']")
+    $(".award [data-emoji='#{emoji}']")
 
   scrollToAwards: ->
     $('body, html').animate({
@@ -99,3 +123,44 @@ class @AwardsHandler
 
   normilizeEmojiName: (emoji) ->
     @aliases[emoji] || emoji
+
+  addEmojiToFrequentlyUsedList: (emoji) ->
+    frequently_used_emojis = @getFrequentlyUsedEmojis()
+    frequently_used_emojis.push(emoji)
+    $.cookie('frequently_used_emojis', frequently_used_emojis.join(","), { expires: 365 })
+
+  getFrequentlyUsedEmojis: ->
+    frequently_used_emojis = ($.cookie('frequently_used_emojis') || "").split(",")
+    _.compact(_.uniq(frequently_used_emojis))
+
+  renderFrequentlyUsedBlock: ->
+    if $.cookie('frequently_used_emojis')
+      frequently_used_emojis = @getFrequentlyUsedEmojis()
+
+      ul = $("<ul>")
+
+      for emoji in frequently_used_emojis
+        do (emoji) ->
+          $(".emoji-menu-content [data-emoji='#{emoji}']").closest("li").clone().appendTo(ul)
+
+      $("input.emoji-search").after(ul).after($("<h5>").text("Frequently used"))
+
+  setupSearch: ->
+    $("input.emoji-search").keyup (ev) =>
+      term = $(ev.target).val()
+
+      # Clean previous search results
+      $("ul.emoji-search,h5.emoji-search").remove()
+
+      if term
+        # Generate a search result block
+        h5 = $("<h5>").text("Search results").addClass("emoji-search")
+        found_emojis = @searchEmojis(term).show()
+        ul = $("<ul>").addClass("emoji-search").append(found_emojis)
+        $(".emoji-menu-content ul, .emoji-menu-content h5").hide()
+        $(".emoji-menu-content").append(h5).append(ul)
+      else
+        $(".emoji-menu-content").children().show()
+
+  searchEmojis: (term)->
+    $(".emoji-menu-content [data-emoji*='#{term}']").closest("li").clone()
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee
index 195f8b11e5dbac896379cd30d13f3caa3532e130..9df932817f6aa785360c5b0a973f3d3895369be7 100644
--- a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee
+++ b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee
@@ -35,7 +35,7 @@ class @BlobFileDropzone
           return
 
         this.on 'sending', (file, xhr, formData) ->
-          formData.append('new_branch', form.find('.js-new-branch').val())
+          formData.append('target_branch', form.find('.js-target-branch').val())
           formData.append('create_merge_request', form.find('.js-create-merge-request').val())
           formData.append('commit_message', form.find('.js-commit-message').val())
           return
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index 599b4c4954001823ebd5a7a77a01bac97069b28e..69e061ce6e927813b489eea7eee06ac7c29e8c4a 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -49,7 +49,7 @@ class Dispatcher
         new DropzoneInput($('.release-form'))
       when 'projects:merge_requests:show'
         new Diff()
-        shortcut_handler = new ShortcutsIssuable()
+        shortcut_handler = new ShortcutsIssuable(true)
         new ZenMode()
       when "projects:merge_requests:diffs"
         new Diff()
diff --git a/app/assets/javascripts/issuable_context.js.coffee b/app/assets/javascripts/issuable_context.js.coffee
index 01bd515cc0215c43f21b7b7fe2432d6946096807..02232698bc20ea522d4a47c414b691b496092d24 100644
--- a/app/assets/javascripts/issuable_context.js.coffee
+++ b/app/assets/javascripts/issuable_context.js.coffee
@@ -18,7 +18,7 @@ class @IssuableContext
 
       $('.issuable-affix').affix offset:
         top: ->
-          @top = ($('.issuable-affix').offset().top - 60)
+          @top = ($('.issuable-affix').offset().top - 70)
         bottom: ->
           @bottom = $('.footer').outerHeight(true)
 
diff --git a/app/assets/javascripts/issue.js.coffee b/app/assets/javascripts/issue.js.coffee
index 603a16da1ce645d51f2958fa68437e91653ebb65..c256ec8f41bb178189c5e39ce1a589d312a05dd8 100644
--- a/app/assets/javascripts/issue.js.coffee
+++ b/app/assets/javascripts/issue.js.coffee
@@ -1,3 +1,4 @@
+#= require flash
 #= require jquery.waitforimages
 #= require task_list
 
@@ -6,16 +7,47 @@ class @Issue
     # Prevent duplicate event bindings
     @disableTaskList()
 
-    if $("a.btn-close").length
+    if $('a.btn-close').length
       @initTaskList()
+      @initIssueBtnEventListeners()
 
   initTaskList: ->
-    $('.issue-details .js-task-list-container').taskList('enable')
-    $(document).on 'tasklist:changed', '.issue-details .js-task-list-container', @updateTaskList
+    $('.detail-page-description .js-task-list-container').taskList('enable')
+    $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
+
+  initIssueBtnEventListeners: ->
+    issueFailMessage = 'Unable to update this issue at this time.'
+    $('a.btn-close, a.btn-reopen').on 'click', (e) ->
+      e.preventDefault()
+      e.stopImmediatePropagation()
+      $this = $(this)
+      isClose = $this.hasClass('btn-close')
+      $this.prop('disabled', true)
+      url = $this.attr('href')
+      $.ajax
+        type: 'PUT'
+        url: url,
+        error: (jqXHR, textStatus, errorThrown) ->
+          issueStatus = if isClose then 'close' else 'open'
+          new Flash(issueFailMessage, 'alert')
+        success: (data, textStatus, jqXHR) ->
+          if data.saved
+            $this.addClass('hidden')
+            if isClose
+              $('a.btn-reopen').removeClass('hidden')
+              $('div.status-box-closed').removeClass('hidden')
+              $('div.status-box-open').addClass('hidden')
+            else
+              $('a.btn-close').removeClass('hidden')
+              $('div.status-box-closed').addClass('hidden')
+              $('div.status-box-open').removeClass('hidden')
+          else
+            new Flash(issueFailMessage, 'alert')
+          $this.prop('disabled', false)
 
   disableTaskList: ->
-    $('.issue-details .js-task-list-container').taskList('disable')
-    $(document).off 'tasklist:changed', '.issue-details .js-task-list-container'
+    $('.detail-page-description .js-task-list-container').taskList('disable')
+    $(document).off 'tasklist:changed', '.detail-page-description .js-task-list-container'
 
   # TODO (rspeicher): Make the issue description inline-editable like a note so
   # that we can re-use its form here
diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee
index b21cb7904b56fdd99739d81c6458ce556af6b414..9047587db81af96a3aeca6a6451b64851a3cd4ba 100644
--- a/app/assets/javascripts/merge_request.js.coffee
+++ b/app/assets/javascripts/merge_request.js.coffee
@@ -40,12 +40,12 @@ class @MergeRequest
     this.$('.all-commits').removeClass 'hide'
 
   initTaskList: ->
-    $('.merge-request-details .js-task-list-container').taskList('enable')
-    $(document).on 'tasklist:changed', '.merge-request-details .js-task-list-container', @updateTaskList
+    $('.detail-page-description .js-task-list-container').taskList('enable')
+    $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
 
   disableTaskList: ->
-    $('.merge-request-details .js-task-list-container').taskList('disable')
-    $(document).off 'tasklist:changed', '.merge-request-details .js-task-list-container'
+    $('.detail-page-description .js-task-list-container').taskList('disable')
+    $(document).off 'tasklist:changed', '.detail-page-description .js-task-list-container'
 
   # TODO (rspeicher): Make the merge request description inline-editable like a
   # note so that we can re-use its form here
diff --git a/app/assets/javascripts/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee
index c4b63966fe77e590ce114d5968fe94bafea36db5..738ffc8343bfd34437915c56f7148ec2cbc8f5cc 100644
--- a/app/assets/javascripts/merge_request_widget.js.coffee
+++ b/app/assets/javascripts/merge_request_widget.js.coffee
@@ -18,7 +18,7 @@ class @MergeRequestWidget
         if data.state == "merged"
           urlSuffix = if deleteSourceBranch then '?delete_source=true' else ''
 
-          window.location.href = window.location.href + urlSuffix
+          window.location.href = window.location.pathname + urlSuffix
         else if data.merge_error
           $('.mr-widget-body').html("<h4>" + data.merge_error + "</h4>")
         else
diff --git a/app/assets/javascripts/new_branch_form.js.coffee b/app/assets/javascripts/new_branch_form.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..4b350854f7855d438dc3a06d6c5ce202c9ed91af
--- /dev/null
+++ b/app/assets/javascripts/new_branch_form.js.coffee
@@ -0,0 +1,78 @@
+class @NewBranchForm
+  constructor: (form, availableRefs) ->
+    @branchNameError = form.find('.js-branch-name-error')
+    @name = form.find('.js-branch-name')
+    @ref  = form.find('#ref')
+
+    @setupAvailableRefs(availableRefs)
+    @setupRestrictions()
+    @addBinding()
+    @init()
+
+  addBinding: ->
+    @name.on 'blur', @validate
+
+  init: ->
+    @name.trigger 'blur' if @name.val().length > 0
+
+  setupAvailableRefs: (availableRefs) ->
+    @ref.autocomplete
+      source: availableRefs,
+      minLength: 1
+
+  setupRestrictions: ->
+    startsWith = {
+      pattern: /^(\/|\.)/g,
+      prefix: "can't start with",
+      conjunction: "or"
+    }
+
+    endsWith = {
+      pattern: /(\/|\.|\.lock)$/g,
+      prefix: "can't end in",
+      conjunction: "or"
+    }
+
+    invalid = {
+      pattern: /(\s|~|\^|:|\?|\*|\[|\\|\.\.|@\{|\/{2,}){1}/g
+      prefix: "can't contain",
+      conjunction: ", "
+    }
+
+    single = {
+      pattern: /^@+$/g
+      prefix: "can't be",
+      conjunction: "or"
+    }
+
+    @restrictions = [startsWith, invalid, endsWith, single]
+
+  validate: =>
+    @branchNameError.empty()
+
+    unique = (values, value) ->
+      values.push(value) unless value in values
+      values
+
+    formatter = (values, restriction) ->
+      formatted = values.map (value) ->
+        switch
+          when /\s/.test value then 'spaces'
+          when /\/{2,}/g.test value then 'consecutive slashes'
+          else "'#{value}'"
+
+      "#{restriction.prefix} #{formatted.join(restriction.conjunction)}"
+
+    validator = (errors, restriction) =>
+      matched = @name.val().match(restriction.pattern)
+
+      if matched
+        errors.concat formatter(matched.reduce(unique, []), restriction)
+      else
+        errors
+
+    errors = @restrictions.reduce validator, []
+
+    if errors.length > 0
+      errorMessage = $("<span/>").text(errors.join(', '))
+      @branchNameError.append(errorMessage)
diff --git a/app/assets/javascripts/new_commit_form.js.coffee b/app/assets/javascripts/new_commit_form.js.coffee
index 3c7b776155fb2929da92df64237075e0bff6bc52..03f0f51acfad536ba0927ceaf5541f774796e0dd 100644
--- a/app/assets/javascripts/new_commit_form.js.coffee
+++ b/app/assets/javascripts/new_commit_form.js.coffee
@@ -1,6 +1,6 @@
 class @NewCommitForm
   constructor: (form) ->
-    @newBranch = form.find('.js-new-branch')
+    @newBranch = form.find('.js-target-branch')
     @originalBranch = form.find('.js-original-branch')
     @createMergeRequest = form.find('.js-create-merge-request')
     @createMergeRequestContainer = form.find('.js-create-merge-request-container')
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index 35dc7829da2d95571c8a7b41797709115a206f25..9e5204bfeebb7b474ad935e64a3eb59e46d2daa2 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -127,7 +127,7 @@ class @Notes
       @initTaskList()
 
     if note.award
-      awards_handler.addAwardToEmojiBar(note.note, note.emoji_path)
+      awards_handler.addAwardToEmojiBar(note.note)
       awards_handler.scrollToAwards()
 
   ###
diff --git a/app/assets/javascripts/project.js.coffee b/app/assets/javascripts/project.js.coffee
index 1f221945c062668955f838add7ab4c034933c681..d7a658f8faa4dd0ce23db69fef1de40d01ec137b 100644
--- a/app/assets/javascripts/project.js.coffee
+++ b/app/assets/javascripts/project.js.coffee
@@ -1,7 +1,7 @@
 class @Project
   constructor: ->
     # Git protocol switcher
-    $('.js-protocol-switch').click ->
+    $('ul.clone-options-dropdown a').click ->
       return if $(@).hasClass('active')
 
 
@@ -10,7 +10,8 @@ class @Project
       # Add the active class for the clicked button
       $(@).toggleClass('active')
 
-      url = $(@).data('clone')
+      url = $("#project_clone").val()
+      console.log("url",url)
 
       # Update the input field
       $('#project_clone').val(url)
diff --git a/app/assets/javascripts/projects_list.js.coffee b/app/assets/javascripts/projects_list.js.coffee
index db5faf71faf79461144bdd260d9bb3adbf380c0b..f2887af190bc5a9e4093786822c0e51138a881e1 100644
--- a/app/assets/javascripts/projects_list.js.coffee
+++ b/app/assets/javascripts/projects_list.js.coffee
@@ -8,17 +8,17 @@ class @ProjectsList
 
     $(".projects-list-filter").keyup ->
       terms = $(this).val()
-      uiBox = $(this).closest('.projects-list-holder')
+      uiBox = $('div.projects-list-holder')
       if terms == "" || terms == undefined
-        uiBox.find(".projects-list li").show()
+        uiBox.find("ul.projects-list li").show()
       else
-        uiBox.find(".projects-list li").each (index) ->
-          name = $(this).find(".filter-title").text()
+        uiBox.find("ul.projects-list li").each (index) ->
+          name = $(this).find("span.filter-title").text()
 
           if name.toLowerCase().search(terms.toLowerCase()) == -1
             $(this).hide()
           else
             $(this).show()
-      uiBox.find(".projects-list li.bottom").hide()
+      uiBox.find("ul.projects-list li.bottom").hide()
 
 
diff --git a/app/assets/javascripts/shortcuts.js.coffee b/app/assets/javascripts/shortcuts.js.coffee
index e9aeb1e9525ccd00e733b625178e5b2fcb8fa84a..4d915bfc8c5c3e83b8d2bfd94659050ed2d0edcd 100644
--- a/app/assets/javascripts/shortcuts.js.coffee
+++ b/app/assets/javascripts/shortcuts.js.coffee
@@ -7,7 +7,7 @@ class @Shortcuts
 
   selectiveHelp: (e) =>
     Shortcuts.showHelp(e, @enabledHelp)
-      
+
   @showHelp: (e, location) ->
     if $('#modal-shortcuts').length > 0
       $('#modal-shortcuts').modal('show')
@@ -17,8 +17,7 @@ class @Shortcuts
         dataType: 'script',
         success: (e) ->
           if location and location.length > 0
-            for l in location
-              $(l).show()
+            $(l).show() for l in location
           else
             $('.hidden-shortcut').show()
             $('.js-more-help-button').remove()
@@ -28,3 +27,8 @@ class @Shortcuts
   @focusSearch: (e) ->
     $('#search').focus()
     e.preventDefault()
+
+$(document).on 'click.more_help', '.js-more-help-button', (e) ->
+  $(@).remove()
+  $('.hidden-shortcut').show()
+  e.preventDefault()
diff --git a/app/assets/javascripts/star.js.coffee b/app/assets/javascripts/star.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..d849b2e79500adbf730f3bee7a2ab1fb0ec18527
--- /dev/null
+++ b/app/assets/javascripts/star.js.coffee
@@ -0,0 +1,22 @@
+class @Star
+  constructor: ->
+    $('.project-home-panel .toggle-star').on('ajax:success', (e, data, status, xhr) ->
+      $this = $(this)
+      $starSpan = $this.find('span')
+      $starIcon = $this.find('i')
+
+      toggleStar = (isStarred) ->
+        $this.parent().find('span.count').text data.star_count
+        if isStarred
+          $starSpan.removeClass('starred').text 'Star'
+          $starIcon.removeClass('fa-star').addClass 'fa-star-o'
+        else
+          $starSpan.addClass('starred').text 'Unstar'
+          $starIcon.removeClass('fa-star-o').addClass 'fa-star'
+        return
+
+      toggleStar $starSpan.hasClass('starred')
+      return
+    ).on 'ajax:error', (e, xhr, status, error) ->
+      new Flash('Star toggle failed. Try again later.', 'alert')
+      return
\ No newline at end of file
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index 12abf806bfab11ec03a633b8526c3e1e112f203a..9467011799fd33f1342095fcad80ffdde73cf0fe 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -117,5 +117,5 @@ class @UsersSelect
       callback(users)
 
   buildUrl: (url) ->
-    url = gon.relative_url_root + url if gon.relative_url_root?
+    url = gon.relative_url_root.replace(/\/$/, '') + url if gon.relative_url_root?
     return url
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 7b060ce48532c36dadd52950c5f8f293a7515821..0c0451fe4ddffcca924242dc13424067609af4a0 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -2,8 +2,8 @@
  * This is a manifest file that'll automatically include all the stylesheets available in this directory
  * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
  * the top of the compiled file, but it's generally better to create a new file per style scope.
- *= require jquery.ui.datepicker
- *= require jquery.ui.autocomplete
+ *= require jquery-ui/datepicker
+ *= require jquery-ui/autocomplete
  *= require jquery.atwho
  *= require select2
  *= require_self
@@ -48,4 +48,4 @@
 /*
  * Styles for JS behaviors.
  */
-@import "behaviors.scss";
\ No newline at end of file
+@import "behaviors.scss";
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index a62c0f62a4c862cd950accfcf367e17ecc5dfc4c..206d39cc9b3b198f42f82729eb5b1aca18062876 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -76,7 +76,7 @@
 
 .cover-block {
   text-align: center;
-  background: #f7f8fa;
+  background: $background-color;
   margin: -$gl-padding;
   margin-bottom: 0;
   padding: 44px $gl-padding;
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index fe56266284b9d5c5709ce5d2cdd0f2d00eb6226e..97a94638847576c5b8695581e3dd83f21c781865 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -1,10 +1,9 @@
 @mixin btn-default {
-  @include border-radius(2px);
+  @include border-radius(3px);
   border-width: 1px;
   border-style: solid;
-  text-transform: uppercase;
-  font-size: 13px;
-  font-weight: 600;
+  font-size: 15px;
+  font-weight: 500;
   line-height: 18px;
   padding: 11px $gl-padding;
   letter-spacing: .4px;
@@ -18,7 +17,7 @@
 
 @mixin btn-middle {
   @include btn-default;
-  @include border-radius(2px);
+  @include border-radius(3px);
   padding: 11px 24px;
 }
 
@@ -51,6 +50,10 @@
   @include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF);
 }
 
+@mixin btn-blue-medium {
+  @include btn-color($blue-medium-light, $border-blue-light, $blue-medium, $border-blue-normal, $blue-medium-dark, $border-blue-dark, #FFFFFF);
+}
+
 @mixin btn-orange {
   @include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF);
 }
@@ -60,7 +63,7 @@
 }
 
 @mixin btn-gray {
-  @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-normal, $gray-dark, $border-gray-dark, #313236);
+  @include btn-color($gray-light, $border-gray-light, $gray-normal, $border-gray-light, $gray-dark, $border-gray-dark, #313236);
 }
 
 @mixin btn-white {
@@ -75,6 +78,10 @@
     padding: 5px 10px;
   }
 
+  &.btn-nr {
+    padding: 7px 10px;
+  }
+
   &.btn-xs {
     padding: 1px 5px;
   }
@@ -91,11 +98,15 @@
     @include btn-gray;
   }
 
-  &.btn-primary,
+  &.btn-primary {
+    @include btn-blue-medium;
+  }
+
   &.btn-info {
     @include btn-blue;
   }
 
+  &.btn-close,
   &.btn-warning {
     @include btn-orange;
   }
@@ -110,20 +121,8 @@
     float: right;
   }
 
-  &.btn-close {
-    color: $gl-danger;
-    border-color: $gl-danger;
-    &:hover {
-      color: #B94A48;
-    }
-  }
-
   &.btn-reopen {
-    color: $gl-success;
-    border-color: $gl-success;
-    &:hover {
-      color: #468847;
-    }
+    /* should be same as parent class for now */
   }
 
   &.btn-grouped {
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 88da799ee2b247c93b70e377c6da33939f51dcd4..11730000f85e32f06b75fe0c282f7c3e0e00d802 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -374,7 +374,7 @@ table {
   }
 }
 
-.center-top-menu {
+.center-top-menu, .left-top-menu {
   @include nav-menu;
   text-align: center;
   margin-top: 5px;
@@ -401,6 +401,16 @@ table {
     border-bottom: 1px solid $border-color;
     height: 57px;
   }
+
+  &.wide {
+    margin-left: -$gl-padding;
+    margin-right: -$gl-padding;
+  }
+}
+
+.left-top-menu {
+  text-align: left;
+  border-bottom: 1px solid #EEE;
 }
 
 .center-middle-menu {
diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss
index f12d68b5a1fe32c8648f87a3d7201665cad526d3..e93dbab0c423673007ae683e417780c04031c27f 100644
--- a/app/assets/stylesheets/framework/issue_box.scss
+++ b/app/assets/stylesheets/framework/issue_box.scss
@@ -4,8 +4,8 @@
  *
  */
 
-.issue-box {
-  @include border-radius(2px);
+.status-box {
+  @include border-radius(3px);
 
   display: block;
   float: left;
@@ -14,22 +14,22 @@
   margin-right: 10px;
   font-size: $gl-font-size;
 
-  &.issue-box-closed {
+  &.status-box-closed {
     background-color: $gl-danger;
     color: #FFF;
   }
 
-  &.issue-box-merged {
+  &.status-box-merged {
     background-color: $gl-primary;
     color: #FFF;
   }
 
-  &.issue-box-open {
-    background-color: #019875;
+  &.status-box-open {
+    background-color: $green-light;
     color: #FFF;
   }
 
-  &.issue-box-expired {
+  &.status-box-expired {
     background: #cea61b;
     color: #FFF;
   }
diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss
index aa5acb93cc52cb96882493e1300bfe3ba94128bc..a1a9990241d6964d96bda9f13e882c2c7ae9c66e 100644
--- a/app/assets/stylesheets/framework/layout.scss
+++ b/app/assets/stylesheets/framework/layout.scss
@@ -5,7 +5,7 @@ html {
 }
 
 body {
-  background-color: #EAEBEC !important;
+  background-color: #F3F3F3 !important;
 
   &.navless {
     background-color: white !important;
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index cc48f8c8166324a874a0cbc3c545222e68dce21e..1c74e525a608348f04250da3177c9fb01ce15838 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -143,7 +143,11 @@ ul.controls {
 
   > li {
     float: left;
-    padding-right: 10px;
+    margin-right: 10px;
+    
+    &:last-child {
+      margin-right: 0;
+    }
 
     .author_link {
       display: inline-block;
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 2b044786738566bae2ef7ab6a04693d11393ec95..4a00a197d9a0c817eaa19345e81fe6b176234e46 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -87,7 +87,7 @@
 
 .new_note,
 .edit_note,
-.issuable-description,
+.detail-page-description,
 .milestone-description,
 .wiki-content,
 .merge-request-form {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 11c48d26ab53a27e50564b4c261ce0224653e6b0..41fd890f14f8046b858b3e6f56fffb4dd16ba338 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -123,7 +123,6 @@
   padding: 0;
   margin: 0;
   list-style: none;
-  margin-top: 5px;
   height: 56px;
 
   li {
@@ -131,9 +130,9 @@
 
     a {
       padding: 14px;
-      font-size: 17px;
+      font-size: 15px;
       line-height: 28px;
-      color: #7f8fa4;
+      color: #959494;
       border-bottom: 2px solid transparent;
 
       &:hover, &:active, &:focus {
@@ -143,8 +142,8 @@
     }
 
     &.active a {
-      color: #4c4e54;
-      border-bottom: 2px solid #1cacfc;
+      color: #616060;
+      border-bottom: 2px solid #4688f1;
     }
 
     .badge {
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
index 6f44c323732325d73eed22088c5ee1f8c43883b7..c00709fb6bb9a3bb1d7f07080ed77ff2502610a1 100644
--- a/app/assets/stylesheets/framework/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -81,7 +81,7 @@
     display: none;
   }
 
-  .center-top-menu {
+  .center-top-menu, .left-top-menu {
     li a {
       font-size: 14px;
       padding: 19px 10px;
diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
index eb53c4153d3e794e48443da57f213ae6315538cd..ff41e26ed8adc4185f783f34a567820392d27e44 100644
--- a/app/assets/stylesheets/framework/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -10,8 +10,7 @@
     margin-left: -$gl-padding;
     margin-right: -$gl-padding;
     color: $gl-gray;
-    border-bottom: 1px solid #ECEEF1;
-    border-right: 1px solid #ECEEF1;
+    border-bottom: 1px solid $border-white-light;
 
     &:target {
       background: $hover;
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 2ef40a6e51738724399a45b592faf9a30c757152..af75123b0af367508648ead871ee196e231dc049 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -1,9 +1,9 @@
-$hover: #FFFAF1;
+$hover: #faf9f9;
 $gl-text-color: #54565B;
 $gl-text-green: #4A2;
 $gl-text-red: #D12F19;
 $gl-text-orange: #D90;
-$gl-header-color: #4c4e54;
+$gl-header-color: #323232;
 $gl-link-color: #333c48;
 $md-text-color: #444;
 $md-link-color: #3084bb;
@@ -15,13 +15,14 @@ $sidebar_width: 230px;
 $avatar_radius: 50%;
 $code_font_size: 13px;
 $code_line_height: 1.5;
-$border-color: #dce0e6;
+$border-color: #efeff1;
 $table-border-color: #eef0f2;
-$background-color: #F7F8FA;
+$background-color: #faf9f9;
 $header-height: 58px;
 $fixed-layout-width: 1280px;
-$gl-gray: #7f8fa4;
+$gl-gray: #5a5a5a;
 $gl-padding: 16px;
+$gl-padding-top:10px;
 $gl-avatar-size: 46px;
 
 /*
@@ -29,12 +30,12 @@ $gl-avatar-size: 46px;
  */
 
 $white-light: #FFFFFF;
-$white-normal: #DCE0E5;
-$white-dark: #E4E7ED;
+$white-normal: #ededed;
+$white-dark: #ededed;
 
-$gray-light: #F0F2F5;
-$gray-normal: #DCE0E5;
-$gray-dark: #E4E7ED;
+$gray-light: #f7f7f7;
+$gray-normal: #ededed;
+$gray-dark: #ededed;
 
 $green-light: #31AF64;
 $green-normal: #2FAA60;
@@ -44,6 +45,10 @@ $blue-light: #2EA8E5;
 $blue-normal: #2D9FD8;
 $blue-dark: #2897CE;
 
+$blue-medium-light: #3498CB;
+$blue-medium: #2F8EBF;
+$blue-medium-dark: #2D86B4;
+
 $orange-light: #FC6443;
 $orange-normal: #E75E40;
 $orange-dark: #CE5237;
@@ -52,11 +57,11 @@ $red-light: #F43263;
 $red-normal: #E52C5A;
 $red-dark: #D22852;
 
-$border-white-light: #E3E7EC;
+$border-white-light: #F1F2F4;
 $border-white-normal: #D6DAE2;
 $border-white-dark: #C6CACF;
 
-$border-gray-light: #DCE0E5;
+$border-gray-light: #d1d1d1;
 $border-gray-normal: #D6DAE2;
 $border-gray-dark: #C6CACF;
 
@@ -76,6 +81,8 @@ $border-red-light: #E52C5A;
 $border-red-normal: #D22852;
 $border-red-dark: #CA264F;
 
+/* header */
+$light-grey-header: #faf9f9;
 
 /*
  * State colors:
diff --git a/app/assets/stylesheets/pages/awards.scss b/app/assets/stylesheets/pages/awards.scss
index 041b811a606b6f418e6417cb3e27fd4c43c04135..87dd30f41114daf3ab6d6bad96e781b38aadcaab 100644
--- a/app/assets/stylesheets/pages/awards.scss
+++ b/app/assets/stylesheets/pages/awards.scss
@@ -2,6 +2,12 @@
   @include clearfix;
   line-height: 34px;
 
+  .emoji-icon {
+    width: 20px;
+    height: 20px;
+    margin: 7px 0 0 5px;
+  }
+
   .award {
     @include border-radius(5px);
 
@@ -40,6 +46,7 @@
   }
 
   .awards-controls {
+    position: relative;
     margin-left: 10px;
     float: left;
 
@@ -55,32 +62,64 @@
       }
     }
 
-    .awards-menu {
-      padding: $gl-padding;
-      min-width: 214px;
+    .emoji-menu{
+      position: absolute;
+      top: 100%;
+      left: 0;
+      z-index: 1000;
+      display: none;
+      float: left;
+      min-width: 160px;
+      padding: 5px 0;
+      margin: 2px 0 0;
+      font-size: 14px;
+      text-align: left;
+      list-style: none;
+      background-color: #fff;
+      -webkit-background-clip: padding-box;
+      background-clip: padding-box;
+      border: 1px solid #ccc;
+      border: 1px solid rgba(0,0,0,.15);
+      border-radius: 4px;
+      -webkit-box-shadow: 0 6px 12px rgba(0,0,0,.175);
+      box-shadow: 0 6px 12px rgba(0,0,0,.175);
+
+      .emoji-menu-content {
+        padding: $gl-padding;
+        width: 300px;
+        height: 300px;
+        overflow-y: scroll;
+
+        h5 {
+          clear: left;
+        }
 
-      > li {
-        cursor: pointer;
-        width: 30px;
-        height: 30px;
-        text-align: center;
-        @include border-radius(5px);
+        ul {
+          list-style-type: none;
+          margin-left: -20px;
+          margin-bottom: 20px;
+          overflow: auto;
+        }
 
-        img {
-          margin-bottom: 2px;
+        input.emoji-search{
+          background: image-url("icon-search.png") 240px no-repeat;
         }
 
-        &:hover {
-          background-color: #ccc;
+        li {
+          cursor: pointer;
+          width: 30px;
+          height: 30px;
+          text-align: center;
+          float: left;
+          margin: 3px;
+          list-decorate: none;
+          @include border-radius(5px);
+
+          &:hover {
+            background-color: #ccc;
+          }
         }
       }
     }
   }
-
-  .awards-menu{
-    li {
-      float: left;
-      margin: 3px;
-    }
-  }
 }
diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss
new file mode 100644
index 0000000000000000000000000000000000000000..deab805dbc2988ab003f6f5b47675e7cb1697a92
--- /dev/null
+++ b/app/assets/stylesheets/pages/detail_page.scss
@@ -0,0 +1,33 @@
+.detail-page-header {
+  margin: -$gl-padding;
+  padding: 7px $gl-padding;
+  margin-bottom: 0px;
+  border-bottom: 1px solid $border-color;
+  color: #5c5d5e;
+  font-size: 16px;
+  line-height: 34px;
+
+  .author {
+    color: #5c5d5e;
+  }
+
+  .identifier {
+    color: #5c5d5e;
+  }
+}
+
+.detail-page-description {
+  .title {
+    margin: 0;
+    font-size: 23px;
+    color: #313236;
+  }
+
+  .description {
+    margin-top: 6px;
+
+    p:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
diff --git a/app/assets/stylesheets/pages/emojis.scss b/app/assets/stylesheets/pages/emojis.scss
new file mode 100644
index 0000000000000000000000000000000000000000..89a94c5a780b5a7a552436475251d008370ada23
--- /dev/null
+++ b/app/assets/stylesheets/pages/emojis.scss
@@ -0,0 +1,1272 @@
+/*
+File is generated by https://github.com/jakesgordon/sprite-factory and midified manualy
+The source: gemojione gem.
+*/
+
+.emoji-icon{
+  background-image: image-url("emoji.png");
+  background-repeat: no-repeat;
+}
+
+.emoji-0023-20E3 { background-position: 0px 0px; }
+.emoji-0030-20E3 { background-position: -20px 0px; }
+.emoji-0031-20E3 { background-position: -40px 0px; }
+.emoji-0032-20E3 { background-position: -60px 0px; }
+.emoji-0033-20E3 { background-position: -80px 0px; }
+.emoji-0034-20E3 { background-position: -100px 0px; }
+.emoji-0035-20E3 { background-position: -120px 0px; }
+.emoji-0036-20E3 { background-position: -140px 0px; }
+.emoji-0037-20E3 { background-position: -160px 0px; }
+.emoji-0038-20E3 { background-position: -180px 0px; }
+.emoji-0039-20E3 { background-position: -200px 0px; }
+.emoji-00A9 { background-position: -220px 0px; }
+.emoji-00AE { background-position: -240px 0px; }
+.emoji-1F004 { background-position: -260px 0px; }
+.emoji-1F0CF { background-position: -280px 0px; }
+.emoji-1F170 { background-position: -300px 0px; }
+.emoji-1F171 { background-position: -320px 0px; }
+.emoji-1F17E { background-position: -340px 0px; }
+.emoji-1F17F { background-position: -360px 0px; }
+.emoji-1F18E { background-position: -380px 0px; }
+.emoji-1F191 { background-position: -400px 0px; }
+.emoji-1F192 { background-position: -420px 0px; }
+.emoji-1F193 { background-position: -440px 0px; }
+.emoji-1F194 { background-position: -460px 0px; }
+.emoji-1F195 { background-position: -480px 0px; }
+.emoji-1F196 { background-position: -500px 0px; }
+.emoji-1F197 { background-position: -520px 0px; }
+.emoji-1F198 { background-position: -540px 0px; }
+.emoji-1F199 { background-position: -560px 0px; }
+.emoji-1F19A { background-position: -580px 0px; }
+.emoji-1F1E6-1F1E8 { background-position: -600px 0px; }
+.emoji-1F1E6-1F1E9 { background-position: -620px 0px; }
+.emoji-1F1E6-1F1EA { background-position: -640px 0px; }
+.emoji-1F1E6-1F1EB { background-position: -660px 0px; }
+.emoji-1F1E6-1F1EC { background-position: -680px 0px; }
+.emoji-1F1E6-1F1EE { background-position: -700px 0px; }
+.emoji-1F1E6-1F1F1 { background-position: -720px 0px; }
+.emoji-1F1E6-1F1F2 { background-position: -740px 0px; }
+.emoji-1F1E6-1F1F4 { background-position: -760px 0px; }
+.emoji-1F1E6-1F1F7 { background-position: -780px 0px; }
+.emoji-1F1E6-1F1F9 { background-position: -800px 0px; }
+.emoji-1F1E6-1F1FA { background-position: -820px 0px; }
+.emoji-1F1E6-1F1FC { background-position: -840px 0px; }
+.emoji-1F1E6-1F1FF { background-position: -860px 0px; }
+.emoji-1F1E7-1F1E6 { background-position: -880px 0px; }
+.emoji-1F1E7-1F1E7 { background-position: -900px 0px; }
+.emoji-1F1E7-1F1E9 { background-position: -920px 0px; }
+.emoji-1F1E7-1F1EA { background-position: -940px 0px; }
+.emoji-1F1E7-1F1EB { background-position: -960px 0px; }
+.emoji-1F1E7-1F1EC { background-position: -980px 0px; }
+.emoji-1F1E7-1F1ED { background-position: -1000px 0px; }
+.emoji-1F1E7-1F1EE { background-position: -1020px 0px; }
+.emoji-1F1E7-1F1EF { background-position: -1040px 0px; }
+.emoji-1F1E7-1F1F2 { background-position: -1060px 0px; }
+.emoji-1F1E7-1F1F3 { background-position: -1080px 0px; }
+.emoji-1F1E7-1F1F4 { background-position: -1100px 0px; }
+.emoji-1F1E7-1F1F7 { background-position: -1120px 0px; }
+.emoji-1F1E7-1F1F8 { background-position: -1140px 0px; }
+.emoji-1F1E7-1F1F9 { background-position: -1160px 0px; }
+.emoji-1F1E7-1F1FC { background-position: -1180px 0px; }
+.emoji-1F1E7-1F1FE { background-position: -1200px 0px; }
+.emoji-1F1E7-1F1FF { background-position: -1220px 0px; }
+.emoji-1F1E8-1F1E6 { background-position: -1240px 0px; }
+.emoji-1F1E8-1F1E9 { background-position: -1260px 0px; }
+.emoji-1F1E8-1F1EB { background-position: -1280px 0px; }
+.emoji-1F1E8-1F1EC { background-position: -1300px 0px; }
+.emoji-1F1E8-1F1ED { background-position: -1320px 0px; }
+.emoji-1F1E8-1F1EE { background-position: -1340px 0px; }
+.emoji-1F1E8-1F1F1 { background-position: -1360px 0px; }
+.emoji-1F1E8-1F1F2 { background-position: -1380px 0px; }
+.emoji-1F1E8-1F1F3 { background-position: -1400px 0px; }
+.emoji-1F1E8-1F1F4 { background-position: -1420px 0px; }
+.emoji-1F1E8-1F1F7 { background-position: -1440px 0px; }
+.emoji-1F1E8-1F1FA { background-position: -1460px 0px; }
+.emoji-1F1E8-1F1FB { background-position: -1480px 0px; }
+.emoji-1F1E8-1F1FE { background-position: -1500px 0px; }
+.emoji-1F1E8-1F1FF { background-position: -1520px 0px; }
+.emoji-1F1E9-1F1EA { background-position: -1540px 0px; }
+.emoji-1F1E9-1F1EF { background-position: -1560px 0px; }
+.emoji-1F1E9-1F1F0 { background-position: -1580px 0px; }
+.emoji-1F1E9-1F1F2 { background-position: -1600px 0px; }
+.emoji-1F1E9-1F1F4 { background-position: -1620px 0px; }
+.emoji-1F1E9-1F1FF { background-position: -1640px 0px; }
+.emoji-1F1EA-1F1E8 { background-position: -1660px 0px; }
+.emoji-1F1EA-1F1EA { background-position: -1680px 0px; }
+.emoji-1F1EA-1F1EC { background-position: -1700px 0px; }
+.emoji-1F1EA-1F1ED { background-position: -1720px 0px; }
+.emoji-1F1EA-1F1F7 { background-position: -1740px 0px; }
+.emoji-1F1EA-1F1F8 { background-position: -1760px 0px; }
+.emoji-1F1EA-1F1F9 { background-position: -1780px 0px; }
+.emoji-1F1EB-1F1EE { background-position: -1800px 0px; }
+.emoji-1F1EB-1F1EF { background-position: -1820px 0px; }
+.emoji-1F1EB-1F1F0 { background-position: -1840px 0px; }
+.emoji-1F1EB-1F1F2 { background-position: -1860px 0px; }
+.emoji-1F1EB-1F1F4 { background-position: -1880px 0px; }
+.emoji-1F1EB-1F1F7 { background-position: -1900px 0px; }
+.emoji-1F1EC-1F1E6 { background-position: -1920px 0px; }
+.emoji-1F1EC-1F1E7 { background-position: -1940px 0px; }
+.emoji-1F1EC-1F1E9 { background-position: -1960px 0px; }
+.emoji-1F1EC-1F1EA { background-position: -1980px 0px; }
+.emoji-1F1EC-1F1ED { background-position: -2000px 0px; }
+.emoji-1F1EC-1F1EE { background-position: -2020px 0px; }
+.emoji-1F1EC-1F1F1 { background-position: -2040px 0px; }
+.emoji-1F1EC-1F1F2 { background-position: -2060px 0px; }
+.emoji-1F1EC-1F1F3 { background-position: -2080px 0px; }
+.emoji-1F1EC-1F1F6 { background-position: -2100px 0px; }
+.emoji-1F1EC-1F1F7 { background-position: -2120px 0px; }
+.emoji-1F1EC-1F1F9 { background-position: -2140px 0px; }
+.emoji-1F1EC-1F1FA { background-position: -2160px 0px; }
+.emoji-1F1EC-1F1FC { background-position: -2180px 0px; }
+.emoji-1F1EC-1F1FE { background-position: -2200px 0px; }
+.emoji-1F1ED-1F1F0 { background-position: -2220px 0px; }
+.emoji-1F1ED-1F1F3 { background-position: -2240px 0px; }
+.emoji-1F1ED-1F1F7 { background-position: -2260px 0px; }
+.emoji-1F1ED-1F1F9 { background-position: -2280px 0px; }
+.emoji-1F1ED-1F1FA { background-position: -2300px 0px; }
+.emoji-1F1EE-1F1E9 { background-position: -2320px 0px; }
+.emoji-1F1EE-1F1EA { background-position: -2340px 0px; }
+.emoji-1F1EE-1F1F1 { background-position: -2360px 0px; }
+.emoji-1F1EE-1F1F3 { background-position: -2380px 0px; }
+.emoji-1F1EE-1F1F6 { background-position: -2400px 0px; }
+.emoji-1F1EE-1F1F7 { background-position: -2420px 0px; }
+.emoji-1F1EE-1F1F8 { background-position: -2440px 0px; }
+.emoji-1F1EE-1F1F9 { background-position: -2460px 0px; }
+.emoji-1F1EF-1F1EA { background-position: -2480px 0px; }
+.emoji-1F1EF-1F1F2 { background-position: -2500px 0px; }
+.emoji-1F1EF-1F1F4 { background-position: -2520px 0px; }
+.emoji-1F1EF-1F1F5 { background-position: -2540px 0px; }
+.emoji-1F1F0-1F1EA { background-position: -2560px 0px; }
+.emoji-1F1F0-1F1EC { background-position: -2580px 0px; }
+.emoji-1F1F0-1F1ED { background-position: -2600px 0px; }
+.emoji-1F1F0-1F1EE { background-position: -2620px 0px; }
+.emoji-1F1F0-1F1F2 { background-position: -2640px 0px; }
+.emoji-1F1F0-1F1F3 { background-position: -2660px 0px; }
+.emoji-1F1F0-1F1F5 { background-position: -2680px 0px; }
+.emoji-1F1F0-1F1F7 { background-position: -2700px 0px; }
+.emoji-1F1F0-1F1FC { background-position: -2720px 0px; }
+.emoji-1F1F0-1F1FE { background-position: -2740px 0px; }
+.emoji-1F1F0-1F1FF { background-position: -2760px 0px; }
+.emoji-1F1F1-1F1E6 { background-position: -2780px 0px; }
+.emoji-1F1F1-1F1E7 { background-position: -2800px 0px; }
+.emoji-1F1F1-1F1E8 { background-position: -2820px 0px; }
+.emoji-1F1F1-1F1EE { background-position: -2840px 0px; }
+.emoji-1F1F1-1F1F0 { background-position: -2860px 0px; }
+.emoji-1F1F1-1F1F7 { background-position: -2880px 0px; }
+.emoji-1F1F1-1F1F8 { background-position: -2900px 0px; }
+.emoji-1F1F1-1F1F9 { background-position: -2920px 0px; }
+.emoji-1F1F1-1F1FA { background-position: -2940px 0px; }
+.emoji-1F1F1-1F1FB { background-position: -2960px 0px; }
+.emoji-1F1F1-1F1FE { background-position: -2980px 0px; }
+.emoji-1F1F2-1F1E6 { background-position: -3000px 0px; }
+.emoji-1F1F2-1F1E8 { background-position: -3020px 0px; }
+.emoji-1F1F2-1F1E9 { background-position: -3040px 0px; }
+.emoji-1F1F2-1F1EA { background-position: -3060px 0px; }
+.emoji-1F1F2-1F1EC { background-position: -3080px 0px; }
+.emoji-1F1F2-1F1ED { background-position: -3100px 0px; }
+.emoji-1F1F2-1F1F0 { background-position: -3120px 0px; }
+.emoji-1F1F2-1F1F1 { background-position: -3140px 0px; }
+.emoji-1F1F2-1F1F2 { background-position: -3160px 0px; }
+.emoji-1F1F2-1F1F3 { background-position: -3180px 0px; }
+.emoji-1F1F2-1F1F4 { background-position: -3200px 0px; }
+.emoji-1F1F2-1F1F7 { background-position: -3220px 0px; }
+.emoji-1F1F2-1F1F8 { background-position: -3240px 0px; }
+.emoji-1F1F2-1F1F9 { background-position: -3260px 0px; }
+.emoji-1F1F2-1F1FA { background-position: -3280px 0px; }
+.emoji-1F1F2-1F1FB { background-position: -3300px 0px; }
+.emoji-1F1F2-1F1FC { background-position: -3320px 0px; }
+.emoji-1F1F2-1F1FD { background-position: -3340px 0px; }
+.emoji-1F1F2-1F1FE { background-position: -3360px 0px; }
+.emoji-1F1F2-1F1FF { background-position: -3380px 0px; }
+.emoji-1F1F3-1F1E6 { background-position: -3400px 0px; }
+.emoji-1F1F3-1F1E8 { background-position: -3420px 0px; }
+.emoji-1F1F3-1F1EA { background-position: -3440px 0px; }
+.emoji-1F1F3-1F1EC { background-position: -3460px 0px; }
+.emoji-1F1F3-1F1EE { background-position: -3480px 0px; }
+.emoji-1F1F3-1F1F1 { background-position: -3500px 0px; }
+.emoji-1F1F3-1F1F4 { background-position: -3520px 0px; }
+.emoji-1F1F3-1F1F5 { background-position: -3540px 0px; }
+.emoji-1F1F3-1F1F7 { background-position: -3560px 0px; }
+.emoji-1F1F3-1F1FA { background-position: -3580px 0px; }
+.emoji-1F1F3-1F1FF { background-position: -3600px 0px; }
+.emoji-1F1F4-1F1F2 { background-position: -3620px 0px; }
+.emoji-1F1F5-1F1E6 { background-position: -3640px 0px; }
+.emoji-1F1F5-1F1EA { background-position: -3660px 0px; }
+.emoji-1F1F5-1F1EB { background-position: -3680px 0px; }
+.emoji-1F1F5-1F1EC { background-position: -3700px 0px; }
+.emoji-1F1F5-1F1ED { background-position: -3720px 0px; }
+.emoji-1F1F5-1F1F0 { background-position: -3740px 0px; }
+.emoji-1F1F5-1F1F1 { background-position: -3760px 0px; }
+.emoji-1F1F5-1F1F7 { background-position: -3780px 0px; }
+.emoji-1F1F5-1F1F8 { background-position: -3800px 0px; }
+.emoji-1F1F5-1F1F9 { background-position: -3820px 0px; }
+.emoji-1F1F5-1F1FC { background-position: -3840px 0px; }
+.emoji-1F1F5-1F1FE { background-position: -3860px 0px; }
+.emoji-1F1F6-1F1E6 { background-position: -3880px 0px; }
+.emoji-1F1F7-1F1F4 { background-position: -3900px 0px; }
+.emoji-1F1F7-1F1F8 { background-position: -3920px 0px; }
+.emoji-1F1F7-1F1FA { background-position: -3940px 0px; }
+.emoji-1F1F7-1F1FC { background-position: -3960px 0px; }
+.emoji-1F1F8-1F1E6 { background-position: -3980px 0px; }
+.emoji-1F1F8-1F1E7 { background-position: -4000px 0px; }
+.emoji-1F1F8-1F1E8 { background-position: -4020px 0px; }
+.emoji-1F1F8-1F1E9 { background-position: -4040px 0px; }
+.emoji-1F1F8-1F1EA { background-position: -4060px 0px; }
+.emoji-1F1F8-1F1EC { background-position: -4080px 0px; }
+.emoji-1F1F8-1F1ED { background-position: -4100px 0px; }
+.emoji-1F1F8-1F1EE { background-position: -4120px 0px; }
+.emoji-1F1F8-1F1F0 { background-position: -4140px 0px; }
+.emoji-1F1F8-1F1F1 { background-position: -4160px 0px; }
+.emoji-1F1F8-1F1F2 { background-position: -4180px 0px; }
+.emoji-1F1F8-1F1F3 { background-position: -4200px 0px; }
+.emoji-1F1F8-1F1F4 { background-position: -4220px 0px; }
+.emoji-1F1F8-1F1F7 { background-position: -4240px 0px; }
+.emoji-1F1F8-1F1F9 { background-position: -4260px 0px; }
+.emoji-1F1F8-1F1FB { background-position: -4280px 0px; }
+.emoji-1F1F8-1F1FE { background-position: -4300px 0px; }
+.emoji-1F1F8-1F1FF { background-position: -4320px 0px; }
+.emoji-1F1F9-1F1E9 { background-position: -4340px 0px; }
+.emoji-1F1F9-1F1EC { background-position: -4360px 0px; }
+.emoji-1F1F9-1F1ED { background-position: -4380px 0px; }
+.emoji-1F1F9-1F1EF { background-position: -4400px 0px; }
+.emoji-1F1F9-1F1F1 { background-position: -4420px 0px; }
+.emoji-1F1F9-1F1F2 { background-position: -4440px 0px; }
+.emoji-1F1F9-1F1F3 { background-position: -4460px 0px; }
+.emoji-1F1F9-1F1F4 { background-position: -4480px 0px; }
+.emoji-1F1F9-1F1F7 { background-position: -4500px 0px; }
+.emoji-1F1F9-1F1F9 { background-position: -4520px 0px; }
+.emoji-1F1F9-1F1FB { background-position: -4540px 0px; }
+.emoji-1F1F9-1F1FC { background-position: -4560px 0px; }
+.emoji-1F1F9-1F1FF { background-position: -4580px 0px; }
+.emoji-1F1FA-1F1E6 { background-position: -4600px 0px; }
+.emoji-1F1FA-1F1EC { background-position: -4620px 0px; }
+.emoji-1F1FA-1F1F8 { background-position: -4640px 0px; }
+.emoji-1F1FA-1F1FE { background-position: -4660px 0px; }
+.emoji-1F1FA-1F1FF { background-position: -4680px 0px; }
+.emoji-1F1FB-1F1E6 { background-position: -4700px 0px; }
+.emoji-1F1FB-1F1E8 { background-position: -4720px 0px; }
+.emoji-1F1FB-1F1EA { background-position: -4740px 0px; }
+.emoji-1F1FB-1F1EE { background-position: -4760px 0px; }
+.emoji-1F1FB-1F1F3 { background-position: -4780px 0px; }
+.emoji-1F1FB-1F1FA { background-position: -4800px 0px; }
+.emoji-1F1FC-1F1EB { background-position: -4820px 0px; }
+.emoji-1F1FC-1F1F8 { background-position: -4840px 0px; }
+.emoji-1F1FD-1F1F0 { background-position: -4860px 0px; }
+.emoji-1F1FE-1F1EA { background-position: -4880px 0px; }
+.emoji-1F1FF-1F1E6 { background-position: -4900px 0px; }
+.emoji-1F1FF-1F1F2 { background-position: -4920px 0px; }
+.emoji-1F1FF-1F1FC { background-position: -4940px 0px; }
+.emoji-1F201 { background-position: -4960px 0px; }
+.emoji-1F202 { background-position: -4980px 0px; }
+.emoji-1F21A { background-position: -5000px 0px; }
+.emoji-1F22F { background-position: -5020px 0px; }
+.emoji-1F232 { background-position: -5040px 0px; }
+.emoji-1F233 { background-position: -5060px 0px; }
+.emoji-1F234 { background-position: -5080px 0px; }
+.emoji-1F235 { background-position: -5100px 0px; }
+.emoji-1F236 { background-position: -5120px 0px; }
+.emoji-1F237 { background-position: -5140px 0px; }
+.emoji-1F238 { background-position: -5160px 0px; }
+.emoji-1F239 { background-position: -5180px 0px; }
+.emoji-1F23A { background-position: -5200px 0px; }
+.emoji-1F250 { background-position: -5220px 0px; }
+.emoji-1F251 { background-position: -5240px 0px; }
+.emoji-1F300 { background-position: -5260px 0px; }
+.emoji-1F301 { background-position: -5280px 0px; }
+.emoji-1F302 { background-position: -5300px 0px; }
+.emoji-1F303 { background-position: -5320px 0px; }
+.emoji-1F304 { background-position: -5340px 0px; }
+.emoji-1F305 { background-position: -5360px 0px; }
+.emoji-1F306 { background-position: -5380px 0px; }
+.emoji-1F307 { background-position: -5400px 0px; }
+.emoji-1F308 { background-position: -5420px 0px; }
+.emoji-1F309 { background-position: -5440px 0px; }
+.emoji-1F30A { background-position: -5460px 0px; }
+.emoji-1F30B { background-position: -5480px 0px; }
+.emoji-1F30C { background-position: -5500px 0px; }
+.emoji-1F30D { background-position: -5520px 0px; }
+.emoji-1F30E { background-position: -5540px 0px; }
+.emoji-1F30F { background-position: -5560px 0px; }
+.emoji-1F310 { background-position: -5580px 0px; }
+.emoji-1F311 { background-position: -5600px 0px; }
+.emoji-1F312 { background-position: -5620px 0px; }
+.emoji-1F313 { background-position: -5640px 0px; }
+.emoji-1F314 { background-position: -5660px 0px; }
+.emoji-1F315 { background-position: -5680px 0px; }
+.emoji-1F316 { background-position: -5700px 0px; }
+.emoji-1F317 { background-position: -5720px 0px; }
+.emoji-1F318 { background-position: -5740px 0px; }
+.emoji-1F319 { background-position: -5760px 0px; }
+.emoji-1F31A { background-position: -5780px 0px; }
+.emoji-1F31B { background-position: -5800px 0px; }
+.emoji-1F31C { background-position: -5820px 0px; }
+.emoji-1F31D { background-position: -5840px 0px; }
+.emoji-1F31E { background-position: -5860px 0px; }
+.emoji-1F31F { background-position: -5880px 0px; }
+.emoji-1F320 { background-position: -5900px 0px; }
+.emoji-1F321 { background-position: -5920px 0px; }
+.emoji-1F327 { background-position: -5940px 0px; }
+.emoji-1F328 { background-position: -5960px 0px; }
+.emoji-1F329 { background-position: -5980px 0px; }
+.emoji-1F32A { background-position: -6000px 0px; }
+.emoji-1F32B { background-position: -6020px 0px; }
+.emoji-1F32C { background-position: -6040px 0px; }
+.emoji-1F330 { background-position: -6060px 0px; }
+.emoji-1F331 { background-position: -6080px 0px; }
+.emoji-1F332 { background-position: -6100px 0px; }
+.emoji-1F333 { background-position: -6120px 0px; }
+.emoji-1F334 { background-position: -6140px 0px; }
+.emoji-1F335 { background-position: -6160px 0px; }
+.emoji-1F336 { background-position: -6180px 0px; }
+.emoji-1F337 { background-position: -6200px 0px; }
+.emoji-1F338 { background-position: -6220px 0px; }
+.emoji-1F339 { background-position: -6240px 0px; }
+.emoji-1F33A { background-position: -6260px 0px; }
+.emoji-1F33B { background-position: -6280px 0px; }
+.emoji-1F33C { background-position: -6300px 0px; }
+.emoji-1F33D { background-position: -6320px 0px; }
+.emoji-1F33E { background-position: -6340px 0px; }
+.emoji-1F33F { background-position: -6360px 0px; }
+.emoji-1F340 { background-position: -6380px 0px; }
+.emoji-1F341 { background-position: -6400px 0px; }
+.emoji-1F342 { background-position: -6420px 0px; }
+.emoji-1F343 { background-position: -6440px 0px; }
+.emoji-1F344 { background-position: -6460px 0px; }
+.emoji-1F345 { background-position: -6480px 0px; }
+.emoji-1F346 { background-position: -6500px 0px; }
+.emoji-1F347 { background-position: -6520px 0px; }
+.emoji-1F348 { background-position: -6540px 0px; }
+.emoji-1F349 { background-position: -6560px 0px; }
+.emoji-1F34A { background-position: -6580px 0px; }
+.emoji-1F34B { background-position: -6600px 0px; }
+.emoji-1F34C { background-position: -6620px 0px; }
+.emoji-1F34D { background-position: -6640px 0px; }
+.emoji-1F34E { background-position: -6660px 0px; }
+.emoji-1F34F { background-position: -6680px 0px; }
+.emoji-1F350 { background-position: -6700px 0px; }
+.emoji-1F351 { background-position: -6720px 0px; }
+.emoji-1F352 { background-position: -6740px 0px; }
+.emoji-1F353 { background-position: -6760px 0px; }
+.emoji-1F354 { background-position: -6780px 0px; }
+.emoji-1F355 { background-position: -6800px 0px; }
+.emoji-1F356 { background-position: -6820px 0px; }
+.emoji-1F357 { background-position: -6840px 0px; }
+.emoji-1F358 { background-position: -6860px 0px; }
+.emoji-1F359 { background-position: -6880px 0px; }
+.emoji-1F35A { background-position: -6900px 0px; }
+.emoji-1F35B { background-position: -6920px 0px; }
+.emoji-1F35C { background-position: -6940px 0px; }
+.emoji-1F35D { background-position: -6960px 0px; }
+.emoji-1F35E { background-position: -6980px 0px; }
+.emoji-1F35F { background-position: -7000px 0px; }
+.emoji-1F360 { background-position: -7020px 0px; }
+.emoji-1F361 { background-position: -7040px 0px; }
+.emoji-1F362 { background-position: -7060px 0px; }
+.emoji-1F363 { background-position: -7080px 0px; }
+.emoji-1F364 { background-position: -7100px 0px; }
+.emoji-1F365 { background-position: -7120px 0px; }
+.emoji-1F366 { background-position: -7140px 0px; }
+.emoji-1F367 { background-position: -7160px 0px; }
+.emoji-1F368 { background-position: -7180px 0px; }
+.emoji-1F369 { background-position: -7200px 0px; }
+.emoji-1F36A { background-position: -7220px 0px; }
+.emoji-1F36B { background-position: -7240px 0px; }
+.emoji-1F36C { background-position: -7260px 0px; }
+.emoji-1F36D { background-position: -7280px 0px; }
+.emoji-1F36E { background-position: -7300px 0px; }
+.emoji-1F36F { background-position: -7320px 0px; }
+.emoji-1F370 { background-position: -7340px 0px; }
+.emoji-1F371 { background-position: -7360px 0px; }
+.emoji-1F372 { background-position: -7380px 0px; }
+.emoji-1F373 { background-position: -7400px 0px; }
+.emoji-1F374 { background-position: -7420px 0px; }
+.emoji-1F375 { background-position: -7440px 0px; }
+.emoji-1F376 { background-position: -7460px 0px; }
+.emoji-1F377 { background-position: -7480px 0px; }
+.emoji-1F378 { background-position: -7500px 0px; }
+.emoji-1F379 { background-position: -7520px 0px; }
+.emoji-1F37A { background-position: -7540px 0px; }
+.emoji-1F37B { background-position: -7560px 0px; }
+.emoji-1F37C { background-position: -7580px 0px; }
+.emoji-1F37D { background-position: -7600px 0px; }
+.emoji-1F380 { background-position: -7620px 0px; }
+.emoji-1F381 { background-position: -7640px 0px; }
+.emoji-1F382 { background-position: -7660px 0px; }
+.emoji-1F383 { background-position: -7680px 0px; }
+.emoji-1F384 { background-position: -7700px 0px; }
+.emoji-1F385 { background-position: -7720px 0px; }
+.emoji-1F386 { background-position: -7740px 0px; }
+.emoji-1F387 { background-position: -7760px 0px; }
+.emoji-1F388 { background-position: -7780px 0px; }
+.emoji-1F389 { background-position: -7800px 0px; }
+.emoji-1F38A { background-position: -7820px 0px; }
+.emoji-1F38B { background-position: -7840px 0px; }
+.emoji-1F38C { background-position: -7860px 0px; }
+.emoji-1F38D { background-position: -7880px 0px; }
+.emoji-1F38E { background-position: -7900px 0px; }
+.emoji-1F38F { background-position: -7920px 0px; }
+.emoji-1F390 { background-position: -7940px 0px; }
+.emoji-1F391 { background-position: -7960px 0px; }
+.emoji-1F392 { background-position: -7980px 0px; }
+.emoji-1F393 { background-position: -8000px 0px; }
+.emoji-1F394 { background-position: -8020px 0px; }
+.emoji-1F395 { background-position: -8040px 0px; }
+.emoji-1F396 { background-position: -8060px 0px; }
+.emoji-1F397 { background-position: -8080px 0px; }
+.emoji-1F398 { background-position: -8100px 0px; }
+.emoji-1F399 { background-position: -8120px 0px; }
+.emoji-1F39A { background-position: -8140px 0px; }
+.emoji-1F39B { background-position: -8160px 0px; }
+.emoji-1F39C { background-position: -8180px 0px; }
+.emoji-1F39D { background-position: -8200px 0px; }
+.emoji-1F39E { background-position: -8220px 0px; }
+.emoji-1F39F { background-position: -8240px 0px; }
+.emoji-1F3A0 { background-position: -8260px 0px; }
+.emoji-1F3A1 { background-position: -8280px 0px; }
+.emoji-1F3A2 { background-position: -8300px 0px; }
+.emoji-1F3A3 { background-position: -8320px 0px; }
+.emoji-1F3A4 { background-position: -8340px 0px; }
+.emoji-1F3A5 { background-position: -8360px 0px; }
+.emoji-1F3A6 { background-position: -8380px 0px; }
+.emoji-1F3A7 { background-position: -8400px 0px; }
+.emoji-1F3A8 { background-position: -8420px 0px; }
+.emoji-1F3A9 { background-position: -8440px 0px; }
+.emoji-1F3AA { background-position: -8460px 0px; }
+.emoji-1F3AB { background-position: -8480px 0px; }
+.emoji-1F3AC { background-position: -8500px 0px; }
+.emoji-1F3AD { background-position: -8520px 0px; }
+.emoji-1F3AE { background-position: -8540px 0px; }
+.emoji-1F3AF { background-position: -8560px 0px; }
+.emoji-1F3B0 { background-position: -8580px 0px; }
+.emoji-1F3B1 { background-position: -8600px 0px; }
+.emoji-1F3B2 { background-position: -8620px 0px; }
+.emoji-1F3B3 { background-position: -8640px 0px; }
+.emoji-1F3B4 { background-position: -8660px 0px; }
+.emoji-1F3B5 { background-position: -8680px 0px; }
+.emoji-1F3B6 { background-position: -8700px 0px; }
+.emoji-1F3B7 { background-position: -8720px 0px; }
+.emoji-1F3B8 { background-position: -8740px 0px; }
+.emoji-1F3B9 { background-position: -8760px 0px; }
+.emoji-1F3BA { background-position: -8780px 0px; }
+.emoji-1F3BB { background-position: -8800px 0px; }
+.emoji-1F3BC { background-position: -8820px 0px; }
+.emoji-1F3BD { background-position: -8840px 0px; }
+.emoji-1F3BE { background-position: -8860px 0px; }
+.emoji-1F3BF { background-position: -8880px 0px; }
+.emoji-1F3C0 { background-position: -8900px 0px; }
+.emoji-1F3C1 { background-position: -8920px 0px; }
+.emoji-1F3C2 { background-position: -8940px 0px; }
+.emoji-1F3C3 { background-position: -8960px 0px; }
+.emoji-1F3C4 { background-position: -8980px 0px; }
+.emoji-1F3C5 { background-position: -9000px 0px; }
+.emoji-1F3C6 { background-position: -9020px 0px; }
+.emoji-1F3C7 { background-position: -9040px 0px; }
+.emoji-1F3C8 { background-position: -9060px 0px; }
+.emoji-1F3C9 { background-position: -9080px 0px; }
+.emoji-1F3CA { background-position: -9100px 0px; }
+.emoji-1F3CB { background-position: -9120px 0px; }
+.emoji-1F3CC { background-position: -9140px 0px; }
+.emoji-1F3CD { background-position: -9160px 0px; }
+.emoji-1F3CE { background-position: -9180px 0px; }
+.emoji-1F3D4 { background-position: -9200px 0px; }
+.emoji-1F3D5 { background-position: -9220px 0px; }
+.emoji-1F3D6 { background-position: -9240px 0px; }
+.emoji-1F3D7 { background-position: -9260px 0px; }
+.emoji-1F3D8 { background-position: -9280px 0px; }
+.emoji-1F3D9 { background-position: -9300px 0px; }
+.emoji-1F3DA { background-position: -9320px 0px; }
+.emoji-1F3DB { background-position: -9340px 0px; }
+.emoji-1F3DC { background-position: -9360px 0px; }
+.emoji-1F3DD { background-position: -9380px 0px; }
+.emoji-1F3DE { background-position: -9400px 0px; }
+.emoji-1F3DF { background-position: -9420px 0px; }
+.emoji-1F3E0 { background-position: -9440px 0px; }
+.emoji-1F3E1 { background-position: -9460px 0px; }
+.emoji-1F3E2 { background-position: -9480px 0px; }
+.emoji-1F3E3 { background-position: -9500px 0px; }
+.emoji-1F3E4 { background-position: -9520px 0px; }
+.emoji-1F3E5 { background-position: -9540px 0px; }
+.emoji-1F3E6 { background-position: -9560px 0px; }
+.emoji-1F3E7 { background-position: -9580px 0px; }
+.emoji-1F3E8 { background-position: -9600px 0px; }
+.emoji-1F3E9 { background-position: -9620px 0px; }
+.emoji-1F3EA { background-position: -9640px 0px; }
+.emoji-1F3EB { background-position: -9660px 0px; }
+.emoji-1F3EC { background-position: -9680px 0px; }
+.emoji-1F3ED { background-position: -9700px 0px; }
+.emoji-1F3EE { background-position: -9720px 0px; }
+.emoji-1F3EF { background-position: -9740px 0px; }
+.emoji-1F3F0 { background-position: -9760px 0px; }
+.emoji-1F3F1 { background-position: -9780px 0px; }
+.emoji-1F3F2 { background-position: -9800px 0px; }
+.emoji-1F3F3 { background-position: -9820px 0px; }
+.emoji-1F3F4 { background-position: -9840px 0px; }
+.emoji-1F3F5 { background-position: -9860px 0px; }
+.emoji-1F3F6 { background-position: -9880px 0px; }
+.emoji-1F3F7 { background-position: -9900px 0px; }
+.emoji-1F400 { background-position: -9920px 0px; }
+.emoji-1F401 { background-position: -9940px 0px; }
+.emoji-1F402 { background-position: -9960px 0px; }
+.emoji-1F403 { background-position: -9980px 0px; }
+.emoji-1F404 { background-position: -10000px 0px; }
+.emoji-1F405 { background-position: -10020px 0px; }
+.emoji-1F406 { background-position: -10040px 0px; }
+.emoji-1F407 { background-position: -10060px 0px; }
+.emoji-1F408 { background-position: -10080px 0px; }
+.emoji-1F409 { background-position: -10100px 0px; }
+.emoji-1F40A { background-position: -10120px 0px; }
+.emoji-1F40B { background-position: -10140px 0px; }
+.emoji-1F40C { background-position: -10160px 0px; }
+.emoji-1F40D { background-position: -10180px 0px; }
+.emoji-1F40E { background-position: -10200px 0px; }
+.emoji-1F40F { background-position: -10220px 0px; }
+.emoji-1F410 { background-position: -10240px 0px; }
+.emoji-1F411 { background-position: -10260px 0px; }
+.emoji-1F412 { background-position: -10280px 0px; }
+.emoji-1F413 { background-position: -10300px 0px; }
+.emoji-1F414 { background-position: -10320px 0px; }
+.emoji-1F415 { background-position: -10340px 0px; }
+.emoji-1F416 { background-position: -10360px 0px; }
+.emoji-1F417 { background-position: -10380px 0px; }
+.emoji-1F418 { background-position: -10400px 0px; }
+.emoji-1F419 { background-position: -10420px 0px; }
+.emoji-1F41A { background-position: -10440px 0px; }
+.emoji-1F41B { background-position: -10460px 0px; }
+.emoji-1F41C { background-position: -10480px 0px; }
+.emoji-1F41D { background-position: -10500px 0px; }
+.emoji-1F41E { background-position: -10520px 0px; }
+.emoji-1F41F { background-position: -10540px 0px; }
+.emoji-1F420 { background-position: -10560px 0px; }
+.emoji-1F421 { background-position: -10580px 0px; }
+.emoji-1F422 { background-position: -10600px 0px; }
+.emoji-1F423 { background-position: -10620px 0px; }
+.emoji-1F424 { background-position: -10640px 0px; }
+.emoji-1F425 { background-position: -10660px 0px; }
+.emoji-1F426 { background-position: -10680px 0px; }
+.emoji-1F427 { background-position: -10700px 0px; }
+.emoji-1F428 { background-position: -10720px 0px; }
+.emoji-1F429 { background-position: -10740px 0px; }
+.emoji-1F42A { background-position: -10760px 0px; }
+.emoji-1F42B { background-position: -10780px 0px; }
+.emoji-1F42C { background-position: -10800px 0px; }
+.emoji-1F42D { background-position: -10820px 0px; }
+.emoji-1F42E { background-position: -10840px 0px; }
+.emoji-1F42F { background-position: -10860px 0px; }
+.emoji-1F430 { background-position: -10880px 0px; }
+.emoji-1F431 { background-position: -10900px 0px; }
+.emoji-1F432 { background-position: -10920px 0px; }
+.emoji-1F433 { background-position: -10940px 0px; }
+.emoji-1F434 { background-position: -10960px 0px; }
+.emoji-1F435 { background-position: -10980px 0px; }
+.emoji-1F436 { background-position: -11000px 0px; }
+.emoji-1F437 { background-position: -11020px 0px; }
+.emoji-1F438 { background-position: -11040px 0px; }
+.emoji-1F439 { background-position: -11060px 0px; }
+.emoji-1F43A { background-position: -11080px 0px; }
+.emoji-1F43B { background-position: -11100px 0px; }
+.emoji-1F43C { background-position: -11120px 0px; }
+.emoji-1F43D { background-position: -11140px 0px; }
+.emoji-1F43E { background-position: -11160px 0px; }
+.emoji-1F43F { background-position: -11180px 0px; }
+.emoji-1F440 { background-position: -11200px 0px; }
+.emoji-1F441 { background-position: -11220px 0px; }
+.emoji-1F442 { background-position: -11240px 0px; }
+.emoji-1F443 { background-position: -11260px 0px; }
+.emoji-1F444 { background-position: -11280px 0px; }
+.emoji-1F445 { background-position: -11300px 0px; }
+.emoji-1F446 { background-position: -11320px 0px; }
+.emoji-1F447 { background-position: -11340px 0px; }
+.emoji-1F448 { background-position: -11360px 0px; }
+.emoji-1F449 { background-position: -11380px 0px; }
+.emoji-1F44A { background-position: -11400px 0px; }
+.emoji-1F44B { background-position: -11420px 0px; }
+.emoji-1F44C { background-position: -11440px 0px; }
+.emoji-1F44D { background-position: -11460px 0px; }
+.emoji-1F44E { background-position: -11480px 0px; }
+.emoji-1F44F { background-position: -11500px 0px; }
+.emoji-1F450 { background-position: -11520px 0px; }
+.emoji-1F451 { background-position: -11540px 0px; }
+.emoji-1F452 { background-position: -11560px 0px; }
+.emoji-1F453 { background-position: -11580px 0px; }
+.emoji-1F454 { background-position: -11600px 0px; }
+.emoji-1F455 { background-position: -11620px 0px; }
+.emoji-1F456 { background-position: -11640px 0px; }
+.emoji-1F457 { background-position: -11660px 0px; }
+.emoji-1F458 { background-position: -11680px 0px; }
+.emoji-1F459 { background-position: -11700px 0px; }
+.emoji-1F45A { background-position: -11720px 0px; }
+.emoji-1F45B { background-position: -11740px 0px; }
+.emoji-1F45C { background-position: -11760px 0px; }
+.emoji-1F45D { background-position: -11780px 0px; }
+.emoji-1F45E { background-position: -11800px 0px; }
+.emoji-1F45F { background-position: -11820px 0px; }
+.emoji-1F460 { background-position: -11840px 0px; }
+.emoji-1F461 { background-position: -11860px 0px; }
+.emoji-1F462 { background-position: -11880px 0px; }
+.emoji-1F463 { background-position: -11900px 0px; }
+.emoji-1F464 { background-position: -11920px 0px; }
+.emoji-1F465 { background-position: -11940px 0px; }
+.emoji-1F466 { background-position: -11960px 0px; }
+.emoji-1F467 { background-position: -11980px 0px; }
+.emoji-1F468 { background-position: -12000px 0px; }
+.emoji-1F468-1F468-1F466 { background-position: -12020px 0px; }
+.emoji-1F468-1F468-1F466-1F466 { background-position: -12040px 0px; }
+.emoji-1F468-1F468-1F467 { background-position: -12060px 0px; }
+.emoji-1F468-1F468-1F467-1F466 { background-position: -12080px 0px; }
+.emoji-1F468-1F468-1F467-1F467 { background-position: -12100px 0px; }
+.emoji-1F468-1F469-1F466-1F466 { background-position: -12120px 0px; }
+.emoji-1F468-1F469-1F467 { background-position: -12140px 0px; }
+.emoji-1F468-1F469-1F467-1F466 { background-position: -12160px 0px; }
+.emoji-1F468-1F469-1F467-1F467 { background-position: -12180px 0px; }
+.emoji-1F468-2764-1F468 { background-position: -12200px 0px; }
+.emoji-1F468-2764-1F48B-1F468 { background-position: -12220px 0px; }
+.emoji-1F469 { background-position: -12240px 0px; }
+.emoji-1F469-1F469-1F466 { background-position: -12260px 0px; }
+.emoji-1F469-1F469-1F466-1F466 { background-position: -12280px 0px; }
+.emoji-1F469-1F469-1F467 { background-position: -12300px 0px; }
+.emoji-1F469-1F469-1F467-1F466 { background-position: -12320px 0px; }
+.emoji-1F469-1F469-1F467-1F467 { background-position: -12340px 0px; }
+.emoji-1F469-2764-1F469 { background-position: -12360px 0px; }
+.emoji-1F469-2764-1F48B-1F469 { background-position: -12380px 0px; }
+.emoji-1F46A { background-position: -12400px 0px; }
+.emoji-1F46B { background-position: -12420px 0px; }
+.emoji-1F46C { background-position: -12440px 0px; }
+.emoji-1F46D { background-position: -12460px 0px; }
+.emoji-1F46E { background-position: -12480px 0px; }
+.emoji-1F46F { background-position: -12500px 0px; }
+.emoji-1F470 { background-position: -12520px 0px; }
+.emoji-1F471 { background-position: -12540px 0px; }
+.emoji-1F472 { background-position: -12560px 0px; }
+.emoji-1F473 { background-position: -12580px 0px; }
+.emoji-1F474 { background-position: -12600px 0px; }
+.emoji-1F475 { background-position: -12620px 0px; }
+.emoji-1F476 { background-position: -12640px 0px; }
+.emoji-1F477 { background-position: -12660px 0px; }
+.emoji-1F478 { background-position: -12680px 0px; }
+.emoji-1F479 { background-position: -12700px 0px; }
+.emoji-1F47A { background-position: -12720px 0px; }
+.emoji-1F47B { background-position: -12740px 0px; }
+.emoji-1F47C { background-position: -12760px 0px; }
+.emoji-1F47D { background-position: -12780px 0px; }
+.emoji-1F47E { background-position: -12800px 0px; }
+.emoji-1F47F { background-position: -12820px 0px; }
+.emoji-1F480 { background-position: -12840px 0px; }
+.emoji-1F481 { background-position: -12860px 0px; }
+.emoji-1F482 { background-position: -12880px 0px; }
+.emoji-1F483 { background-position: -12900px 0px; }
+.emoji-1F484 { background-position: -12920px 0px; }
+.emoji-1F485 { background-position: -12940px 0px; }
+.emoji-1F486 { background-position: -12960px 0px; }
+.emoji-1F487 { background-position: -12980px 0px; }
+.emoji-1F488 { background-position: -13000px 0px; }
+.emoji-1F489 { background-position: -13020px 0px; }
+.emoji-1F48A { background-position: -13040px 0px; }
+.emoji-1F48B { background-position: -13060px 0px; }
+.emoji-1F48C { background-position: -13080px 0px; }
+.emoji-1F48D { background-position: -13100px 0px; }
+.emoji-1F48E { background-position: -13120px 0px; }
+.emoji-1F48F { background-position: -13140px 0px; }
+.emoji-1F490 { background-position: -13160px 0px; }
+.emoji-1F491 { background-position: -13180px 0px; }
+.emoji-1F492 { background-position: -13200px 0px; }
+.emoji-1F493 { background-position: -13220px 0px; }
+.emoji-1F494 { background-position: -13240px 0px; }
+.emoji-1F495 { background-position: -13260px 0px; }
+.emoji-1F496 { background-position: -13280px 0px; }
+.emoji-1F497 { background-position: -13300px 0px; }
+.emoji-1F498 { background-position: -13320px 0px; }
+.emoji-1F499 { background-position: -13340px 0px; }
+.emoji-1F49A { background-position: -13360px 0px; }
+.emoji-1F49B { background-position: -13380px 0px; }
+.emoji-1F49C { background-position: -13400px 0px; }
+.emoji-1F49D { background-position: -13420px 0px; }
+.emoji-1F49E { background-position: -13440px 0px; }
+.emoji-1F49F { background-position: -13460px 0px; }
+.emoji-1F4A0 { background-position: -13480px 0px; }
+.emoji-1F4A1 { background-position: -13500px 0px; }
+.emoji-1F4A2 { background-position: -13520px 0px; }
+.emoji-1F4A3 { background-position: -13540px 0px; }
+.emoji-1F4A4 { background-position: -13560px 0px; }
+.emoji-1F4A5 { background-position: -13580px 0px; }
+.emoji-1F4A6 { background-position: -13600px 0px; }
+.emoji-1F4A7 { background-position: -13620px 0px; }
+.emoji-1F4A8 { background-position: -13640px 0px; }
+.emoji-1F4A9 { background-position: -13660px 0px; }
+.emoji-1F4AA { background-position: -13680px 0px; }
+.emoji-1F4AB { background-position: -13700px 0px; }
+.emoji-1F4AC { background-position: -13720px 0px; }
+.emoji-1F4AD { background-position: -13740px 0px; }
+.emoji-1F4AE { background-position: -13760px 0px; }
+.emoji-1F4AF { background-position: -13780px 0px; }
+.emoji-1F4B0 { background-position: -13800px 0px; }
+.emoji-1F4B1 { background-position: -13820px 0px; }
+.emoji-1F4B2 { background-position: -13840px 0px; }
+.emoji-1F4B3 { background-position: -13860px 0px; }
+.emoji-1F4B4 { background-position: -13880px 0px; }
+.emoji-1F4B5 { background-position: -13900px 0px; }
+.emoji-1F4B6 { background-position: -13920px 0px; }
+.emoji-1F4B7 { background-position: -13940px 0px; }
+.emoji-1F4B8 { background-position: -13960px 0px; }
+.emoji-1F4B9 { background-position: -13980px 0px; }
+.emoji-1F4BA { background-position: -14000px 0px; }
+.emoji-1F4BB { background-position: -14020px 0px; }
+.emoji-1F4BC { background-position: -14040px 0px; }
+.emoji-1F4BD { background-position: -14060px 0px; }
+.emoji-1F4BE { background-position: -14080px 0px; }
+.emoji-1F4BF { background-position: -14100px 0px; }
+.emoji-1F4C0 { background-position: -14120px 0px; }
+.emoji-1F4C1 { background-position: -14140px 0px; }
+.emoji-1F4C2 { background-position: -14160px 0px; }
+.emoji-1F4C3 { background-position: -14180px 0px; }
+.emoji-1F4C4 { background-position: -14200px 0px; }
+.emoji-1F4C5 { background-position: -14220px 0px; }
+.emoji-1F4C6 { background-position: -14240px 0px; }
+.emoji-1F4C7 { background-position: -14260px 0px; }
+.emoji-1F4C8 { background-position: -14280px 0px; }
+.emoji-1F4C9 { background-position: -14300px 0px; }
+.emoji-1F4CA { background-position: -14320px 0px; }
+.emoji-1F4CB { background-position: -14340px 0px; }
+.emoji-1F4CC { background-position: -14360px 0px; }
+.emoji-1F4CD { background-position: -14380px 0px; }
+.emoji-1F4CE { background-position: -14400px 0px; }
+.emoji-1F4CF { background-position: -14420px 0px; }
+.emoji-1F4D0 { background-position: -14440px 0px; }
+.emoji-1F4D1 { background-position: -14460px 0px; }
+.emoji-1F4D2 { background-position: -14480px 0px; }
+.emoji-1F4D3 { background-position: -14500px 0px; }
+.emoji-1F4D4 { background-position: -14520px 0px; }
+.emoji-1F4D5 { background-position: -14540px 0px; }
+.emoji-1F4D6 { background-position: -14560px 0px; }
+.emoji-1F4D7 { background-position: -14580px 0px; }
+.emoji-1F4D8 { background-position: -14600px 0px; }
+.emoji-1F4D9 { background-position: -14620px 0px; }
+.emoji-1F4DA { background-position: -14640px 0px; }
+.emoji-1F4DB { background-position: -14660px 0px; }
+.emoji-1F4DC { background-position: -14680px 0px; }
+.emoji-1F4DD { background-position: -14700px 0px; }
+.emoji-1F4DE { background-position: -14720px 0px; }
+.emoji-1F4DF { background-position: -14740px 0px; }
+.emoji-1F4E0 { background-position: -14760px 0px; }
+.emoji-1F4E1 { background-position: -14780px 0px; }
+.emoji-1F4E2 { background-position: -14800px 0px; }
+.emoji-1F4E3 { background-position: -14820px 0px; }
+.emoji-1F4E4 { background-position: -14840px 0px; }
+.emoji-1F4E5 { background-position: -14860px 0px; }
+.emoji-1F4E6 { background-position: -14880px 0px; }
+.emoji-1F4E7 { background-position: -14900px 0px; }
+.emoji-1F4E8 { background-position: -14920px 0px; }
+.emoji-1F4E9 { background-position: -14940px 0px; }
+.emoji-1F4EA { background-position: -14960px 0px; }
+.emoji-1F4EB { background-position: -14980px 0px; }
+.emoji-1F4EC { background-position: -15000px 0px; }
+.emoji-1F4ED { background-position: -15020px 0px; }
+.emoji-1F4EE { background-position: -15040px 0px; }
+.emoji-1F4EF { background-position: -15060px 0px; }
+.emoji-1F4F0 { background-position: -15080px 0px; }
+.emoji-1F4F1 { background-position: -15100px 0px; }
+.emoji-1F4F2 { background-position: -15120px 0px; }
+.emoji-1F4F3 { background-position: -15140px 0px; }
+.emoji-1F4F4 { background-position: -15160px 0px; }
+.emoji-1F4F5 { background-position: -15180px 0px; }
+.emoji-1F4F6 { background-position: -15200px 0px; }
+.emoji-1F4F7 { background-position: -15220px 0px; }
+.emoji-1F4F8 { background-position: -15240px 0px; }
+.emoji-1F4F9 { background-position: -15260px 0px; }
+.emoji-1F4FA { background-position: -15280px 0px; }
+.emoji-1F4FB { background-position: -15300px 0px; }
+.emoji-1F4FC { background-position: -15320px 0px; }
+.emoji-1F4FD { background-position: -15340px 0px; }
+.emoji-1F4FE { background-position: -15360px 0px; }
+.emoji-1F500 { background-position: -15380px 0px; }
+.emoji-1F501 { background-position: -15400px 0px; }
+.emoji-1F502 { background-position: -15420px 0px; }
+.emoji-1F503 { background-position: -15440px 0px; }
+.emoji-1F504 { background-position: -15460px 0px; }
+.emoji-1F505 { background-position: -15480px 0px; }
+.emoji-1F506 { background-position: -15500px 0px; }
+.emoji-1F507 { background-position: -15520px 0px; }
+.emoji-1F508 { background-position: -15540px 0px; }
+.emoji-1F509 { background-position: -15560px 0px; }
+.emoji-1F50A { background-position: -15580px 0px; }
+.emoji-1F50B { background-position: -15600px 0px; }
+.emoji-1F50C { background-position: -15620px 0px; }
+.emoji-1F50D { background-position: -15640px 0px; }
+.emoji-1F50E { background-position: -15660px 0px; }
+.emoji-1F50F { background-position: -15680px 0px; }
+.emoji-1F510 { background-position: -15700px 0px; }
+.emoji-1F511 { background-position: -15720px 0px; }
+.emoji-1F512 { background-position: -15740px 0px; }
+.emoji-1F513 { background-position: -15760px 0px; }
+.emoji-1F514 { background-position: -15780px 0px; }
+.emoji-1F515 { background-position: -15800px 0px; }
+.emoji-1F516 { background-position: -15820px 0px; }
+.emoji-1F517 { background-position: -15840px 0px; }
+.emoji-1F518 { background-position: -15860px 0px; }
+.emoji-1F519 { background-position: -15880px 0px; }
+.emoji-1F51A { background-position: -15900px 0px; }
+.emoji-1F51B { background-position: -15920px 0px; }
+.emoji-1F51C { background-position: -15940px 0px; }
+.emoji-1F51D { background-position: -15960px 0px; }
+.emoji-1F51E { background-position: -15980px 0px; }
+.emoji-1F51F { background-position: -16000px 0px; }
+.emoji-1F520 { background-position: -16020px 0px; }
+.emoji-1F521 { background-position: -16040px 0px; }
+.emoji-1F522 { background-position: -16060px 0px; }
+.emoji-1F523 { background-position: -16080px 0px; }
+.emoji-1F524 { background-position: -16100px 0px; }
+.emoji-1F525 { background-position: -16120px 0px; }
+.emoji-1F526 { background-position: -16140px 0px; }
+.emoji-1F527 { background-position: -16160px 0px; }
+.emoji-1F528 { background-position: -16180px 0px; }
+.emoji-1F529 { background-position: -16200px 0px; }
+.emoji-1F52A { background-position: -16220px 0px; }
+.emoji-1F52B { background-position: -16240px 0px; }
+.emoji-1F52C { background-position: -16260px 0px; }
+.emoji-1F52D { background-position: -16280px 0px; }
+.emoji-1F52E { background-position: -16300px 0px; }
+.emoji-1F52F { background-position: -16320px 0px; }
+.emoji-1F530 { background-position: -16340px 0px; }
+.emoji-1F531 { background-position: -16360px 0px; }
+.emoji-1F532 { background-position: -16380px 0px; }
+.emoji-1F533 { background-position: -16400px 0px; }
+.emoji-1F534 { background-position: -16420px 0px; }
+.emoji-1F535 { background-position: -16440px 0px; }
+.emoji-1F536 { background-position: -16460px 0px; }
+.emoji-1F537 { background-position: -16480px 0px; }
+.emoji-1F538 { background-position: -16500px 0px; }
+.emoji-1F539 { background-position: -16520px 0px; }
+.emoji-1F53A { background-position: -16540px 0px; }
+.emoji-1F53B { background-position: -16560px 0px; }
+.emoji-1F53C { background-position: -16580px 0px; }
+.emoji-1F53D { background-position: -16600px 0px; }
+.emoji-1F546 { background-position: -16620px 0px; }
+.emoji-1F547 { background-position: -16640px 0px; }
+.emoji-1F548 { background-position: -16660px 0px; }
+.emoji-1F549 { background-position: -16680px 0px; }
+.emoji-1F54A { background-position: -16700px 0px; }
+.emoji-1F550 { background-position: -16720px 0px; }
+.emoji-1F551 { background-position: -16740px 0px; }
+.emoji-1F552 { background-position: -16760px 0px; }
+.emoji-1F553 { background-position: -16780px 0px; }
+.emoji-1F554 { background-position: -16800px 0px; }
+.emoji-1F555 { background-position: -16820px 0px; }
+.emoji-1F556 { background-position: -16840px 0px; }
+.emoji-1F557 { background-position: -16860px 0px; }
+.emoji-1F558 { background-position: -16880px 0px; }
+.emoji-1F559 { background-position: -16900px 0px; }
+.emoji-1F55A { background-position: -16920px 0px; }
+.emoji-1F55B { background-position: -16940px 0px; }
+.emoji-1F55C { background-position: -16960px 0px; }
+.emoji-1F55D { background-position: -16980px 0px; }
+.emoji-1F55E { background-position: -17000px 0px; }
+.emoji-1F55F { background-position: -17020px 0px; }
+.emoji-1F560 { background-position: -17040px 0px; }
+.emoji-1F561 { background-position: -17060px 0px; }
+.emoji-1F562 { background-position: -17080px 0px; }
+.emoji-1F563 { background-position: -17100px 0px; }
+.emoji-1F564 { background-position: -17120px 0px; }
+.emoji-1F565 { background-position: -17140px 0px; }
+.emoji-1F566 { background-position: -17160px 0px; }
+.emoji-1F567 { background-position: -17180px 0px; }
+.emoji-1F568 { background-position: -17200px 0px; }
+.emoji-1F569 { background-position: -17220px 0px; }
+.emoji-1F56A { background-position: -17240px 0px; }
+.emoji-1F56B { background-position: -17260px 0px; }
+.emoji-1F56C { background-position: -17280px 0px; }
+.emoji-1F56D { background-position: -17300px 0px; }
+.emoji-1F56E { background-position: -17320px 0px; }
+.emoji-1F56F { background-position: -17340px 0px; }
+.emoji-1F570 { background-position: -17360px 0px; }
+.emoji-1F571 { background-position: -17380px 0px; }
+.emoji-1F572 { background-position: -17400px 0px; }
+.emoji-1F573 { background-position: -17420px 0px; }
+.emoji-1F574 { background-position: -17440px 0px; }
+.emoji-1F575 { background-position: -17460px 0px; }
+.emoji-1F576 { background-position: -17480px 0px; }
+.emoji-1F577 { background-position: -17500px 0px; }
+.emoji-1F578 { background-position: -17520px 0px; }
+.emoji-1F579 { background-position: -17540px 0px; }
+.emoji-1F57B { background-position: -17560px 0px; }
+.emoji-1F57E { background-position: -17580px 0px; }
+.emoji-1F57F { background-position: -17600px 0px; }
+.emoji-1F581 { background-position: -17620px 0px; }
+.emoji-1F582 { background-position: -17640px 0px; }
+.emoji-1F583 { background-position: -17660px 0px; }
+.emoji-1F585 { background-position: -17680px 0px; }
+.emoji-1F586 { background-position: -17700px 0px; }
+.emoji-1F587 { background-position: -17720px 0px; }
+.emoji-1F588 { background-position: -17740px 0px; }
+.emoji-1F589 { background-position: -17760px 0px; }
+.emoji-1F58A { background-position: -17780px 0px; }
+.emoji-1F58B { background-position: -17800px 0px; }
+.emoji-1F58C { background-position: -17820px 0px; }
+.emoji-1F58D { background-position: -17840px 0px; }
+.emoji-1F58E { background-position: -17860px 0px; }
+.emoji-1F58F { background-position: -17880px 0px; }
+.emoji-1F590 { background-position: -17900px 0px; }
+.emoji-1F591 { background-position: -17920px 0px; }
+.emoji-1F592 { background-position: -17940px 0px; }
+.emoji-1F593 { background-position: -17960px 0px; }
+.emoji-1F594 { background-position: -17980px 0px; }
+.emoji-1F595 { background-position: -18000px 0px; }
+.emoji-1F596 { background-position: -18020px 0px; }
+.emoji-1F597 { background-position: -18040px 0px; }
+.emoji-1F598 { background-position: -18060px 0px; }
+.emoji-1F599 { background-position: -18080px 0px; }
+.emoji-1F59E { background-position: -18100px 0px; }
+.emoji-1F59F { background-position: -18120px 0px; }
+.emoji-1F5A5 { background-position: -18140px 0px; }
+.emoji-1F5A6 { background-position: -18160px 0px; }
+.emoji-1F5A7 { background-position: -18180px 0px; }
+.emoji-1F5A8 { background-position: -18200px 0px; }
+.emoji-1F5A9 { background-position: -18220px 0px; }
+.emoji-1F5AA { background-position: -18240px 0px; }
+.emoji-1F5AB { background-position: -18260px 0px; }
+.emoji-1F5AD { background-position: -18280px 0px; }
+.emoji-1F5AE { background-position: -18300px 0px; }
+.emoji-1F5AF { background-position: -18320px 0px; }
+.emoji-1F5B2 { background-position: -18340px 0px; }
+.emoji-1F5B3 { background-position: -18360px 0px; }
+.emoji-1F5B4 { background-position: -18380px 0px; }
+.emoji-1F5B8 { background-position: -18400px 0px; }
+.emoji-1F5B9 { background-position: -18420px 0px; }
+.emoji-1F5BC { background-position: -18440px 0px; }
+.emoji-1F5BD { background-position: -18460px 0px; }
+.emoji-1F5BE { background-position: -18480px 0px; }
+.emoji-1F5C0 { background-position: -18500px 0px; }
+.emoji-1F5C1 { background-position: -18520px 0px; }
+.emoji-1F5C2 { background-position: -18540px 0px; }
+.emoji-1F5C3 { background-position: -18560px 0px; }
+.emoji-1F5C4 { background-position: -18580px 0px; }
+.emoji-1F5C6 { background-position: -18600px 0px; }
+.emoji-1F5C7 { background-position: -18620px 0px; }
+.emoji-1F5C9 { background-position: -18640px 0px; }
+.emoji-1F5CA { background-position: -18660px 0px; }
+.emoji-1F5CE { background-position: -18680px 0px; }
+.emoji-1F5CF { background-position: -18700px 0px; }
+.emoji-1F5D0 { background-position: -18720px 0px; }
+.emoji-1F5D1 { background-position: -18740px 0px; }
+.emoji-1F5D2 { background-position: -18760px 0px; }
+.emoji-1F5D3 { background-position: -18780px 0px; }
+.emoji-1F5D4 { background-position: -18800px 0px; }
+.emoji-1F5D8 { background-position: -18820px 0px; }
+.emoji-1F5D9 { background-position: -18840px 0px; }
+.emoji-1F5DC { background-position: -18860px 0px; }
+.emoji-1F5DD { background-position: -18880px 0px; }
+.emoji-1F5DE { background-position: -18900px 0px; }
+.emoji-1F5E0 { background-position: -18920px 0px; }
+.emoji-1F5E1 { background-position: -18940px 0px; }
+.emoji-1F5E2 { background-position: -18960px 0px; }
+.emoji-1F5E3 { background-position: -18980px 0px; }
+.emoji-1F5E8 { background-position: -19000px 0px; }
+.emoji-1F5E9 { background-position: -19020px 0px; }
+.emoji-1F5EA { background-position: -19040px 0px; }
+.emoji-1F5EB { background-position: -19060px 0px; }
+.emoji-1F5EC { background-position: -19080px 0px; }
+.emoji-1F5ED { background-position: -19100px 0px; }
+.emoji-1F5EE { background-position: -19120px 0px; }
+.emoji-1F5EF { background-position: -19140px 0px; }
+.emoji-1F5F0 { background-position: -19160px 0px; }
+.emoji-1F5F1 { background-position: -19180px 0px; }
+.emoji-1F5F2 { background-position: -19200px 0px; }
+.emoji-1F5F3 { background-position: -19220px 0px; }
+.emoji-1F5F4 { background-position: -19240px 0px; }
+.emoji-1F5F5 { background-position: -19260px 0px; }
+.emoji-1F5F8 { background-position: -19280px 0px; }
+.emoji-1F5F9 { background-position: -19300px 0px; }
+.emoji-1F5FA { background-position: -19320px 0px; }
+.emoji-1F5FB { background-position: -19340px 0px; }
+.emoji-1F5FC { background-position: -19360px 0px; }
+.emoji-1F5FD { background-position: -19380px 0px; }
+.emoji-1F5FE { background-position: -19400px 0px; }
+.emoji-1F5FF { background-position: -19420px 0px; }
+.emoji-1F600 { background-position: -19440px 0px; }
+.emoji-1F601 { background-position: -19460px 0px; }
+.emoji-1F602 { background-position: -19480px 0px; }
+.emoji-1F603 { background-position: -19500px 0px; }
+.emoji-1F604 { background-position: -19520px 0px; }
+.emoji-1F605 { background-position: -19540px 0px; }
+.emoji-1F606 { background-position: -19560px 0px; }
+.emoji-1F607 { background-position: -19580px 0px; }
+.emoji-1F608 { background-position: -19600px 0px; }
+.emoji-1F609 { background-position: -19620px 0px; }
+.emoji-1F60A { background-position: -19640px 0px; }
+.emoji-1F60B { background-position: -19660px 0px; }
+.emoji-1F60C { background-position: -19680px 0px; }
+.emoji-1F60D { background-position: -19700px 0px; }
+.emoji-1F60E { background-position: -19720px 0px; }
+.emoji-1F60F { background-position: -19740px 0px; }
+.emoji-1F610 { background-position: -19760px 0px; }
+.emoji-1F611 { background-position: -19780px 0px; }
+.emoji-1F612 { background-position: -19800px 0px; }
+.emoji-1F613 { background-position: -19820px 0px; }
+.emoji-1F614 { background-position: -19840px 0px; }
+.emoji-1F615 { background-position: -19860px 0px; }
+.emoji-1F616 { background-position: -19880px 0px; }
+.emoji-1F617 { background-position: -19900px 0px; }
+.emoji-1F618 { background-position: -19920px 0px; }
+.emoji-1F619 { background-position: -19940px 0px; }
+.emoji-1F61A { background-position: -19960px 0px; }
+.emoji-1F61B { background-position: -19980px 0px; }
+.emoji-1F61C { background-position: -20000px 0px; }
+.emoji-1F61D { background-position: -20020px 0px; }
+.emoji-1F61E { background-position: -20040px 0px; }
+.emoji-1F61F { background-position: -20060px 0px; }
+.emoji-1F620 { background-position: -20080px 0px; }
+.emoji-1F621 { background-position: -20100px 0px; }
+.emoji-1F622 { background-position: -20120px 0px; }
+.emoji-1F623 { background-position: -20140px 0px; }
+.emoji-1F624 { background-position: -20160px 0px; }
+.emoji-1F625 { background-position: -20180px 0px; }
+.emoji-1F626 { background-position: -20200px 0px; }
+.emoji-1F627 { background-position: -20220px 0px; }
+.emoji-1F628 { background-position: -20240px 0px; }
+.emoji-1F629 { background-position: -20260px 0px; }
+.emoji-1F62A { background-position: -20280px 0px; }
+.emoji-1F62B { background-position: -20300px 0px; }
+.emoji-1F62C { background-position: -20320px 0px; }
+.emoji-1F62D { background-position: -20340px 0px; }
+.emoji-1F62E { background-position: -20360px 0px; }
+.emoji-1F62F { background-position: -20380px 0px; }
+.emoji-1F630 { background-position: -20400px 0px; }
+.emoji-1F631 { background-position: -20420px 0px; }
+.emoji-1F632 { background-position: -20440px 0px; }
+.emoji-1F633 { background-position: -20460px 0px; }
+.emoji-1F634 { background-position: -20480px 0px; }
+.emoji-1F635 { background-position: -20500px 0px; }
+.emoji-1F636 { background-position: -20520px 0px; }
+.emoji-1F637 { background-position: -20540px 0px; }
+.emoji-1F638 { background-position: -20560px 0px; }
+.emoji-1F639 { background-position: -20580px 0px; }
+.emoji-1F63A { background-position: -20600px 0px; }
+.emoji-1F63B { background-position: -20620px 0px; }
+.emoji-1F63C { background-position: -20640px 0px; }
+.emoji-1F63D { background-position: -20660px 0px; }
+.emoji-1F63E { background-position: -20680px 0px; }
+.emoji-1F63F { background-position: -20700px 0px; }
+.emoji-1F640 { background-position: -20720px 0px; }
+.emoji-1F641 { background-position: -20740px 0px; }
+.emoji-1F642 { background-position: -20760px 0px; }
+.emoji-1F645 { background-position: -20780px 0px; }
+.emoji-1F646 { background-position: -20800px 0px; }
+.emoji-1F647 { background-position: -20820px 0px; }
+.emoji-1F648 { background-position: -20840px 0px; }
+.emoji-1F649 { background-position: -20860px 0px; }
+.emoji-1F64A { background-position: -20880px 0px; }
+.emoji-1F64B { background-position: -20900px 0px; }
+.emoji-1F64C { background-position: -20920px 0px; }
+.emoji-1F64D { background-position: -20940px 0px; }
+.emoji-1F64E { background-position: -20960px 0px; }
+.emoji-1F64F { background-position: -20980px 0px; }
+.emoji-1F680 { background-position: -21000px 0px; }
+.emoji-1F681 { background-position: -21020px 0px; }
+.emoji-1F682 { background-position: -21040px 0px; }
+.emoji-1F683 { background-position: -21060px 0px; }
+.emoji-1F684 { background-position: -21080px 0px; }
+.emoji-1F685 { background-position: -21100px 0px; }
+.emoji-1F686 { background-position: -21120px 0px; }
+.emoji-1F687 { background-position: -21140px 0px; }
+.emoji-1F688 { background-position: -21160px 0px; }
+.emoji-1F689 { background-position: -21180px 0px; }
+.emoji-1F68A { background-position: -21200px 0px; }
+.emoji-1F68B { background-position: -21220px 0px; }
+.emoji-1F68C { background-position: -21240px 0px; }
+.emoji-1F68D { background-position: -21260px 0px; }
+.emoji-1F68E { background-position: -21280px 0px; }
+.emoji-1F68F { background-position: -21300px 0px; }
+.emoji-1F690 { background-position: -21320px 0px; }
+.emoji-1F691 { background-position: -21340px 0px; }
+.emoji-1F692 { background-position: -21360px 0px; }
+.emoji-1F693 { background-position: -21380px 0px; }
+.emoji-1F694 { background-position: -21400px 0px; }
+.emoji-1F695 { background-position: -21420px 0px; }
+.emoji-1F696 { background-position: -21440px 0px; }
+.emoji-1F697 { background-position: -21460px 0px; }
+.emoji-1F698 { background-position: -21480px 0px; }
+.emoji-1F699 { background-position: -21500px 0px; }
+.emoji-1F69A { background-position: -21520px 0px; }
+.emoji-1F69B { background-position: -21540px 0px; }
+.emoji-1F69C { background-position: -21560px 0px; }
+.emoji-1F69D { background-position: -21580px 0px; }
+.emoji-1F69E { background-position: -21600px 0px; }
+.emoji-1F69F { background-position: -21620px 0px; }
+.emoji-1F6A0 { background-position: -21640px 0px; }
+.emoji-1F6A1 { background-position: -21660px 0px; }
+.emoji-1F6A2 { background-position: -21680px 0px; }
+.emoji-1F6A3 { background-position: -21700px 0px; }
+.emoji-1F6A4 { background-position: -21720px 0px; }
+.emoji-1F6A5 { background-position: -21740px 0px; }
+.emoji-1F6A6 { background-position: -21760px 0px; }
+.emoji-1F6A7 { background-position: -21780px 0px; }
+.emoji-1F6A8 { background-position: -21800px 0px; }
+.emoji-1F6A9 { background-position: -21820px 0px; }
+.emoji-1F6AA { background-position: -21840px 0px; }
+.emoji-1F6AB { background-position: -21860px 0px; }
+.emoji-1F6AC { background-position: -21880px 0px; }
+.emoji-1F6AD { background-position: -21900px 0px; }
+.emoji-1F6AE { background-position: -21920px 0px; }
+.emoji-1F6AF { background-position: -21940px 0px; }
+.emoji-1F6B0 { background-position: -21960px 0px; }
+.emoji-1F6B1 { background-position: -21980px 0px; }
+.emoji-1F6B2 { background-position: -22000px 0px; }
+.emoji-1F6B3 { background-position: -22020px 0px; }
+.emoji-1F6B4 { background-position: -22040px 0px; }
+.emoji-1F6B5 { background-position: -22060px 0px; }
+.emoji-1F6B6 { background-position: -22080px 0px; }
+.emoji-1F6B7 { background-position: -22100px 0px; }
+.emoji-1F6B8 { background-position: -22120px 0px; }
+.emoji-1F6B9 { background-position: -22140px 0px; }
+.emoji-1F6BA { background-position: -22160px 0px; }
+.emoji-1F6BB { background-position: -22180px 0px; }
+.emoji-1F6BC { background-position: -22200px 0px; }
+.emoji-1F6BD { background-position: -22220px 0px; }
+.emoji-1F6BE { background-position: -22240px 0px; }
+.emoji-1F6BF { background-position: -22260px 0px; }
+.emoji-1F6C0 { background-position: -22280px 0px; }
+.emoji-1F6C1 { background-position: -22300px 0px; }
+.emoji-1F6C2 { background-position: -22320px 0px; }
+.emoji-1F6C3 { background-position: -22340px 0px; }
+.emoji-1F6C4 { background-position: -22360px 0px; }
+.emoji-1F6C5 { background-position: -22380px 0px; }
+.emoji-1F6C6 { background-position: -22400px 0px; }
+.emoji-1F6C7 { background-position: -22420px 0px; }
+.emoji-1F6C8 { background-position: -22440px 0px; }
+.emoji-1F6C9 { background-position: -22460px 0px; }
+.emoji-1F6CA { background-position: -22480px 0px; }
+.emoji-1F6CB { background-position: -22500px 0px; }
+.emoji-1F6CC { background-position: -22520px 0px; }
+.emoji-1F6CD { background-position: -22540px 0px; }
+.emoji-1F6CE { background-position: -22560px 0px; }
+.emoji-1F6CF { background-position: -22580px 0px; }
+.emoji-1F6E0 { background-position: -22600px 0px; }
+.emoji-1F6E1 { background-position: -22620px 0px; }
+.emoji-1F6E2 { background-position: -22640px 0px; }
+.emoji-1F6E3 { background-position: -22660px 0px; }
+.emoji-1F6E4 { background-position: -22680px 0px; }
+.emoji-1F6E5 { background-position: -22700px 0px; }
+.emoji-1F6E6 { background-position: -22720px 0px; }
+.emoji-1F6E7 { background-position: -22740px 0px; }
+.emoji-1F6E8 { background-position: -22760px 0px; }
+.emoji-1F6E9 { background-position: -22780px 0px; }
+.emoji-1F6EA { background-position: -22800px 0px; }
+.emoji-1F6EB { background-position: -22820px 0px; }
+.emoji-1F6EC { background-position: -22840px 0px; }
+.emoji-1F6F0 { background-position: -22860px 0px; }
+.emoji-1F6F1 { background-position: -22880px 0px; }
+.emoji-1F6F2 { background-position: -22900px 0px; }
+.emoji-1F6F3 { background-position: -22920px 0px; }
+.emoji-203C { background-position: -22940px 0px; }
+.emoji-2049 { background-position: -22960px 0px; }
+.emoji-2122 { background-position: -22980px 0px; }
+.emoji-2139 { background-position: -23000px 0px; }
+.emoji-2194 { background-position: -23020px 0px; }
+.emoji-2195 { background-position: -23040px 0px; }
+.emoji-2196 { background-position: -23060px 0px; }
+.emoji-2197 { background-position: -23080px 0px; }
+.emoji-2198 { background-position: -23100px 0px; }
+.emoji-2199 { background-position: -23120px 0px; }
+.emoji-21A9 { background-position: -23140px 0px; }
+.emoji-21AA { background-position: -23160px 0px; }
+.emoji-231A { background-position: -23180px 0px; }
+.emoji-231B { background-position: -23200px 0px; }
+.emoji-23E9 { background-position: -23220px 0px; }
+.emoji-23EA { background-position: -23240px 0px; }
+.emoji-23EB { background-position: -23260px 0px; }
+.emoji-23EC { background-position: -23280px 0px; }
+.emoji-23F0 { background-position: -23300px 0px; }
+.emoji-23F3 { background-position: -23320px 0px; }
+.emoji-24C2 { background-position: -23340px 0px; }
+.emoji-25AA { background-position: -23360px 0px; }
+.emoji-25AB { background-position: -23380px 0px; }
+.emoji-25B6 { background-position: -23400px 0px; }
+.emoji-25C0 { background-position: -23420px 0px; }
+.emoji-25FB { background-position: -23440px 0px; }
+.emoji-25FC { background-position: -23460px 0px; }
+.emoji-25FD { background-position: -23480px 0px; }
+.emoji-25FE { background-position: -23500px 0px; }
+.emoji-2600 { background-position: -23520px 0px; }
+.emoji-2601 { background-position: -23540px 0px; }
+.emoji-260E { background-position: -23560px 0px; }
+.emoji-2611 { background-position: -23580px 0px; }
+.emoji-2614 { background-position: -23600px 0px; }
+.emoji-2615 { background-position: -23620px 0px; }
+.emoji-261D { background-position: -23640px 0px; }
+.emoji-263A { background-position: -23660px 0px; }
+.emoji-2648 { background-position: -23680px 0px; }
+.emoji-2649 { background-position: -23700px 0px; }
+.emoji-264A { background-position: -23720px 0px; }
+.emoji-264B { background-position: -23740px 0px; }
+.emoji-264C { background-position: -23760px 0px; }
+.emoji-264D { background-position: -23780px 0px; }
+.emoji-264E { background-position: -23800px 0px; }
+.emoji-264F { background-position: -23820px 0px; }
+.emoji-2650 { background-position: -23840px 0px; }
+.emoji-2651 { background-position: -23860px 0px; }
+.emoji-2652 { background-position: -23880px 0px; }
+.emoji-2653 { background-position: -23900px 0px; }
+.emoji-2660 { background-position: -23920px 0px; }
+.emoji-2663 { background-position: -23940px 0px; }
+.emoji-2665 { background-position: -23960px 0px; }
+.emoji-2666 { background-position: -23980px 0px; }
+.emoji-2668 { background-position: -24000px 0px; }
+.emoji-267B { background-position: -24020px 0px; }
+.emoji-267F { background-position: -24040px 0px; }
+.emoji-2693 { background-position: -24060px 0px; }
+.emoji-26A0 { background-position: -24080px 0px; }
+.emoji-26A1 { background-position: -24100px 0px; }
+.emoji-26AA { background-position: -24120px 0px; }
+.emoji-26AB { background-position: -24140px 0px; }
+.emoji-26BD { background-position: -24160px 0px; }
+.emoji-26BE { background-position: -24180px 0px; }
+.emoji-26C4 { background-position: -24200px 0px; }
+.emoji-26C5 { background-position: -24220px 0px; }
+.emoji-26CE { background-position: -24240px 0px; }
+.emoji-26D4 { background-position: -24260px 0px; }
+.emoji-26EA { background-position: -24280px 0px; }
+.emoji-26F2 { background-position: -24300px 0px; }
+.emoji-26F3 { background-position: -24320px 0px; }
+.emoji-26F5 { background-position: -24340px 0px; }
+.emoji-26FA { background-position: -24360px 0px; }
+.emoji-26FD { background-position: -24380px 0px; }
+.emoji-2702 { background-position: -24400px 0px; }
+.emoji-2705 { background-position: -24420px 0px; }
+.emoji-2708 { background-position: -24440px 0px; }
+.emoji-2709 { background-position: -24460px 0px; }
+.emoji-270A { background-position: -24480px 0px; }
+.emoji-270B { background-position: -24500px 0px; }
+.emoji-270C { background-position: -24520px 0px; }
+.emoji-270F { background-position: -24540px 0px; }
+.emoji-2712 { background-position: -24560px 0px; }
+.emoji-2714 { background-position: -24580px 0px; }
+.emoji-2716 { background-position: -24600px 0px; }
+.emoji-2728 { background-position: -24620px 0px; }
+.emoji-2733 { background-position: -24640px 0px; }
+.emoji-2734 { background-position: -24660px 0px; }
+.emoji-2744 { background-position: -24680px 0px; }
+.emoji-2747 { background-position: -24700px 0px; }
+.emoji-274C { background-position: -24720px 0px; }
+.emoji-274E { background-position: -24740px 0px; }
+.emoji-2753 { background-position: -24760px 0px; }
+.emoji-2754 { background-position: -24780px 0px; }
+.emoji-2755 { background-position: -24800px 0px; }
+.emoji-2757 { background-position: -24820px 0px; }
+.emoji-2764 { background-position: -24840px 0px; }
+.emoji-2795 { background-position: -24860px 0px; }
+.emoji-2796 { background-position: -24880px 0px; }
+.emoji-2797 { background-position: -24900px 0px; }
+.emoji-27A1 { background-position: -24920px 0px; }
+.emoji-27B0 { background-position: -24940px 0px; }
+.emoji-27BF { background-position: -24960px 0px; }
+.emoji-2934 { background-position: -24980px 0px; }
+.emoji-2935 { background-position: -25000px 0px; }
+.emoji-2B05 { background-position: -25020px 0px; }
+.emoji-2B06 { background-position: -25040px 0px; }
+.emoji-2B07 { background-position: -25060px 0px; }
+.emoji-2B1B { background-position: -25080px 0px; }
+.emoji-2B1C { background-position: -25100px 0px; }
+.emoji-2B50 { background-position: -25120px 0px; }
+.emoji-2B55 { background-position: -25140px 0px; }
+.emoji-3030 { background-position: -25160px 0px; }
+.emoji-303D { background-position: -25180px 0px; }
+.emoji-3297 { background-position: -25200px 0px; }
+.emoji-3299 { background-position: -25220px 0px; }
\ No newline at end of file
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 797a0af3720a66f78d2b55040d71e43c3cebd768..9da273a0b6b399a664c35eda53d3efcce6c94581 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -18,7 +18,7 @@
 
     &.affix {
       position: fixed;
-      top: 60px;
+      top: 70px;
       margin-right: 35px;
     }
   }
@@ -36,33 +36,12 @@
 }
 
 .issuable-details {
-  .issue-title {
-    margin: 0;
-    font-size: 23px;
-    color: #313236;
-  }
-
-  .description {
-    margin-top: 6px;
-
-    p:last-child {
-      margin-bottom: 0;
-    }
-  }
-
   section {
-    border-right: 1px solid #ECEEF1;
+    border-right: 1px solid $border-white-light;
 
-    > .tab-content {
+    .issuable-discussion {
       margin-right: 1px;
     }
-
-    .issue-discussion > .gray-content-block,
-    > .gray-content-block {
-      margin-top: 0;
-      border-top: none;
-      margin-right: -15px;
-    }
   }
 }
 
@@ -136,21 +115,3 @@
     margin-right: 2px;
   }
 }
-
-.issuable-title {
-  margin: -$gl-padding;
-  padding: 7px $gl-padding;
-  margin-bottom: 0px;
-  border-bottom: 1px solid $border-color;
-  color: #5c5d5e;
-  font-size: 16px;
-  line-height: 42px;
-
-  .author {
-    color: #5c5d5e;
-  }
-
-  .issuable-id {
-    color: #5c5d5e;
-  }
-}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index a652b65502ffaafaa9759b705f6135b53052c76d..a02a3a72e79fc54bd8f1fa865e79c65823f29064 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -141,11 +141,6 @@ form.edit-issue {
   }
 }
 
-.issue-closed-by-widget {
-  padding: 16px 0;
-  margin: 0px;
-}
-
 .issue-form .select2-container {
   width: 250px !important;
 }
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 502e9552acdba8c2b12e573507fd3f71dda7afdc..82effde0bf3b49e8bb8aed35f1c2387292dfc6ea 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -191,7 +191,7 @@
   .btn-clipboard {
     @extend .pull-right;
 
-    margin-right: 18px;
+    margin-right: 20px;
     margin-top: 5px;
     position: absolute;
     right: 0;
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index e1a72af00130ea5234072ea58e118c13e1b0800a..d86259f93fbcfe672cf0fab9d84d03ad196a21fe 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -75,17 +75,15 @@
 
 .common-note-form {
   margin: 0;
-  background: #F7F8FA;
+  background: #fff;
   padding: $gl-padding;
   margin-left: -$gl-padding;
   margin-right: -$gl-padding;
-  border-right: 1px solid $border-color;
-  border-top: 1px solid $border-color;
   margin-bottom: -$gl-padding;
 }
 
 .note-form-actions {
-  background: #F9F9F9;
+  background: #fff;
 
   .note-form-option {
     margin-top: 8px;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 4dff87abaa4ec2d556c336014544c62cefcebf25..72b0ed29a698b1d2e95b79c8c654f61784a2165f 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -128,7 +128,7 @@ ul.notes {
     }
 
     &:last-child {
-      border-bottom: none;
+      border-bottom: 1px solid $border-color;
     }
   }
 }
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 2ded32dba123746e77ff1d319852ac21f3ad1755..cff3edb7ed26c2a5caa0a062001c5af7d705017f 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -91,21 +91,83 @@
     }
   }
 
-  .input-group {
+  .git-clone-holder {
     display: inline-table;
     position: relative;
-    top: 17px;
   }
 
   .project-repo-buttons {
     margin-top: 12px;
     margin-bottom: 0px;
 
+    .count-buttons {
+      display: block;
+      margin-bottom: 12px;
+    }
+
     .btn {
       @include btn-gray;
-
+      text-transform: none;
+    }
+    .count-with-arrow {
+      display: inline-block;
+      position: relative;
+      margin-left: 4px;
+
+      .arrow {
+        &:before {
+          content: '';
+          display: inline-block;
+          position: absolute;
+          width: 0;
+          height: 0;
+          border-color: transparent;
+          border-style: solid;
+          top: 50%;
+          left: 0;
+          margin-top: -6px;
+          border-width: 7px 5px 7px 0;
+          border-right-color: #dce0e5;
+        }
+
+        &:after {
+          content: '';
+          position: absolute;
+          width: 0;
+          height: 0;
+          border-color: transparent;
+          border-style: solid;
+          top: 50%;
+          left: 1px;
+          margin-top: -9px;
+          border-width: 10px 7px 10px 0;
+          border-right-color: #FFF;
+        }
+      }
       .count {
+        @include btn-gray;
         display: inline-block;
+        background: white;
+        border-radius: 2px;
+        border-width: 1px;
+        border-style: solid;
+        font-size: 13px;
+        font-weight: 600;
+        line-height: 20px;
+        padding: 11px 16px;
+        letter-spacing: .4px;
+        padding: 10px;
+        text-align: center;
+        vertical-align: middle;
+        touch-action: manipulation;
+        cursor: pointer;
+        background-image: none;
+        white-space: nowrap;
+        margin: 0 11px 0px 4px;
+
+        &:hover {
+          background: #FFF;
+        }
       }
     }
   }
@@ -125,6 +187,13 @@
     margin-right: 45px;
   }
 
+  .clone-options {
+    display: table-cell;
+    a.btn {
+      width: 100%;
+    }
+  }
+
   .form-control {
     cursor: auto;
     @extend .monospace;
@@ -335,6 +404,38 @@ ul.nav.nav-projects-tabs {
   }
 }
 
+.top-area {
+  border-bottom: 1px solid #EEE;
+  margin: 0 -16px;
+  padding: 0 $gl-padding;
+
+  ul.left-top-menu {
+    display: inline-block;
+    width: 50%;
+    margin-bottom: 0px;
+    border-bottom: none;
+  }
+
+  .projects-search-form {
+    width: 50%;
+    display: inline-block;
+    float: right;
+    padding-top: 7px;
+    text-align: right;
+
+    .btn-green {
+      margin-top: -2px;
+      margin-left: 10px;
+    }
+  }
+
+  @media (max-width: $screen-xs-max) {
+    .projects-search-form {
+      padding-top: 15px;
+    }
+  }
+}
+
 .fork-namespaces {
   .fork-thumbnail {
     text-align: center;
@@ -412,11 +513,18 @@ pre.light-well {
 
 .projects-search-form {
   margin: -$gl-padding;
-  background-color: #f8fafc;
   padding: $gl-padding;
   margin-bottom: 0px;
-  border-top: 1px solid #e7e9ed;
-  border-bottom: 1px solid #e7e9ed;
+
+  input {
+    display: inline-block;
+    width: calc(100% - 151px);
+  }
+
+  .btn {
+    display: inline-block;
+    width: 135px;
+  }
 }
 
 .git-empty {
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index a7d3b2197f15f82636018d1e00e6ad6b6792256d..4b6ef035673b595f1b835a7444e40abc0cb70ae4 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -35,3 +35,20 @@
     border-color: $gl-warning;
   }
 }
+
+.ci-status-icon-success {
+  @extend .cgreen;
+}
+.ci-status-icon-failed {
+  @extend .cred;
+}
+.ci-status-icon-running,
+.ci-status-icon-pending {
+  // These are standard text color
+}
+.ci-status-icon-canceled,
+.ci-status-icon-disabled,
+.ci-status-icon-not-found,
+.ci-status-icon-skipped {
+  @extend .cgray;
+}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 9dd16f8c7353a7b8304efa6ae265ce89bcb23332..10e736fd362248e9e9f0aa6e3f07fbd11202742a 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -49,6 +49,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
       :default_branch_protection,
       :signup_enabled,
       :signin_enabled,
+      :require_two_factor_authentication,
+      :two_factor_grace_period,
       :gravatar_enabled,
       :twitter_sharing_enabled,
       :sign_in_text,
@@ -65,6 +67,17 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
       :user_oauth_applications,
       :shared_runners_enabled,
       :max_artifacts_size,
+      :metrics_enabled,
+      :metrics_host,
+      :metrics_port,
+      :metrics_username,
+      :metrics_password,
+      :metrics_pool_size,
+      :metrics_timeout,
+      :metrics_method_call_threshold,
+      :recaptcha_enabled,
+      :recaptcha_site_key,
+      :recaptcha_private_key,
       restricted_visibility_levels: [],
       import_sources: []
     )
diff --git a/app/controllers/admin/identities_controller.rb b/app/controllers/admin/identities_controller.rb
index d28614731f9211cf66fb1ef3af5e76a2c3fe972d..e383fe38ea68352c5ba172a396a978f805a27527 100644
--- a/app/controllers/admin/identities_controller.rb
+++ b/app/controllers/admin/identities_controller.rb
@@ -1,6 +1,21 @@
 class Admin::IdentitiesController < Admin::ApplicationController
   before_action :user
-  before_action :identity, except: :index
+  before_action :identity, except: [:index, :new, :create]
+
+  def new
+    @identity = Identity.new
+  end
+
+  def create
+    @identity = Identity.new(identity_params)
+    @identity.user_id = user.id
+
+    if @identity.save
+      redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully created.'
+    else
+      render :new
+    end
+  end
 
   def index
     @identities = @user.identities
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 0d182e8eb04d92fded1152636459a9be917d82c1..d9a37a4d45f8bccd7961e0e731ecd46f3b95eef0 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -10,8 +10,10 @@ class ApplicationController < ActionController::Base
 
   before_action :authenticate_user_from_token!
   before_action :authenticate_user!
+  before_action :validate_user_service_ticket!
   before_action :reject_blocked!
   before_action :check_password_expiration
+  before_action :check_2fa_requirement
   before_action :ldap_security_check
   before_action :default_headers
   before_action :add_gon_variables
@@ -202,12 +204,32 @@ class ApplicationController < ActionController::Base
     end
   end
 
+  def validate_user_service_ticket!
+    return unless signed_in? && session[:service_tickets]
+
+    valid = session[:service_tickets].all? do |provider, ticket|
+      Gitlab::OAuth::Session.valid?(provider, ticket)
+    end
+
+    unless valid
+      session[:service_tickets] = nil
+      sign_out current_user
+      redirect_to new_user_session_path
+    end
+  end
+
   def check_password_expiration
     if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now  && !current_user.ldap_user?
       redirect_to new_profile_password_path and return
     end
   end
 
+  def check_2fa_requirement
+    if two_factor_authentication_required? && current_user && !current_user.two_factor_enabled && !skip_two_factor?
+      redirect_to new_profile_two_factor_auth_path
+    end
+  end
+
   def ldap_security_check
     if current_user && current_user.requires_ldap_check?
       unless Gitlab::LDAP::Access.allowed?(current_user)
@@ -342,6 +364,23 @@ class ApplicationController < ActionController::Base
     current_application_settings.import_sources.include?('git')
   end
 
+  def two_factor_authentication_required?
+    current_application_settings.require_two_factor_authentication
+  end
+
+  def two_factor_grace_period
+    current_application_settings.two_factor_grace_period
+  end
+
+  def two_factor_grace_period_expired?
+    date = current_user.otp_grace_period_started_at
+    date && (date + two_factor_grace_period.hours) < Time.current
+  end
+
+  def skip_two_factor?
+    session[:skip_tfa] && session[:skip_tfa] > Time.current
+  end
+
   def redirect_to_home_page_url?
     # If user is not signed-in and tries to access root_path - redirect him to landing page
     # Don't redirect to the default URL to prevent endless redirections
diff --git a/app/controllers/ci/lints_controller.rb b/app/controllers/ci/lints_controller.rb
index 7ed78ff8e989492249818665fc8ae1a7c6ea5784..e782a51e7eb93dce8ca605dd2236cd749a272119 100644
--- a/app/controllers/ci/lints_controller.rb
+++ b/app/controllers/ci/lints_controller.rb
@@ -19,8 +19,10 @@ module Ci
       @error = e.message
       @status = false
     rescue
-      @error = "Undefined error"
+      @error = 'Undefined error'
       @status = false
+    ensure
+      render :show
     end
   end
 end
diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb
new file mode 100644
index 0000000000000000000000000000000000000000..62127a090817e01355ec314399db321c0d378a56
--- /dev/null
+++ b/app/controllers/concerns/creates_commit.rb
@@ -0,0 +1,103 @@
+module CreatesCommit
+  extend ActiveSupport::Concern
+
+  def create_commit(service, success_path:, failure_path:, failure_view: nil, success_notice: nil)
+    set_commit_variables
+
+    commit_params = @commit_params.merge(
+      source_project: @project,
+      source_branch: @ref,
+      target_branch: @target_branch
+    )
+
+    result = service.new(@tree_edit_project, current_user, commit_params).execute
+
+    if result[:status] == :success
+      flash[:notice] = success_notice || "Your changes have been successfully committed."
+
+      if create_merge_request?
+        success_path = new_merge_request_path
+        target = different_project? ? "project" : "branch"
+        flash[:notice] << " You can now submit a merge request to get this change into the original #{target}."
+      end
+
+      respond_to do |format|
+        format.html { redirect_to success_path }
+        format.json { render json: { message: "success", filePath: success_path } }
+      end
+    else
+      flash[:alert] = result[:message]
+      respond_to do |format|
+        format.html do
+          if failure_view
+            render failure_view
+          else
+            redirect_to failure_path
+          end
+        end
+        format.json { render json: { message: "failed", filePath: failure_path } }
+      end
+    end
+  end
+
+  def authorize_edit_tree!
+    return if can?(current_user, :push_code, project)
+    return if current_user && current_user.already_forked?(project)
+
+    access_denied!
+  end
+
+  private
+
+  def new_merge_request_path
+    new_namespace_project_merge_request_path(
+      @mr_source_project.namespace,
+      @mr_source_project,
+      merge_request: {
+        source_project_id: @mr_source_project.id,
+        target_project_id: @mr_target_project.id,
+        source_branch: @mr_source_branch,
+        target_branch: @mr_target_branch
+      }
+    )
+  end
+
+  def different_project?
+    @mr_source_project != @mr_target_project
+  end
+
+  def different_branch?
+    @mr_source_branch != @mr_target_branch || different_project?
+  end
+
+  def create_merge_request?
+    params[:create_merge_request].present? && different_branch?
+  end
+
+  def set_commit_variables
+    @mr_source_branch = @target_branch
+
+    if can?(current_user, :push_code, @project)
+      # Edit file in this project
+      @tree_edit_project = @project
+      @mr_source_project = @project
+
+      if @project.forked?
+        # Merge request from this project to fork origin
+        @mr_target_project = @project.forked_from_project
+        @mr_target_branch = @mr_target_project.repository.root_ref
+      else
+        # Merge request to this project
+        @mr_target_project = @project
+        @mr_target_branch = @ref
+      end
+    else
+      # Edit file in fork
+      @tree_edit_project = current_user.fork_of(@project)
+      # Merge request from fork to this project
+      @mr_source_project = @tree_edit_project
+      @mr_target_project = @project
+      @mr_target_branch = @mr_target_project.repository.root_ref
+    end
+  end
+end
diff --git a/app/controllers/concerns/creates_merge_request_for_commit.rb b/app/controllers/concerns/creates_merge_request_for_commit.rb
deleted file mode 100644
index c75278221585a95a18e591f63c1e7839727ace7a..0000000000000000000000000000000000000000
--- a/app/controllers/concerns/creates_merge_request_for_commit.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-module CreatesMergeRequestForCommit
-  extend ActiveSupport::Concern
-
-  def new_merge_request_path
-    if @project.forked?
-      target_project = @project.forked_from_project || @project
-      target_branch = target_project.repository.root_ref
-    else
-      target_project = @project
-      target_branch = @ref
-    end
-
-    new_namespace_project_merge_request_path(
-      @project.namespace,
-      @project,
-      merge_request: {
-        source_project_id: @project.id,
-        target_project_id: target_project.id,
-        source_branch: @new_branch,
-        target_branch: target_branch
-      }
-    )
-  end
-
-  def create_merge_request?
-    params[:create_merge_request] && @new_branch != @ref
-  end
-end
diff --git a/app/controllers/dashboard/snippets_controller.rb b/app/controllers/dashboard/snippets_controller.rb
index f4354c6d8cad9665e6cbb4cd69a6191338202915..b3594d82530b09d06bfb97e2ec7189b42bf98313 100644
--- a/app/controllers/dashboard/snippets_controller.rb
+++ b/app/controllers/dashboard/snippets_controller.rb
@@ -1,6 +1,7 @@
 class Dashboard::SnippetsController < Dashboard::ApplicationController
   def index
-    @snippets = SnippetsFinder.new.execute(current_user,
+    @snippets = SnippetsFinder.new.execute(
+      current_user,
       filter: :by_user,
       user: current_user,
       scope: params[:scope]
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index f809fa7500a09fd37a547238198987e80501f5ea..4cad98b8e98bdd7044ed442ea0622418e14f016a 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -1,6 +1,6 @@
 class OmniauthCallbacksController < Devise::OmniauthCallbacksController
 
-  protect_from_forgery except: [:kerberos, :saml]
+  protect_from_forgery except: [:kerberos, :saml, :cas3]
 
   Gitlab.config.omniauth.providers.each do |provider|
     define_method provider['name'] do
@@ -42,6 +42,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
     render 'errors/omniauth_error', layout: "errors", status: 422
   end
 
+  def cas3
+    ticket = params['ticket']
+    if ticket
+      handle_service_ticket oauth['provider'], ticket
+    end
+    handle_omniauth
+  end
+
   private
 
   def handle_omniauth
@@ -84,6 +92,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
     redirect_to new_user_session_path
   end
 
+  def handle_service_ticket provider, ticket
+    Gitlab::OAuth::Session.create provider, ticket
+    session[:service_tickets] ||= {}
+    session[:service_tickets][provider] = ticket
+  end
+
   def oauth
     @oauth ||= request.env['omniauth.auth']
   end
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index e6b99be37fb7fab9bcf2190321a3df0e446b050f..6e91d9b4ad96791adb21a9288b2ac54857d63688 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -1,8 +1,22 @@
 class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
+  skip_before_action :check_2fa_requirement
+
   def new
     unless current_user.otp_secret
       current_user.otp_secret = User.generate_otp_secret(32)
-      current_user.save!
+    end
+
+    unless current_user.otp_grace_period_started_at && two_factor_grace_period
+      current_user.otp_grace_period_started_at = Time.current
+    end
+
+    current_user.save! if current_user.changed?
+
+    if two_factor_grace_period_expired?
+      flash.now[:alert] = 'You must configure Two-Factor Authentication in your account.'
+    else
+      grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
+      flash.now[:alert] = "You must configure Two-Factor Authentication in your account until #{l(grace_period_deadline)}."
     end
 
     @qr_code = build_qr_code
@@ -34,6 +48,15 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
     redirect_to profile_account_path
   end
 
+  def skip
+    if two_factor_grace_period_expired?
+      redirect_to new_profile_two_factor_auth_path, alert: 'Cannot skip two factor authentication setup'
+    else
+      session[:skip_tfa] = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
+      redirect_to root_path
+    end
+  end
+
   private
 
   def build_qr_code
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 6216368293637cbd528cb589f0f25e573cf785c7..c56a3497bb2d096cb00231fa979148c0c22c8037 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -1,7 +1,7 @@
 # Controller for viewing a file's blame
 class Projects::BlobController < Projects::ApplicationController
   include ExtractsPath
-  include CreatesMergeRequestForCommit
+  include CreatesCommit
   include ActionView::Helpers::SanitizeHelper
 
   # Raised when given an invalid file path
@@ -9,21 +9,21 @@ class Projects::BlobController < Projects::ApplicationController
 
   before_action :require_non_empty_project, except: [:new, :create]
   before_action :authorize_download_code!
-  before_action :authorize_push_code!, only: [:destroy, :create]
+  before_action :authorize_edit_tree!, only: [:new, :create, :edit, :update, :destroy]
   before_action :assign_blob_vars
   before_action :commit, except: [:new, :create]
   before_action :blob, except: [:new, :create]
   before_action :from_merge_request, only: [:edit, :update]
   before_action :require_branch_head, only: [:edit, :update]
   before_action :editor_variables, except: [:show, :preview, :diff]
-  before_action :after_edit_path, only: [:edit, :update]
 
   def new
     commit unless @repository.empty?
   end
 
   def create
-    create_commit(Files::CreateService, success_path: after_create_path,
+    create_commit(Files::CreateService, success_notice: "The file has been successfully created.",
+                                        success_path: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)),
                                         failure_view: :new,
                                         failure_path: namespace_project_new_blob_path(@project.namespace, @project, @ref))
   end
@@ -36,6 +36,14 @@ class Projects::BlobController < Projects::ApplicationController
   end
 
   def update
+    after_edit_path =
+      if from_merge_request && @target_branch == @ref
+        diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) +
+          "#file-path-#{hexdigest(@path)}"
+      else
+        namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @path))
+      end
+
     create_commit(Files::UpdateService, success_path: after_edit_path,
                                         failure_view: :edit,
                                         failure_path: namespace_project_blob_path(@project.namespace, @project, @id))
@@ -50,15 +58,10 @@ class Projects::BlobController < Projects::ApplicationController
   end
 
   def destroy
-    result = Files::DeleteService.new(@project, current_user, @commit_params).execute
-
-    if result[:status] == :success
-      flash[:notice] = "Your changes have been successfully committed"
-      redirect_to after_destroy_path
-    else
-      flash[:alert] = result[:message]
-      render :show
-    end
+    create_commit(Files::DeleteService, success_notice: "The file has been successfully deleted.",
+                                        success_path: namespace_project_tree_path(@project.namespace, @project, @target_branch),
+                                        failure_view: :show,
+                                        failure_path: namespace_project_blob_path(@project.namespace, @project, @id))
   end
 
   def diff
@@ -108,74 +111,13 @@ class Projects::BlobController < Projects::ApplicationController
     render_404
   end
 
-  def create_commit(service, success_path:, failure_view:, failure_path:)
-    result = service.new(@project, current_user, @commit_params).execute
-
-    if result[:status] == :success
-      flash[:notice] = "Your changes have been successfully committed"
-      respond_to do |format|
-        format.html { redirect_to success_path }
-        format.json { render json: { message: "success", filePath: success_path } }
-      end
-    else
-      flash[:alert] = result[:message]
-      respond_to do |format|
-        format.html { render failure_view }
-        format.json { render json: { message: "failed", filePath: failure_path } }
-      end
-    end
-  end
-
-  def after_create_path
-    @after_create_path ||=
-      if create_merge_request?
-        new_merge_request_path
-      else
-        namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @file_path))
-      end
-  end
-
-  def after_edit_path
-    @after_edit_path ||=
-      if create_merge_request?
-        new_merge_request_path
-      elsif from_merge_request && @new_branch == @ref
-        diffs_namespace_project_merge_request_path(from_merge_request.target_project.namespace, from_merge_request.target_project, from_merge_request) +
-          "#file-path-#{hexdigest(@path)}"
-      else
-        namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @path))
-      end
-  end
-
-  def after_destroy_path
-    @after_destroy_path ||=
-      if create_merge_request?
-        new_merge_request_path
-      else
-        namespace_project_tree_path(@project.namespace, @project, @new_branch)
-      end
-  end
-
   def from_merge_request
     # If blob edit was initiated from merge request page
     @from_merge_request ||= MergeRequest.find_by(id: params[:from_merge_request_id])
   end
 
-  def sanitized_new_branch_name
-    sanitize(strip_tags(params[:new_branch]))
-  end
-
   def editor_variables
-    @current_branch = @ref
-
-    @new_branch =
-      if params[:new_branch].present?
-        sanitized_new_branch_name
-      elsif ::Gitlab::GitAccess.new(current_user, @project).can_push_to_branch?(@ref)
-        @ref
-      else
-        @repository.next_patch_branch
-      end
+    @target_branch = params[:target_branch]
 
     @file_path =
       if action_name.to_s == 'create'
@@ -194,8 +136,6 @@ class Projects::BlobController < Projects::ApplicationController
 
     @commit_params = {
       file_path: @file_path,
-      current_branch: @current_branch,
-      target_branch: @new_branch,
       commit_message: params[:commit_message],
       file_content: params[:content],
       file_content_encoding: params[:encoding]
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index 58fb946dbc24c8a3a06e663f9b9deddf38dde2fb..04a88990bf4d68557cac40687203cdaca2188d6d 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -9,7 +9,7 @@ class Projects::CommitsController < Projects::ApplicationController
 
   def show
     @repo = @project.repository
-    @limit, @offset = (params[:limit] || 40), (params[:offset] || 0)
+    @limit, @offset = (params[:limit] || 40).to_i, (params[:offset] || 0).to_i
 
     @commits = @repo.commits(@ref, @path, @limit, @offset)
     @note_counts = project.notes.where(commit_id: @commits.map(&:id)).
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 8a785076bb7be6e88c8b0f48de2214ddb48e9bb0..750181f0c1932257d9e60fa465578f986a070d31 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -10,19 +10,35 @@ class Projects::ForksController < Projects::ApplicationController
 
   def create
     namespace = Namespace.find(params[:namespace_key])
-    @forked_project = ::Projects::ForkService.new(project, current_user, namespace: namespace).execute
+    
+    @forked_project = namespace.projects.find_by(path: project.path)
+    @forked_project = nil unless @forked_project && @forked_project.forked_from_project == project
+
+    @forked_project ||= ::Projects::ForkService.new(project, current_user, namespace: namespace).execute
 
     if @forked_project.saved? && @forked_project.forked?
       if @forked_project.import_in_progress?
-        redirect_to namespace_project_import_path(@forked_project.namespace, @forked_project)
+        redirect_to namespace_project_import_path(@forked_project.namespace, @forked_project, continue: continue_params)
       else
-        redirect_to(
-          namespace_project_path(@forked_project.namespace, @forked_project),
-          notice: 'Project was successfully forked.'
-        )
+        if continue_params
+          redirect_to continue_params[:to], notice: continue_params[:notice]
+        else
+          redirect_to namespace_project_path(@forked_project.namespace, @forked_project), notice: "The project was successfully forked."
+        end
       end
     else
       render :error
     end
   end
+
+  private
+
+  def continue_params
+    continue_params = params[:continue]
+    if continue_params
+      continue_params.permit(:to, :notice, :notice_now)
+    else
+      nil
+    end
+  end
 end
diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb
index fb8788f0818bbbd7d4b022b1dab647ec45035460..8d8035ef5ff9a993b161358a66f1f13e80016367 100644
--- a/app/controllers/projects/imports_controller.rb
+++ b/app/controllers/projects/imports_controller.rb
@@ -1,7 +1,7 @@
 class Projects::ImportsController < Projects::ApplicationController
   # Authorize
   before_action :authorize_admin_project!
-  before_action :require_no_repo
+  before_action :require_no_repo, except: :show
   before_action :redirect_if_progress, except: :show
 
   def new
@@ -24,21 +24,36 @@ class Projects::ImportsController < Projects::ApplicationController
   end
 
   def show
-    unless @project.import_in_progress?
-      if @project.import_finished?
-        redirect_to(project_path(@project)) and return
+    if @project.repository_exists? || @project.import_finished?
+      if continue_params
+        redirect_to continue_params[:to], notice: continue_params[:notice]
       else
-        redirect_to(new_namespace_project_import_path(@project.namespace,
-                                                      @project)) and return
+        redirect_to project_path(@project), notice: "The project was successfully forked."
       end
+    elsif @project.import_failed?
+      redirect_to new_namespace_project_import_path(@project.namespace, @project)
+    else
+      if continue_params && continue_params[:notice_now]
+        flash.now[:notice] = continue_params[:notice_now]
+      end
+      # Render
     end
   end
 
   private
 
+  def continue_params
+    continue_params = params[:continue]
+    if continue_params
+      continue_params.permit(:to, :notice, :notice_now)
+    else
+      nil
+    end
+  end
+
   def require_no_repo
     if @project.repository_exists? && !@project.import_in_progress?
-      redirect_to(namespace_project_path(@project.namespace, @project)) and return
+      redirect_to(namespace_project_path(@project.namespace, @project))
     end
   end
 
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index fffd90d87eb9c0885d45482260ffc249d146f47c..ab5c953189cfa6d86123fe9d8ac945a1b3903365 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -7,7 +7,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
   before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds]
   before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
   before_action :define_show_vars, only: [:show, :diffs, :commits, :builds]
-  before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds]
+  before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
   before_action :ensure_ref_fetched, only: [:show, :diffs, :commits, :builds]
 
   # Allow read any merge_request
@@ -153,11 +153,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
   end
 
   def merge_check
-    if @merge_request.unchecked?
-      @merge_request.check_if_can_be_merged
-    end
-
-    closes_issues
+    @merge_request.check_if_can_be_merged if @merge_request.unchecked?
 
     render partial: "projects/merge_requests/widget/show.html.haml", layout: false
   end
@@ -178,7 +174,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
 
     @merge_request.update(merge_error: nil)
 
-    if params[:merge_when_build_succeeds] && @merge_request.ci_commit && @merge_request.ci_commit.active?
+    if params[:merge_when_build_succeeds].present? && @merge_request.ci_commit && @merge_request.ci_commit.active?
       MergeRequests::MergeWhenBuildSucceedsService.new(@project, current_user, merge_params)
                                                       .execute(@merge_request)
       @status = :merge_when_build_succeeds
@@ -299,6 +295,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
 
   def define_widget_vars
     @ci_commit = @merge_request.ci_commit
+    closes_issues
   end
 
   def invalid_mr
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index ae6e9f6fd3857dd51a88b02f37fa46abb3955c85..6f1e186d4084d4eb4729a74b989785c48115ad6a 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -69,7 +69,7 @@ class Projects::NotesController < Projects::ApplicationController
     data = {
       author: current_user,
       is_award: true,
-      note: note_params[:note].gsub(":", '')
+      note: note_params[:note].delete(":")
     }
 
     note = noteable.notes.find_by(data)
@@ -139,7 +139,6 @@ class Projects::NotesController < Projects::ApplicationController
         discussion_id: note.discussion_id,
         html: note_to_html(note),
         award: note.is_award,
-        emoji_path: note.is_award ? view_context.image_url(::AwardEmoji.path_to_emoji_image(note.note)) : "",
         note: note.note,
         discussion_html: note_to_discussion_html(note),
         discussion_with_diff_html: note_to_discussion_with_diff_html(note)
diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb
index 6b52eccebf73a6f49406052ad28994b82324a39c..e49259c34b6d6c66be68593e72acc969f443695b 100644
--- a/app/controllers/projects/protected_branches_controller.rb
+++ b/app/controllers/projects/protected_branches_controller.rb
@@ -21,7 +21,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
 
     if protected_branch &&
        protected_branch.update_attributes(
-        developers_can_push: params[:developers_can_push]
+         developers_can_push: params[:developers_can_push]
        )
 
       respond_to do |format|
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 6e7590260ff0e3bfa6f88fc706e54054b0b14c32..8b2577aebe1e537dc368cac0598bfc1154650c30 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -1,5 +1,5 @@
 class Projects::ServicesController < Projects::ApplicationController
-  ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_version, :subdomain,
+  ALLOWED_PARAMS = [:title, :token, :type, :active, :api_key, :api_url, :api_version, :subdomain,
                     :room, :recipients, :project_url, :webhook,
                     :user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
                     :build_key, :server, :teamcity_url, :drone_url, :build_type,
@@ -10,7 +10,8 @@ class Projects::ServicesController < Projects::ApplicationController
                     :notify_only_broken_builds, :add_pusher,
                     :send_from_committer_email, :disable_diffs, :external_wiki_url,
                     :notify, :color,
-                    :server_host, :server_port, :default_irc_uri, :enable_ssl_verification]
+                    :server_host, :server_port, :default_irc_uri, :enable_ssl_verification,
+                    :jira_issue_transition_id]
 
   # Parameters to ignore if no value is specified
   FILTER_BLANK_PARAMS = [:password]
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index 8f272ad1281fef7306c646248ff67acf1f18465d..cb3ed0f6f9c25dabfb05247f6002bf2478330a3d 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -1,14 +1,14 @@
 # Controller for viewing a repository's file structure
 class Projects::TreeController < Projects::ApplicationController
   include ExtractsPath
-  include CreatesMergeRequestForCommit
+  include CreatesCommit
   include ActionView::Helpers::SanitizeHelper
 
   before_action :require_non_empty_project, except: [:new, :create]
   before_action :assign_ref_vars
   before_action :assign_dir_vars, only: [:create_dir]
   before_action :authorize_download_code!
-  before_action :authorize_push_code!, only: [:create_dir]
+  before_action :authorize_edit_tree!, only: [:create_dir]
 
   def show
     return render_404 unless @repository.commit(@ref)
@@ -34,44 +34,20 @@ class Projects::TreeController < Projects::ApplicationController
   def create_dir
     return render_404 unless @commit_params.values.all?
 
-    begin
-      result = Files::CreateDirService.new(@project, current_user, @commit_params).execute
-      message = result[:message]
-    rescue => e
-      message = e.to_s
-    end
-
-    if result && result[:status] == :success
-      flash[:notice] = "The directory has been successfully created"
-      respond_to do |format|
-        format.html { redirect_to after_create_dir_path }
-      end
-    else
-      flash[:alert] = message
-      respond_to do |format|
-        format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, @new_branch) }
-      end
-    end
+    create_commit(Files::CreateDirService,  success_notice: "The directory has been successfully created.",
+                                            success_path: namespace_project_tree_path(@project.namespace, @project, File.join(@target_branch, @dir_name)),
+                                            failure_path: namespace_project_tree_path(@project.namespace, @project, @ref))
   end
 
   private
 
   def assign_dir_vars
-    @new_branch = params[:new_branch].present? ? sanitize(strip_tags(params[:new_branch])) : @ref
+    @target_branch = params[:target_branch]
+
     @dir_name = File.join(@path, params[:dir_name])
     @commit_params = {
       file_path: @dir_name,
-      current_branch: @ref,
-      target_branch: @new_branch,
       commit_message: params[:commit_message],
     }
   end
-
-  def after_create_dir_path
-    if create_merge_request?
-      new_merge_request_path
-    else
-      namespace_project_blob_path(@project.namespace, @project, File.join(@new_branch, @dir_name))
-    end
-  end
 end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index bf5e25ff89514d0da9e62bdc76aa1cdc392ab52a..3004722bce033664de15775ab47227daf3e02f5b 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -171,14 +171,14 @@ class ProjectsController < ApplicationController
     @project.reload
 
     render json: {
-      html: view_to_html_string("projects/buttons/_star")
+      star_count: @project.star_count
     }
   end
 
   def markdown_preview
     text = params[:text]
 
-    ext = Gitlab::ReferenceExtractor.new(@project, current_user)
+    ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user)
     ext.analyze(text)
 
     render json: {
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 3b3dc86cb6852d64ee3855c0ebd43b609f8c519c..c48175a4c5ab25fb73277740ccab91e9e2df1bef 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -1,10 +1,21 @@
 class RegistrationsController < Devise::RegistrationsController
   before_action :signup_enabled?
+  include Recaptcha::Verify
 
   def new
     redirect_to(new_user_session_path)
   end
 
+  def create
+    if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
+      super
+    else
+      flash[:alert] = "There was an error with the reCAPTCHA code below. Please re-enter the code."
+      flash.delete :recaptcha_error
+      render action: 'new'
+    end
+  end
+
   def destroy
     DeleteUserService.new(current_user).execute(current_user)
 
@@ -38,4 +49,16 @@ class RegistrationsController < Devise::RegistrationsController
   def sign_up_params
     params.require(:user).permit(:username, :email, :name, :password, :password_confirmation)
   end
+
+  def resource_name
+    :user
+  end
+
+  def resource
+    @resource ||= User.new(sign_up_params)
+  end
+
+  def devise_mapping
+    @devise_mapping ||= Devise.mappings[:user]
+  end
 end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 1b60d3e27d0ae170a410d8ab43b9109b5e66695d..825f85199bef03a33d4daa608bf0f5c38c88c06d 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,9 +1,11 @@
 class SessionsController < Devise::SessionsController
   include AuthenticatesWithTwoFactor
+  include Recaptcha::ClientHelper
 
   prepend_before_action :authenticate_with_two_factor, only: [:create]
   prepend_before_action :store_redirect_path, only: [:new]
   before_action :auto_sign_in_with_provider, only: [:new]
+  before_action :load_recaptcha
 
   def new
     if Gitlab.config.ldap.enabled
@@ -40,7 +42,7 @@ class SessionsController < Devise::SessionsController
       User.find(session[:otp_user_id])
     end
   end
-  
+
   def store_redirect_path
     redirect_path =
       if request.referer.present? && (params['redirect_to_referer'] == 'yes')
@@ -87,14 +89,14 @@ class SessionsController < Devise::SessionsController
     provider = Gitlab.config.omniauth.auto_sign_in_with_provider
     return unless provider.present?
 
-    # Auto sign in with an Omniauth provider only if the standard "you need to sign-in" alert is 
-    # registered or no alert at all. In case of another alert (such as a blocked user), it is safer  
+    # Auto sign in with an Omniauth provider only if the standard "you need to sign-in" alert is
+    # registered or no alert at all. In case of another alert (such as a blocked user), it is safer
     # to do nothing to prevent redirection loops with certain Omniauth providers.
     return unless flash[:alert].blank? || flash[:alert] == I18n.t('devise.failure.unauthenticated')
-    
+
     # Prevent alert from popping up on the first page shown after authentication.
-    flash[:alert] = nil 
-    
+    flash[:alert] = nil
+
     redirect_to user_omniauth_authorize_path(provider.to_sym)
   end
 
@@ -107,4 +109,8 @@ class SessionsController < Devise::SessionsController
     AuditEventService.new(user, user, options).
       for_authentication.security_event
   end
+
+  def load_recaptcha
+    Gitlab::Recaptcha.load_configurations!
+  end
 end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 21f962df206d5814d5bf4af0551e0c4ba6412119..f7f7a1a02d3ef00d3ce475c35fa23f95542acbaa 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -61,7 +61,7 @@ module ApplicationHelper
     options[:class] ||= ''
     options[:class] << ' identicon'
     bg_key = project.id % 7
-    style = "background-color: ##{ allowed_colors.values[bg_key] }; color: #555"
+    style = "background-color: ##{allowed_colors.values[bg_key]}; color: #555"
 
     content_tag(:div, class: options[:class], style: style) do
       project.name[0, 1].upcase
@@ -72,7 +72,7 @@ module ApplicationHelper
     if user_or_email.is_a?(User)
       user = user_or_email
     else
-      user = User.find_by(email: user_or_email)
+      user = User.find_by(email: user_or_email.downcase)
     end
 
     if user
@@ -204,12 +204,16 @@ module ApplicationHelper
   # Returns an HTML-safe String
   def time_ago_with_tooltip(time, placement: 'top', html_class: 'time_ago', skip_js: false)
     element = content_tag :time, time.to_s,
-      class: "#{html_class} js-timeago",
+      class: "#{html_class} js-timeago js-timeago-pending",
       datetime: time.getutc.iso8601,
       title: time.in_time_zone.stamp('Aug 21, 2011 9:23pm'),
       data: { toggle: 'tooltip', placement: placement, container: 'body' }
 
-    element += javascript_tag "$('.js-timeago').last().timeago()" unless skip_js
+    unless skip_js
+      element << javascript_tag(
+        "$('.js-timeago-pending').removeClass('js-timeago-pending').timeago()"
+      )
+    end
 
     element
   end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 2c81ea1623c52f9945519e121e0df1f839926ec1..0cfc0565e84fb50836609e58c4143cfe2ae2ef45 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -50,5 +50,17 @@ module AuthHelper
     current_user.identities.exists?(provider: provider.to_s)
   end
 
+  def two_factor_skippable?
+    current_application_settings.require_two_factor_authentication &&
+      !current_user.two_factor_enabled &&
+      current_application_settings.two_factor_grace_period &&
+      !two_factor_grace_period_expired?
+  end
+
+  def two_factor_grace_period_expired?
+    current_user.otp_grace_period_started_at &&
+      (current_user.otp_grace_period_started_at + current_application_settings.two_factor_grace_period.hours) < Time.current
+  end
+
   extend self
 end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 68e5d5be600edcff277409109b8a7c020bcdcea7..d31d4cde08f4dcb2579d2fd582c50111401e9bca 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -22,32 +22,90 @@ module BlobHelper
     %w(credits changelog news copying copyright license authors)
   end
 
-  def edit_blob_link(project, ref, path, options = {})
-    blob =
-      begin
-        project.repository.blob_at(ref, path)
-      rescue
-        nil
-      end
-
-    return unless blob && blob.text? && blob_editable?(blob)
-
-    text = 'Edit'
-    after = options[:after] || ''
+  def edit_blob_link(project = @project, ref = @ref, path = @path, options = {})
+    return unless current_user
+
+    blob = project.repository.blob_at(ref, path) rescue nil
+
+    return unless blob && blob_text_viewable?(blob)
+
     from_mr = options[:from_merge_request_id]
     link_opts = {}
     link_opts[:from_merge_request_id] = from_mr if from_mr
-    cls = 'btn btn-small'
-    link_to(text,
-            namespace_project_edit_blob_path(project.namespace, project,
-                                             tree_join(ref, path),
-                                             link_opts),
-            class: cls
-           ) + after.html_safe
+
+    edit_path = namespace_project_edit_blob_path(project.namespace, project,
+                                     tree_join(ref, path),
+                                     link_opts)
+
+    if !on_top_of_branch?
+      button_tag "Edit", class: "btn btn-default disabled has_tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
+    elsif can_edit_blob?(blob)
+      link_to "Edit", edit_path, class: 'btn btn-small'
+    elsif can?(current_user, :fork_project, project)
+      continue_params = {
+        to:     edit_path,
+        notice: edit_in_new_fork_notice,
+        notice_now: edit_in_new_fork_notice_now
+      }
+      fork_path = namespace_project_fork_path(project.namespace, project, namespace_key:  current_user.namespace.id,
+                                                                          continue:       continue_params)
+
+      link_to "Edit", fork_path, class: 'btn btn-small', method: :post
+    end
+  end
+
+  def modify_file_link(project = @project, ref = @ref, path = @path, label:, action:, btn_class:, modal_type:)
+    return unless current_user
+
+    blob = project.repository.blob_at(ref, path) rescue nil
+
+    return unless blob
+
+    if !on_top_of_branch?
+      button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' }
+    elsif blob.lfs_pointer?
+      button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "It is not possible to #{action} files that are stored in LFS using the web interface", data: { container: 'body' }
+    elsif can_edit_blob?(blob)
+      button_tag label, class: "btn btn-#{btn_class}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal'
+    elsif can?(current_user, :fork_project, project)
+      continue_params = {
+        to:     request.fullpath,
+        notice: edit_in_new_fork_notice + " Try to #{action} this file again.",
+        notice_now: edit_in_new_fork_notice_now
+      }
+      fork_path = namespace_project_fork_path(project.namespace, project, namespace_key:  current_user.namespace.id,
+                                                                          continue:       continue_params)
+
+      link_to label, fork_path, class: "btn btn-#{btn_class}", method: :post
+    end
+  end
+
+  def replace_blob_link(project = @project, ref = @ref, path = @path)
+    modify_file_link(
+      project,
+      ref,
+      path,
+      label:      "Replace",
+      action:     "replace",
+      btn_class:  "default",
+      modal_type: "upload"
+    )
+  end
+
+  def delete_blob_link(project = @project, ref = @ref, path = @path)
+    modify_file_link(
+      project,
+      ref,
+      path,
+      label:      "Delete",
+      action:     "delete",
+      btn_class:  "remove",
+      modal_type: "remove"
+    )
   end
 
-  def blob_editable?(blob, project = @project, ref = @ref)
-    !blob.lfs_pointer? && allowed_tree_edit?(project, ref)
+  def can_edit_blob?(blob, project = @project, ref = @ref)
+    !blob.lfs_pointer? && can_edit_tree?(project, ref)
   end
 
   def leave_edit_message
@@ -70,7 +128,7 @@ module BlobHelper
     icon("#{file_type_icon_class('file', mode, name)} fw")
   end
 
-  def blob_viewable?(blob)
+  def blob_text_viewable?(blob)
     blob && blob.text? && !blob.lfs_pointer?
   end
 
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index 313b6dde9102795fda16d8e9eb4e1d322732a76d..ec0e3f409c1596e03e5f344748ea562ddaca4902 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -10,8 +10,8 @@ module ButtonHelper
   #   # => "<button class='...' data-clipboard-text='Foo'>...</button>"
   #
   #   # Define the target element
-  #   clipboard_button(clipboard_target: "#foo")
-  #   # => "<button class='...' data-clipboard-target='#foo'>...</button>"
+  #   clipboard_button(clipboard_target: "div#foo")
+  #   # => "<button class='...' data-clipboard-target='div#foo'>...</button>"
   #
   # See http://clipboardjs.com/#usage
   def clipboard_button(data = {})
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index 8554074d6199dda91a9f41c85aa176e0ffe21f14..d8bee21c82e95753236f6b6701ed0249411f7060 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -12,19 +12,6 @@ module CiStatusHelper
     ci_label_for_status(ci_commit.status)
   end
 
-  def ci_status_color(ci_commit)
-    case ci_commit.status
-    when 'success'
-      'green'
-    when 'failed'
-      'red'
-    when 'running', 'pending'
-      'yellow'
-    else
-      'gray'
-    end
-  end
-
   def ci_status_with_icon(status)
     content_tag :span, class: "ci-status ci-#{status}" do
       ci_icon_for_status(status) + '&nbsp;'.html_safe + ci_label_for_status(status)
@@ -56,12 +43,11 @@ module CiStatusHelper
   end
 
   def render_ci_status(ci_commit)
-    link_to ci_status_path(ci_commit),
-      class: "ci-status-link c#{ci_status_color(ci_commit)}",
+    link_to ci_status_icon(ci_commit),
+      ci_status_path(ci_commit),
+      class: "ci-status-link ci-status-icon-#{ci_commit.status.dasherize}",
       title: "Build #{ci_status_label(ci_commit)}",
-      data: { toggle: 'tooltip', placement: 'left' } do
-      ci_status_icon(ci_commit)
-    end
+      data: { toggle: 'tooltip', placement: 'left' }
   end
 
   def no_runners_for_project?(project)
diff --git a/app/helpers/external_wiki_helper.rb b/app/helpers/external_wiki_helper.rb
index 838b85afdfe573e1d605c784fe47b35731aa9894..1f3401f290637587be4ee512738b864885220569 100644
--- a/app/helpers/external_wiki_helper.rb
+++ b/app/helpers/external_wiki_helper.rb
@@ -1,7 +1,7 @@
 module ExternalWikiHelper
   def get_project_wiki_path(project)
     external_wiki_service = project.services.
-      select { |service| service.to_param == 'external_wiki' }.first
+      find { |service| service.to_param == 'external_wiki' }
     if external_wiki_service.present? && external_wiki_service.active?
       external_wiki_service.properties['external_wiki_url']
     else
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index a0cf3dc084398fb165f9919af8003c5e76c596a4..ca41657cec152fbdc6f7f90fa29b09cc7a5f6aec 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -65,7 +65,8 @@ module GitlabMarkdownHelper
   end
 
   def asciidoc(text)
-    Gitlab::Asciidoc.render(text,
+    Gitlab::Asciidoc.render(
+      text,
       project:      @project,
       current_user: (current_user if defined?(current_user)),
 
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index cdf7038b2f27770d97b1b830a9011932d471be30..80e2741b09a07795b4678a3346859b0fbbe07495 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -57,18 +57,22 @@ module IssuesHelper
     options_from_collection_for_select(milestones, 'id', 'title', object.milestone_id)
   end
 
-  def issue_box_class(item)
+  def status_box_class(item)
     if item.respond_to?(:expired?) && item.expired?
-      'issue-box-expired'
+      'status-box-expired'
     elsif item.respond_to?(:merged?) && item.merged?
-      'issue-box-merged'
+      'status-box-merged'
     elsif item.closed?
-      'issue-box-closed'
+      'status-box-closed'
     else
-      'issue-box-open'
+      'status-box-open'
     end
   end
 
+  def issue_button_visibility(issue, closed)    
+    return 'hidden' if issue.closed? == closed
+  end
+
   def issue_to_atom(xml, issue)
     xml.entry do
       xml.id      namespace_project_issue_url(issue.project.namespace,
@@ -94,11 +98,14 @@ module IssuesHelper
     end.sort.to_sentence(last_word_connector: ', or ')
   end
 
-  def url_to_emoji(name)
-    emoji_path = ::AwardEmoji.path_to_emoji_image(name)
-    url_to_image(emoji_path)
-  rescue StandardError
-    ""
+  def emoji_icon(name, unicode = nil, aliases = [])
+    unicode ||= Emoji.emoji_filename(name)
+
+    content_tag :div, "",
+      class: "icon emoji-icon emoji-#{unicode}",
+      "data-emoji" => name,
+      "data-aliases" => aliases.join(" "),
+      "data-unicode-name" => unicode
   end
 
   def emoji_author_list(notes, current_user)
@@ -109,10 +116,6 @@ module IssuesHelper
     list.join(", ")
   end
 
-  def emoji_list
-    ::AwardEmoji::EMOJI_LIST
-  end
-
   def note_active_class(notes, current_user)
     if current_user && notes.pluck(:author_id).include?(current_user.id)
       "active"
@@ -121,6 +124,18 @@ module IssuesHelper
     end
   end
 
+  def awards_sort(awards)
+    awards.sort_by do |award, notes|
+      if award == "thumbsup"
+        0
+      elsif award == "thumbsdown"
+        1
+      else
+        2
+      end
+    end.to_h
+  end
+
   # Required for Banzai::Filter::IssueReferenceFilter
   module_function :url_for_issue
 end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 6c32647594d5a0642d70f52ed57cb93b5989badb..1dd07a2a2204b0368671f57e3b89b05b82432477 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -27,7 +27,16 @@ module MergeRequestsHelper
   end
 
   def ci_build_details_path(merge_request)
-    merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch)
+    build_url = merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch)
+    return nil unless build_url
+
+    parsed_url = URI.parse(build_url)
+
+    unless parsed_url.userinfo.blank?
+      parsed_url.userinfo = ''
+    end
+
+    parsed_url.to_s
   end
 
   def merge_path_description(merge_request, separator)
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 9bf750124b25085361aafff6c982916ef10a2c27..791cb9e50bd013b738d5d59c22a17ea098a6816b 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -8,6 +8,80 @@ module PageLayoutHelper
     @page_title.join(" \u00b7 ")
   end
 
+  # Define or get a description for the current page
+  #
+  # description - String (default: nil)
+  #
+  # If this helper is called multiple times with an argument, only the last
+  # description will be returned when called without an argument. Descriptions
+  # have newlines replaced with spaces and all HTML tags are sanitized.
+  #
+  # Examples:
+  #
+  #   page_description # => "GitLab Community Edition"
+  #   page_description("Foo")
+  #   page_description # => "Foo"
+  #
+  #   page_description("<b>Bar</b>\nBaz")
+  #   page_description # => "Bar Baz"
+  #
+  # Returns an HTML-safe String.
+  def page_description(description = nil)
+    @page_description ||= page_description_default
+
+    if description.present?
+      @page_description = description.squish
+    else
+      sanitize(@page_description, tags: []).truncate_words(30)
+    end
+  end
+
+  # Default value for page_description when one hasn't been defined manually by
+  # a view
+  def page_description_default
+    if @project
+      @project.description || brand_title
+    else
+      brand_title
+    end
+  end
+
+  def page_image
+    default = image_url('gitlab_logo.png')
+
+    if @project
+      @project.avatar_url || default
+    elsif @user
+      avatar_icon(@user)
+    else
+      default
+    end
+  end
+
+  # Define or get attributes to be used as Twitter card metadata
+  #
+  # map - Hash of label => data pairs. Keys become labels, values become data
+  #
+  # Raises ArgumentError if given more than two attributes
+  def page_card_attributes(map = {})
+    raise ArgumentError, 'cannot provide more than two attributes' if map.length > 2
+
+    @page_card_attributes ||= {}
+    @page_card_attributes = map.reject { |_,v| v.blank? } if map.present?
+    @page_card_attributes
+  end
+
+  def page_card_meta_tags
+    tags = ''
+
+    page_card_attributes.each_with_index do |pair, i|
+      tags << tag(:meta, property: "twitter:label#{i + 1}", content: pair[0])
+      tags << tag(:meta, property: "twitter:data#{i + 1}",  content: pair[1])
+    end
+
+    tags.html_safe
+  end
+
   def header_title(title = nil, title_url = nil)
     if title
       @header_title     = title
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index d061136b7b856a2cec99a073459b1d045561e0b3..77ba612548a11785dbb214bbd2e8026e9c879946 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -105,6 +105,14 @@ module ProjectsHelper
     end
   end
 
+  def user_max_access_in_project(user_id, project)
+    level = project.team.max_member_access(user_id)
+
+    if level
+      Gitlab::Access.options_with_owner.key(level)
+    end
+  end
+
   private
 
   def get_project_nav_tabs(project, current_user)
@@ -277,14 +285,6 @@ module ProjectsHelper
     end
   end
 
-  def user_max_access_in_project(user, project)
-    level = project.team.max_member_access(user)
-
-    if level
-      Gitlab::Access.options_with_owner.key(level)
-    end
-  end
-
   def leave_project_message(project)
     "Are you sure you want to leave \"#{project.name}\" project?"
   end
@@ -330,10 +330,9 @@ module ProjectsHelper
   def filename_path(project, filename)
     if project && blob = project.repository.send(filename)
       namespace_project_blob_path(
-          project.namespace,
-          project,
-          tree_join(project.default_branch,
-                    blob.name)
+        project.namespace,
+        project,
+        tree_join(project.default_branch, blob.name)
       )
     end
   end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 886a1e734b5c1ca71acf9bd175ae4134ea04d738..2ad7c80dae0fe5379a9f074f3fcdf6a816e128f5 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -50,24 +50,49 @@ module TreeHelper
     project.repository.branch_names.include?(ref)
   end
 
-  def allowed_tree_edit?(project = nil, ref = nil)
+  def can_edit_tree?(project = nil, ref = nil)
     project ||= @project
     ref ||= @ref
+
     return false unless on_top_of_branch?(project, ref)
 
-    can?(current_user, :push_code, project)
+    can?(current_user, :push_code, project) ||
+      (current_user && current_user.already_forked?(project))
   end
 
   def tree_edit_branch(project = @project, ref = @ref)
-    if allowed_tree_edit?(project, ref)
-      if can_push_branch?(project, ref)
-        ref
-      else
-        project.repository.next_patch_branch
-      end
+    return unless can_edit_tree?(project, ref)
+
+    if can_push_branch?(project, ref)
+      ref
+    else
+      project = tree_edit_project(project)
+      project.repository.next_patch_branch
+    end
+  end
+
+  def tree_edit_project(project = @project)
+    if can?(current_user, :push_code, project)
+      project
+    elsif current_user && current_user.already_forked?(project)
+      current_user.fork_of(project)
     end
   end
 
+  def edit_in_new_fork_notice_now
+    "You're not allowed to make changes to this project directly." +
+      " A fork of this project is being created that you can make changes in, so you can submit a merge request."
+  end
+
+  def edit_in_new_fork_notice
+    "You're not allowed to make changes to this project directly." +
+      " A fork of this project has been created that you can make changes in, so you can submit a merge request."
+  end
+
+  def commit_in_fork_help
+    "A new branch will be created in your fork and a new merge request will be started."
+  end
+
   def tree_breadcrumbs(tree, max_links = 2)
     if @path.present?
       part_path = ""
@@ -79,7 +104,7 @@ module TreeHelper
         part_path = File.join(part_path, part) unless part_path.empty?
         part_path = part if part_path.empty?
 
-        next unless parts.last(2).include?(part) if parts.count > max_links
+        next if parts.count > max_links && !parts.last(2).include?(part)
         yield(part, tree_join(@ref, part_path))
       end
     end
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index 2e69ce923a2f9438e8fc788be8447b28f72ce838..71d33b445c22bea272c664e004ef0f01401ea4db 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -69,7 +69,6 @@ module VisibilityLevelHelper
 
   def skip_level?(form_model, level)
     form_model.is_a?(Project) &&
-    form_model.forked? &&
-    !Gitlab::VisibilityLevel.allowed_fork_levels(form_model.forked_from_project.visibility_level).include?(level)
+    !form_model.visibility_level_allowed?(level)
   end
 end
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 9beb0de68f3b8ebdd7989e682fbd0bd126505d3e..3bbdd9cee76c2761718bc65259cbebfd5f8c65bf 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -17,7 +17,7 @@ class Notify < BaseMailer
          subject: subject,
          body: body.html_safe,
          content_type: 'text/html'
-    )
+        )
   end
 
   # Splits "gitlab.corp.company.com" up into "gitlab.corp.company.com",
diff --git a/app/models/ability.rb b/app/models/ability.rb
index cd5ae0fb0fd3c99182320d605c7e24bc5904a2b9..1b3ee757040515250134b79afe752fc30883f16a 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -132,14 +132,14 @@ class Ability
     end
 
     def public_project_rules
-      project_guest_rules + [
+      @public_project_rules ||= project_guest_rules + [
         :download_code,
         :fork_project
       ]
     end
 
     def project_guest_rules
-      [
+      @project_guest_rules ||= [
         :read_project,
         :read_wiki,
         :read_issue,
@@ -157,7 +157,7 @@ class Ability
     end
 
     def project_report_rules
-      project_guest_rules + [
+      @project_report_rules ||= project_guest_rules + [
         :create_commit_status,
         :read_commit_statuses,
         :download_code,
@@ -170,7 +170,7 @@ class Ability
     end
 
     def project_dev_rules
-      project_report_rules + [
+      @project_dev_rules ||= project_report_rules + [
         :admin_merge_request,
         :create_merge_request,
         :create_wiki,
@@ -181,7 +181,7 @@ class Ability
     end
 
     def project_archived_rules
-      [
+      @project_archived_rules ||= [
         :create_merge_request,
         :push_code,
         :push_code_to_protected_branches,
@@ -191,7 +191,7 @@ class Ability
     end
 
     def project_master_rules
-      project_dev_rules + [
+      @project_master_rules ||= project_dev_rules + [
         :push_code_to_protected_branches,
         :update_project_snippet,
         :update_merge_request,
@@ -206,7 +206,7 @@ class Ability
     end
 
     def project_admin_rules
-      project_master_rules + [
+      @project_admin_rules ||= project_master_rules + [
         :change_namespace,
         :change_visibility_level,
         :rename_project,
@@ -332,7 +332,7 @@ class Ability
       end
 
       if snippet.public? || snippet.internal?
-        rules << :read_personal_snippet 
+        rules << :read_personal_snippet
       end
 
       rules
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index faa0bdf840b53d5f5b4359b1e5686f43e45cbb0a..be69d317d7306edd3577c51e6a95f5600e503fdb 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -2,32 +2,34 @@
 #
 # Table name: application_settings
 #
-#  id                           :integer          not null, primary key
-#  default_projects_limit       :integer
-#  signup_enabled               :boolean
-#  signin_enabled               :boolean
-#  gravatar_enabled             :boolean
-#  sign_in_text                 :text
-#  created_at                   :datetime
-#  updated_at                   :datetime
-#  home_page_url                :string(255)
-#  default_branch_protection    :integer          default(2)
-#  twitter_sharing_enabled      :boolean          default(TRUE)
-#  restricted_visibility_levels :text
-#  version_check_enabled        :boolean          default(TRUE)
-#  max_attachment_size          :integer          default(10), not null
-#  default_project_visibility   :integer
-#  default_snippet_visibility   :integer
-#  restricted_signup_domains    :text
-#  user_oauth_applications      :boolean          default(TRUE)
-#  after_sign_out_path          :string(255)
-#  session_expire_delay         :integer          default(10080), not null
-#  import_sources               :text
-#  help_page_text               :text
-#  admin_notification_email     :string(255)
-#  shared_runners_enabled       :boolean          default(TRUE), not null
-#  max_artifacts_size           :integer          default(100), not null
-#  runners_registration_token   :string(255)
+#  id                                :integer          not null, primary key
+#  default_projects_limit            :integer
+#  signup_enabled                    :boolean
+#  signin_enabled                    :boolean
+#  gravatar_enabled                  :boolean
+#  sign_in_text                      :text
+#  created_at                        :datetime
+#  updated_at                        :datetime
+#  home_page_url                     :string(255)
+#  default_branch_protection         :integer          default(2)
+#  twitter_sharing_enabled           :boolean          default(TRUE)
+#  restricted_visibility_levels      :text
+#  version_check_enabled             :boolean          default(TRUE)
+#  max_attachment_size               :integer          default(10), not null
+#  default_project_visibility        :integer
+#  default_snippet_visibility        :integer
+#  restricted_signup_domains         :text
+#  user_oauth_applications           :boolean          default(TRUE)
+#  after_sign_out_path               :string(255)
+#  session_expire_delay              :integer          default(10080), not null
+#  import_sources                    :text
+#  help_page_text                    :text
+#  admin_notification_email          :string(255)
+#  shared_runners_enabled            :boolean          default(TRUE), not null
+#  max_artifacts_size                :integer          default(100), not null
+#  runners_registration_token        :string(255)
+#  require_two_factor_authentication :boolean          default(TRUE)
+#  two_factor_grace_period           :integer          default(48)
 #
 
 class ApplicationSetting < ActiveRecord::Base
@@ -42,21 +44,32 @@ class ApplicationSetting < ActiveRecord::Base
   attr_accessor :restricted_signup_domains_raw
 
   validates :session_expire_delay,
-    presence: true,
-    numericality: { only_integer: true, greater_than_or_equal_to: 0 }
+            presence: true,
+            numericality: { only_integer: true, greater_than_or_equal_to: 0 }
 
   validates :home_page_url,
-    allow_blank: true,
-    url: true,
-    if: :home_page_url_column_exist
+            allow_blank: true,
+            url: true,
+            if: :home_page_url_column_exist
 
   validates :after_sign_out_path,
-    allow_blank: true,
-    url: true
+            allow_blank: true,
+            url: true
 
   validates :admin_notification_email,
-    allow_blank: true,
-    email: true
+            allow_blank: true,
+            email: true
+
+  validates :two_factor_grace_period,
+            numericality: { greater_than_or_equal_to: 0 }
+
+  validates :recaptcha_site_key,
+            presence: true,
+            if: :recaptcha_enabled
+
+  validates :recaptcha_private_key,
+            presence: true,
+            if: :recaptcha_enabled
 
   validates_each :restricted_visibility_levels do |record, attr, value|
     unless value.nil?
@@ -112,6 +125,8 @@ class ApplicationSetting < ActiveRecord::Base
       import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'],
       shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
       max_artifacts_size: Settings.artifacts['max_size'],
+      require_two_factor_authentication: false,
+      two_factor_grace_period: 48
     )
   end
 
@@ -126,12 +141,16 @@ class ApplicationSetting < ActiveRecord::Base
   def restricted_signup_domains_raw=(values)
     self.restricted_signup_domains = []
     self.restricted_signup_domains = values.split(
-        /\s*[,;]\s*     # comma or semicolon, optionally surrounded by whitespace
-        |               # or
-        \s              # any whitespace character
-        |               # or
-        [\r\n]          # any number of newline characters
-        /x)
+      /\s*[,;]\s*     # comma or semicolon, optionally surrounded by whitespace
+      |               # or
+      \s              # any whitespace character
+      |               # or
+      [\r\n]          # any number of newline characters
+      /x)
     self.restricted_signup_domains.reject! { |d| d.empty? }
   end
+
+  def runners_registration_token
+    ensure_runners_registration_token!
+  end
 end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 6d9cdb95295d395186ab3b6e5597b4bad8e08d79..3e67b2771c1d7322328286c2c88b23edc822509e 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -135,6 +135,16 @@ module Ci
       predefined_variables + yaml_variables + project_variables + trigger_variables
     end
 
+    def merge_request
+      merge_requests = MergeRequest.includes(:merge_request_diff)
+                                   .where(source_branch: ref, source_project_id: commit.gl_project_id)
+                                   .reorder(iid: :asc)
+
+      merge_requests.find do |merge_request|
+        merge_request.commits.any? { |ci| ci.id == commit.sha }
+      end
+    end
+
     def project
       commit.project
     end
@@ -170,7 +180,8 @@ module Ci
 
     def extract_coverage(text, regex)
       begin
-        matches = text.gsub(Regexp.new(regex)).to_a.last
+        matches = text.scan(Regexp.new(regex)).last
+        matches = matches.last if matches.kind_of?(Array)
         coverage = matches.gsub(/\d+(\.\d+)?/).first
 
         if coverage.present?
@@ -183,8 +194,11 @@ module Ci
     end
 
     def raw_trace
-      if File.exist?(path_to_trace)
+      if File.file?(path_to_trace)
         File.read(path_to_trace)
+      elsif project.ci_id && File.file?(old_path_to_trace)
+        # Temporary fix for build trace data integrity
+        File.read(old_path_to_trace)
       else
         # backward compatibility
         read_attribute :trace
@@ -201,8 +215,8 @@ module Ci
     end
 
     def trace=(trace)
-      unless Dir.exists? dir_to_trace
-        FileUtils.mkdir_p dir_to_trace
+      unless Dir.exists?(dir_to_trace)
+        FileUtils.mkdir_p(dir_to_trace)
       end
 
       File.write(path_to_trace, trace)
@@ -220,6 +234,55 @@ module Ci
       "#{dir_to_trace}/#{id}.log"
     end
 
+    ##
+    # Deprecated
+    #
+    # This is a hotfix for CI build data integrity, see #4246
+    # Should be removed in 8.4, after CI files migration has been done.
+    #
+    def old_dir_to_trace
+      File.join(
+        Settings.gitlab_ci.builds_path,
+        created_at.utc.strftime("%Y_%m"),
+        project.ci_id.to_s
+      )
+    end
+
+    ##
+    # Deprecated
+    #
+    # This is a hotfix for CI build data integrity, see #4246
+    # Should be removed in 8.4, after CI files migration has been done.
+    #
+    def old_path_to_trace
+      "#{old_dir_to_trace}/#{id}.log"
+    end
+
+    ##
+    # Deprecated
+    #
+    # This contains a hotfix for CI build data integrity, see #4246
+    #
+    # This method is used by `ArtifactUploader` to create a store_dir.
+    # Warning: Uploader uses it after AND before file has been stored.
+    #
+    # This method returns old path to artifacts only if it already exists.
+    #
+    def artifacts_path
+      old = File.join(created_at.utc.strftime('%Y_%m'),
+                      project.ci_id.to_s,
+                      id.to_s)
+
+      old_store = File.join(ArtifactUploader.artifacts_path, old)
+      return old if project.ci_id && File.directory?(old_store)
+
+      File.join(
+        created_at.utc.strftime('%Y_%m'),
+        project.id.to_s,
+        id.to_s
+      )
+    end
+
     def token
       project.runners_token
     end
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
index 6bf596e5d3e640f0b9df5f4ba25d39df29c263f9..d2a29236942eebead2e1bb85f2087b2a283e3a06 100644
--- a/app/models/ci/commit.rb
+++ b/app/models/ci/commit.rb
@@ -218,16 +218,6 @@ module Ci
       update!(committed_at: DateTime.now)
     end
 
-    ##
-    # This method checks if build status should be displayed.
-    #
-    # Build status should be available only if builds are enabled
-    # on project level and `.gitlab-ci.yml` file is present.
-    #
-    def show_build_status?
-      project.builds_enabled? && ci_yaml_file
-    end
-
     private
 
     def save_yaml_error(error)
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index f56fd3e02d472a06d839c18f6d63d189b01e896c..18a00f95b48291abe09e17d7f9cbe2869988cb19 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -95,14 +95,12 @@ module Issuable
     opened? || reopened?
   end
 
-  # Deprecated. Still exists to preserve API compatibility.
   def downvotes
-    0
+    notes.awards.where(note: "thumbsdown").count
   end
 
-  # Deprecated. Still exists to preserve API compatibility.
   def upvotes
-    0
+    notes.awards.where(note: "thumbsup").count
   end
 
   def subscribed?(user)
@@ -161,6 +159,14 @@ module Issuable
     self.class.to_s.underscore
   end
 
+  # Returns a Hash of attributes to be used for Twitter card metadata
+  def card_attributes
+    {
+      'Author'   => author.try(:name),
+      'Assignee' => assignee.try(:name)
+    }
+  end
+
   def notes_with_associations
     notes.includes(:author, :project)
   end
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index d4e3099453dce57e0a7b7a4188c4ff625fea2517..6316ee208b5a7c3b2ea60d9983f858858369feda 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -44,14 +44,14 @@ module Mentionable
   end
 
   def all_references(current_user = self.author, text = nil)
-    ext = Gitlab::ReferenceExtractor.new(self.project, current_user)
+    ext = Gitlab::ReferenceExtractor.new(self.project, current_user, self.author)
 
     if text
       ext.analyze(text)
     else
       self.class.mentionable_attrs.each do |attr, options|
         text = send(attr)
-        options[:cache_key] = [self, attr] if options.delete(:cache)
+        options[:cache_key] = [self, attr] if options.delete(:cache) && self.persisted?
         ext.analyze(text, options)
       end
     end
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 808d80b0530fb417885ae5cf2524d77bbd0c09bc..fc6f83b918b4929240bd85acfb9906af1ea51b1a 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -37,7 +37,7 @@ module Participable
 
   # Be aware that this method makes a lot of sql queries.
   # Save result into variable if you are going to reuse it inside same request
-  def participants(current_user = self.author, load_lazy_references: true)
+  def participants(current_user = self.author)
     participants =
       Gitlab::ReferenceExtractor.lazily do
         self.class.participant_attrs.flat_map do |attr|
diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb
index 56d38fe825088f54e01662b2acca4a1757c1e165..885deaf78d2d480b0ad416a04f0d3a970ed45833 100644
--- a/app/models/concerns/token_authenticatable.rb
+++ b/app/models/concerns/token_authenticatable.rb
@@ -13,20 +13,21 @@ module TokenAuthenticatable
       @token_fields << token_field
 
       define_singleton_method("find_by_#{token_field}") do |token|
-        where(token_field => token).first if token
+        find_by(token_field => token) if token
       end
 
       define_method("ensure_#{token_field}") do
         current_token = read_attribute(token_field)
-        if current_token.blank?
-          write_attribute(token_field, generate_token_for(token_field))
-        else
-          current_token
-        end
+        current_token.blank? ? write_new_token(token_field) : current_token
+      end
+
+      define_method("ensure_#{token_field}!") do
+        send("reset_#{token_field}!") if read_attribute(token_field).blank?
+        read_attribute(token_field)
       end
 
       define_method("reset_#{token_field}!") do
-        write_attribute(token_field, generate_token_for(token_field))
+        write_new_token(token_field)
         save!
       end
     end
@@ -34,10 +35,15 @@ module TokenAuthenticatable
 
   private
 
-  def generate_token_for(token_field)
+  def write_new_token(token_field)
+    new_token = generate_token(token_field)
+    write_attribute(token_field, new_token)
+  end
+
+  def generate_token(token_field)
     loop do
       token = Devise.friendly_token
-      break token unless self.class.unscoped.where(token_field => token).first
+      break token unless self.class.unscoped.find_by(token_field => token)
     end
   end
 end
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index 8bfc79d88f8d1ad82027123a7f9413ba5ecb3df9..af1d7562ebe2a5312fdcf1e477a1af0812952e4f 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -16,7 +16,7 @@ class GlobalMilestone
   end
 
   def safe_title
-    @title.to_slug.to_s
+    @title.to_slug.normalize.to_s
   end
 
   def expired?
diff --git a/app/models/identity.rb b/app/models/identity.rb
index ad60154be710f0af8092db93d76b28ad765b5f69..8bcdc1949538f9dc67a1de39223f20fc7d68f57f 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -12,6 +12,7 @@
 
 class Identity < ActiveRecord::Base
   include Sortable
+  include CaseSensitivity
   belongs_to :user
 
   validates :provider, presence: true
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 4571d7f0ee10bed4688e06811318984dd779fa6f..80ecd15077f188864ad3719fa8bb223492cc5b58 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -86,7 +86,7 @@ class Issue < ActiveRecord::Base
   def referenced_merge_requests
     Gitlab::ReferenceExtractor.lazily do
       [self, *notes].flat_map do |note|
-        note.all_references(load_lazy_references: false).merge_requests
+        note.all_references.merge_requests
       end
     end.sort_by(&:iid)
   end
diff --git a/app/models/jira_issue.rb b/app/models/jira_issue.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5b21aac5e43c5902e67e0ed1af87aa155ae9fcce
--- /dev/null
+++ b/app/models/jira_issue.rb
@@ -0,0 +1,2 @@
+class JiraIssue < ExternalIssue
+end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index f6f77a162673216a9deee9194592537c457c2b89..ac25d38eb6338be998c93c6711e54c806df77a47 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -194,9 +194,7 @@ class MergeRequest < ActiveRecord::Base
       similar_mrs = similar_mrs.where('id not in (?)', self.id) if self.id
       if similar_mrs.any?
         errors.add :validate_branches,
-                   "Cannot Create: This merge request already exists: #{
-                   similar_mrs.pluck(:title)
-                   }"
+                   "Cannot Create: This merge request already exists: #{similar_mrs.pluck(:title)}"
       end
     end
   end
@@ -337,7 +335,7 @@ class MergeRequest < ActiveRecord::Base
       issues = commits.flat_map { |c| c.closes_issues(current_user) }
       issues.push(*Gitlab::ClosingIssueExtractor.new(project, current_user).
                   closed_by_message(description))
-      issues.uniq
+      issues.uniq(&:id)
     else
       []
     end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 1c4e101cc105708c9a324dfee7b67f4f8bdf40fb..adafabbec07602a5ccbebcb0a31828ac7fd5790e 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -45,7 +45,7 @@ class Namespace < ActiveRecord::Base
 
   class << self
     def by_path(path)
-      where('lower(path) = :value', value: path.downcase).first
+      find_by('lower(path) = :value', value: path.downcase)
     end
 
     # Case insensetive search for namespace by path or name
@@ -148,6 +148,6 @@ class Namespace < ActiveRecord::Base
   end
 
   def find_fork_of(project)
-    projects.joins(:forked_project_link).where('forked_project_links.forked_from_project_id = ?', project.id).first
+    projects.joins(:forked_project_link).find_by('forked_project_links.forked_from_project_id = ?', project.id)
   end
 end
diff --git a/app/models/note.rb b/app/models/note.rb
index 8c5b5836f9a2cbcf2d2b569b2042cc36629d3c6a..3d5b663c99f0ff545c3682ac422cdcedf9b22e5a 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -107,9 +107,16 @@ class Note < ActiveRecord::Base
     end
 
     def grouped_awards
+      notes = {}
+
       awards.select(:note).distinct.map do |note|
-        [ note.note, where(note: note.note) ]
+        notes[note.note] = where(note: note.note)
       end
+
+      notes["thumbsup"] ||= Note.none
+      notes["thumbsdown"] ||= Note.none
+
+      notes
     end
   end
 
@@ -339,14 +346,12 @@ class Note < ActiveRecord::Base
     read_attribute(:system)
   end
 
-  # Deprecated. Still exists to preserve API compatibility.
   def downvote?
-    false
+    is_award && note == "thumbsdown"
   end
 
-  # Deprecated. Still exists to preserve API compatibility.
   def upvote?
-    false
+    is_award && note == "thumbsup"
   end
 
   def editable?
diff --git a/app/models/project.rb b/app/models/project.rb
index e1f7bf971e384df359e552d56f7f96f115f5fa81..017471995ec25458e6d74233447d091113bbeb1d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -64,6 +64,19 @@ class Project < ActiveRecord::Base
     update_column(:last_activity_at, self.created_at)
   end
 
+  # update visibility_levet of forks
+  after_update :update_forks_visibility_level
+  def update_forks_visibility_level
+    return unless visibility_level < visibility_level_was
+
+    forks.each do |forked_project|
+      if forked_project.visibility_level > visibility_level
+        forked_project.visibility_level = visibility_level
+        forked_project.save!
+      end
+    end
+  end
+
   ActsAsTaggableOn.strict_case_match = true
   acts_as_taggable_on :tags
 
@@ -100,9 +113,12 @@ class Project < ActiveRecord::Base
   has_one :gitlab_issue_tracker_service, dependent: :destroy
   has_one :external_wiki_service, dependent: :destroy
 
-  has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
+  has_one  :forked_project_link,  dependent: :destroy, foreign_key: "forked_to_project_id"
+  has_one  :forked_from_project,  through:   :forked_project_link
+
+  has_many :forked_project_links, foreign_key: "forked_from_project_id"
+  has_many :forks,                through:     :forked_project_links, source: :forked_to_project
 
-  has_one :forked_from_project, through: :forked_project_link
   # Merge Requests for target project should be removed with it
   has_many :merge_requests,     dependent: :destroy, foreign_key: 'target_project_id'
   # Merge requests from source project should be kept when source project was removed
@@ -265,7 +281,7 @@ class Project < ActiveRecord::Base
         joins(:namespace).
         iwhere('namespaces.path' => namespace_path)
 
-      projects.where('projects.path' => project_path).take ||
+      projects.find_by('projects.path' => project_path) ||
         projects.iwhere('projects.path' => project_path).take
     end
 
@@ -450,7 +466,7 @@ class Project < ActiveRecord::Base
   end
 
   def external_issue_tracker
-    @external_issues_tracker ||= external_issues_trackers.select(&:activated?).first
+    @external_issues_tracker ||= external_issues_trackers.find(&:activated?)
   end
 
   def can_have_issues_tracker_id?
@@ -496,7 +512,11 @@ class Project < ActiveRecord::Base
   end
 
   def ci_service
-    @ci_service ||= ci_services.select(&:activated?).first
+    @ci_service ||= ci_services.find(&:activated?)
+  end
+
+  def jira_tracker?
+    issues_tracker.to_param == 'jira'
   end
 
   def avatar_type
@@ -535,7 +555,9 @@ class Project < ActiveRecord::Base
   end
 
   def send_move_instructions(old_path_with_namespace)
-    NotificationService.new.project_was_moved(self, old_path_with_namespace)
+    # New project path needs to be committed to the DB or notification will
+    # retrieve stale information
+    run_after_commit { NotificationService.new.project_was_moved(self, old_path_with_namespace) }
   end
 
   def owner
@@ -547,7 +569,7 @@ class Project < ActiveRecord::Base
   end
 
   def project_member_by_name_or_email(name = nil, email = nil)
-    user = users.where('name like ? or email like ?', name, email).first
+    user = users.find_by('name like ? or email like ?', name, email)
     project_members.where(user: user) if user
   end
 
@@ -722,7 +744,7 @@ class Project < ActiveRecord::Base
   end
 
   def project_member(user)
-    project_members.where(user_id: user).first
+    project_members.find_by(user_id: user)
   end
 
   def default_branch
@@ -764,7 +786,7 @@ class Project < ActiveRecord::Base
   end
 
   def forks_count
-    ForkedProjectLink.where(forked_from_project_id: self.id).count
+    forks.count
   end
 
   def find_label(name)
@@ -799,6 +821,10 @@ class Project < ActiveRecord::Base
     false
   end
 
+  def jira_tracker_active?
+    jira_tracker? && jira_service.active
+  end
+
   def ci_commit(sha)
     ci_commits.find_by(sha: sha)
   end
@@ -850,4 +876,13 @@ class Project < ActiveRecord::Base
   def build_timeout_in_minutes=(value)
     self.build_timeout = value.to_i * 60
   end
+
+  def open_issues_count
+    issues.opened.count
+  end
+
+  def visibility_level_allowed?(level)
+    return true unless forked?
+    Gitlab::VisibilityLevel.allowed_fork_levels(forked_from_project.visibility_level).include?(level.to_i)
+  end
 end
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index 0a61ad96a0e9b6aedbfe13ccc92e68dc4642963b..aa8746beb806acef7310ce140ee734bb5ce9801d 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -27,12 +27,10 @@ class BambooService < CiService
   validates :build_key, presence: true, if: :activated?
   validates :username,
     presence: true,
-    if: ->(service) { service.password? },
-    if: :activated?
+    if: ->(service) { service.activated? && service.password }
   validates :password,
     presence: true,
-    if: ->(service) { service.username? },
-    if: :activated?
+    if: ->(service) { service.activated? && service.username }
 
   attr_accessor :response
 
diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb
index 27fc19379f1d0c49e9b018f4f7f7f4c32411646c..15c7c907f7e38dac47825390cd251f7401d0f9ea 100644
--- a/app/models/project_services/flowdock_service.rb
+++ b/app/models/project_services/flowdock_service.rb
@@ -58,6 +58,6 @@ class FlowdockService < Service
       repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
       commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s",
       diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s",
-      )
+    )
   end
 end
diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb
index 91ef267ad79f11eee131fe5583f03fae602f1695..202fee042e30bfe6bbea33d1b73a673c52dc53a4 100644
--- a/app/models/project_services/gemnasium_service.rb
+++ b/app/models/project_services/gemnasium_service.rb
@@ -57,6 +57,6 @@ class GemnasiumService < Service
       token: token,
       api_key: api_key,
       repo: project.repository.path_to_repo
-      )
+    )
   end
 end
diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb
index d73182d40ac6235cee37728b063bf8365a4247f4..b64d97ce75dc5d2ebd90f410812b527c88a6d11d 100644
--- a/app/models/project_services/gitlab_ci_service.rb
+++ b/app/models/project_services/gitlab_ci_service.rb
@@ -18,6 +18,11 @@
 #  note_events           :boolean          default(TRUE), not null
 #
 
+# TODO(ayufan): The GitLabCiService is deprecated and the type should be removed when the database entries are removed
 class GitlabCiService < CiService
-  # this is no longer used
+  # We override the active accessor to always make GitLabCiService disabled
+  # Otherwise the GitLabCiService can be picked, but should never be since it's deprecated
+  def active
+    false
+  end
 end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 35e30b1cb0b76370baa3d5c714afbde0f2269209..e216f406e1cb672187d8dadfd2f91a375b878143 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -19,9 +19,24 @@
 #
 
 class JiraService < IssueTrackerService
+  include HTTParty
   include Gitlab::Application.routes.url_helpers
 
-  prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
+  DEFAULT_API_VERSION = 2
+
+  prop_accessor :username, :password, :api_url, :jira_issue_transition_id,
+                :title, :description, :project_url, :issues_url, :new_issue_url
+
+  before_validation :set_api_url, :set_jira_issue_transition_id
+
+  before_update :reset_password
+
+  def reset_password
+    # don't reset the password if a new one is provided
+    if api_url_changed? && !password_touched?
+      self.password = nil
+    end
+  end
 
   def help
     line1 = 'Setting `project_url`, `issues_url` and `new_issue_url` will '\
@@ -54,4 +69,228 @@ class JiraService < IssueTrackerService
   def to_param
     'jira'
   end
+
+  def fields
+    super.push(
+      { type: 'text', name: 'api_url', placeholder: 'https://jira.example.com/rest/api/2' },
+      { type: 'text', name: 'username', placeholder: '' },
+      { type: 'password', name: 'password', placeholder: '' },
+      { type: 'text', name: 'jira_issue_transition_id', placeholder: '2' }
+    )
+  end
+
+  def execute(push, issue = nil)
+    if issue.nil?
+      # No specific issue, that means
+      # we just want to test settings
+      test_settings
+    else
+      close_issue(push, issue)
+    end
+  end
+
+  def create_cross_reference_note(mentioned, noteable, author)
+    issue_name = mentioned.id
+    project = self.project
+    noteable_name = noteable.class.name.underscore.downcase
+    noteable_id = if noteable.is_a?(Commit)
+                    noteable.id
+                  else
+                    noteable.iid
+                  end
+
+    entity_url = build_entity_url(noteable_name.to_sym, noteable_id)
+
+    data = {
+      user: {
+        name: author.name,
+        url: resource_url(user_path(author)),
+      },
+      project: {
+        name: project.path_with_namespace,
+        url: resource_url(namespace_project_path(project.namespace, project))
+      },
+      entity: {
+        name: noteable_name.humanize.downcase,
+        url: entity_url
+      }
+    }
+
+    add_comment(data, issue_name)
+  end
+
+  def test_settings
+    result = JiraService.get(
+      jira_api_test_url,
+      headers: {
+        'Content-Type' => 'application/json',
+        'Authorization' => "Basic #{auth}"
+      }
+    )
+
+    case result.code
+    when 201, 200
+      Rails.logger.info("#{self.class.name} SUCCESS #{result.code}: Successfully connected to #{api_url}.")
+      true
+    else
+      Rails.logger.info("#{self.class.name} ERROR #{result.code}: #{result.parsed_response}")
+      false
+    end
+  rescue Errno::ECONNREFUSED => e
+    Rails.logger.info "#{self.class.name} ERROR: #{e.message}. API URL: #{api_url}."
+    false
+  end
+
+  private
+
+  def build_api_url_from_project_url
+    server = URI(project_url)
+    default_ports = [["http",80],["https",443]].include?([server.scheme,server.port])
+    server_url = "#{server.scheme}://#{server.host}"
+    server_url.concat(":#{server.port}") unless default_ports
+    "#{server_url}/rest/api/#{DEFAULT_API_VERSION}"
+  rescue
+    "" # looks like project URL was not valid
+  end
+
+  def set_api_url
+    self.api_url = build_api_url_from_project_url if self.api_url.blank?
+  end
+
+  def set_jira_issue_transition_id
+    self.jira_issue_transition_id ||= "2"
+  end
+
+  def close_issue(entity, issue)
+    commit_id = if entity.is_a?(Commit)
+                  entity.id
+                elsif entity.is_a?(MergeRequest)
+                  entity.last_commit.id
+                end
+    commit_url = build_entity_url(:commit, commit_id)
+
+    # Depending on the JIRA project's workflow, a comment during transition
+    # may or may not be allowed. Split the operation in to two calls so the
+    # comment always works.
+    transition_issue(issue)
+    add_issue_solved_comment(issue, commit_id, commit_url)
+  end
+
+  def transition_issue(issue)
+    message = {
+      transition: {
+        id: jira_issue_transition_id
+      }
+    }
+    send_message(close_issue_url(issue.iid), message.to_json)
+  end
+
+  def add_issue_solved_comment(issue, commit_id, commit_url)
+    comment = {
+      body: "Issue solved with [#{commit_id}|#{commit_url}]."
+    }
+
+    send_message(comment_url(issue.iid), comment.to_json)
+  end
+
+  def add_comment(data, issue_name)
+    url = comment_url(issue_name)
+    user_name = data[:user][:name]
+    user_url = data[:user][:url]
+    entity_name = data[:entity][:name]
+    entity_url = data[:entity][:url]
+    project_name = data[:project][:name]
+
+    message = {
+      body: "[#{user_name}|#{user_url}] mentioned this issue in [a #{entity_name} of #{project_name}|#{entity_url}]."
+    }
+
+    unless existing_comment?(issue_name, message[:body])
+      send_message(url, message.to_json)
+    end
+  end
+
+
+  def auth
+    require 'base64'
+    Base64.urlsafe_encode64("#{self.username}:#{self.password}")
+  end
+
+  def send_message(url, message)
+    result = JiraService.post(
+      url,
+      body: message,
+      headers: {
+        'Content-Type' => 'application/json',
+        'Authorization' => "Basic #{auth}"
+      }
+    )
+
+    message = case result.code
+              when 201, 200, 204
+                "#{self.class.name} SUCCESS #{result.code}: Successfully posted to #{url}."
+              when 401
+                "#{self.class.name} ERROR 401: Unauthorized. Check the #{self.username} credentials and JIRA access permissions and try again."
+              else
+                "#{self.class.name} ERROR #{result.code}: #{result.parsed_response}"
+              end
+
+    Rails.logger.info(message)
+    message
+  rescue URI::InvalidURIError, Errno::ECONNREFUSED => e
+    Rails.logger.info "#{self.class.name} ERROR: #{e.message}. Hostname: #{url}."
+  end
+
+  def existing_comment?(issue_name, new_comment)
+    result = JiraService.get(
+      comment_url(issue_name),
+      headers: {
+        'Content-Type' => 'application/json',
+        'Authorization' => "Basic #{auth}"
+      }
+    )
+
+    case result.code
+    when 201, 200
+      existing_comments = JSON.parse(result.body)['comments']
+
+      if existing_comments.present?
+        return existing_comments.map { |comment| comment['body'].include?(new_comment) }.any?
+      end
+    end
+
+    false
+  rescue JSON::ParserError
+    false
+  end
+
+  def resource_url(resource)
+    "#{Settings.gitlab['url'].chomp("/")}#{resource}"
+  end
+
+  def build_entity_url(entity_name, entity_id)
+    resource_url(
+      polymorphic_url(
+        [
+          self.project.namespace.becomes(Namespace),
+          self.project,
+          entity_name
+        ],
+        id: entity_id,
+        routing_type: :path
+      )
+    )
+  end
+
+  def close_issue_url(issue_name)
+    "#{self.api_url}/issue/#{issue_name}/transitions"
+  end
+
+  def comment_url(issue_name)
+    "#{self.api_url}/issue/#{issue_name}/comment"
+  end
+
+  def jira_api_test_url
+    "#{self.api_url}/myself"
+  end
 end
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index 29d4236745a15aa46be95a2eddbd695cbf55c6cc..a63700693d778c18a99b9929c8af46116776adfb 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -27,12 +27,10 @@ class TeamcityService < CiService
   validates :build_type, presence: true, if: :activated?
   validates :username,
     presence: true,
-    if: ->(service) { service.password? },
-    if: :activated?
+    if: ->(service) { service.activated? && service.password }
   validates :password,
     presence: true,
-    if: ->(service) { service.username? },
-    if: :activated?
+    if: ->(service) { service.activated? && service.username }
 
   attr_accessor :response
 
@@ -147,6 +145,6 @@ class TeamcityService < CiService
                           '</build>',
                     headers: { 'Content-type' => 'application/xml' },
                     basic_auth: auth
-        )
+                   )
   end
 end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 2c25f4ce451561a71301ccdcf952b535aa32a9d6..a9bf4eb4033251fcd67261f5ebaaeca7e1e45a58 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -76,7 +76,9 @@ class Repository
       path: path,
       limit: limit,
       offset: offset,
-      follow: path.present?
+      # --follow doesn't play well with --skip. See:
+      # https://gitlab.com/gitlab-org/gitlab-ce/issues/3574#note_3040520
+      follow: false
     }
 
     commits = Gitlab::Git::Commit.where(options)
@@ -592,47 +594,54 @@ class Repository
     Gitlab::Popen.popen(args, path_to_repo)
   end
 
-  def commit_with_hooks(current_user, branch)
-    oldrev = Gitlab::Git::BLANK_SHA
-    ref = Gitlab::Git::BRANCH_REF_PREFIX + branch
-    was_empty = empty?
-
-    # Create temporary ref
+  def with_tmp_ref(oldrev = nil)
     random_string = SecureRandom.hex
     tmp_ref = "refs/tmp/#{random_string}/head"
 
-    unless was_empty
-      oldrev = find_branch(branch).target
+    if oldrev && !Gitlab::Git.blank_ref?(oldrev)
       rugged.references.create(tmp_ref, oldrev)
     end
 
     # Make commit in tmp ref
-    newrev = yield(tmp_ref)
+    yield(tmp_ref)
+  ensure
+    rugged.references.delete(tmp_ref) rescue nil
+  end
+
+  def commit_with_hooks(current_user, branch)
+    oldrev = Gitlab::Git::BLANK_SHA
+    ref = Gitlab::Git::BRANCH_REF_PREFIX + branch
+    was_empty = empty?
 
-    unless newrev
-      raise CommitError.new('Failed to create commit')
+    unless was_empty
+      oldrev = find_branch(branch).target
     end
 
-    GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do
-      if was_empty
-        # Create branch
-        rugged.references.create(ref, newrev)
-      else
-        # Update head
-        current_head = find_branch(branch).target
+    with_tmp_ref(oldrev) do |tmp_ref|
+      # Make commit in tmp ref
+      newrev = yield(tmp_ref)
+
+      unless newrev
+        raise CommitError.new('Failed to create commit')
+      end
 
-        # Make sure target branch was not changed during pre-receive hook
-        if current_head == oldrev
-          rugged.references.update(ref, newrev)
+      GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do
+        if was_empty
+          # Create branch
+          rugged.references.create(ref, newrev)
         else
-          raise CommitError.new('Commit was rejected because branch received new push')
+          # Update head
+          current_head = find_branch(branch).target
+
+          # Make sure target branch was not changed during pre-receive hook
+          if current_head == oldrev
+            rugged.references.update(ref, newrev)
+          else
+            raise CommitError.new('Commit was rejected because branch received new push')
+          end
         end
       end
     end
-  rescue GitHooksService::PreReceiveError
-    # Remove tmp ref and return error to user
-    rugged.references.delete(tmp_ref)
-    raise
   end
 
   private
diff --git a/app/models/user.rb b/app/models/user.rb
index fdd14f4571d7a136b09f5f490c17b128cb45f67b..df87f3b79bd66735c96a65eda8298d1c7fabcfe5 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -26,6 +26,7 @@
 #  bio                        :string(255)
 #  failed_attempts            :integer          default(0)
 #  locked_at                  :datetime
+#  unlock_token               :string(255)
 #  username                   :string(255)
 #  can_create_group           :boolean          default(TRUE), not null
 #  can_create_team            :boolean          default(TRUE), not null
@@ -220,9 +221,9 @@ class User < ActiveRecord::Base
     def find_for_database_authentication(warden_conditions)
       conditions = warden_conditions.dup
       if login = conditions.delete(:login)
-        where(conditions).where(["lower(username) = :value OR lower(email) = :value", { value: login.downcase }]).first
+        where(conditions).find_by("lower(username) = :value OR lower(email) = :value", value: login.downcase)
       else
-        where(conditions).first
+        find_by(conditions)
       end
     end
 
@@ -285,7 +286,7 @@ class User < ActiveRecord::Base
     end
 
     def by_username_or_id(name_or_id)
-      where('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i).first
+      find_by('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i)
     end
 
     def build_user(attrs = {})
diff --git a/app/services/base_service.rb b/app/services/base_service.rb
index f00ec7408b683fb6f00e6c85c38ad04364bfeef3..b48ca67d4d2de1c561aedb04c307b42cdabc7903 100644
--- a/app/services/base_service.rb
+++ b/app/services/base_service.rb
@@ -39,10 +39,7 @@ class BaseService
   def deny_visibility_level(model, denied_visibility_level = nil)
     denied_visibility_level ||= model.visibility_level
 
-    level_name = 'Unknown'
-    Gitlab::VisibilityLevel.options.each do |name, level|
-      level_name = name if level == denied_visibility_level
-    end
+    level_name = Gitlab::VisibilityLevel.level_name(denied_visibility_level)
 
     model.errors.add(
       :visibility_level,
diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb
index de18f3bc5567f6c2194340fc3ed26dd76c3fe9e8..f139872c728ec618300c9a354ff6dffa5a176d85 100644
--- a/app/services/create_branch_service.rb
+++ b/app/services/create_branch_service.rb
@@ -1,10 +1,10 @@
 require_relative 'base_service'
 
 class CreateBranchService < BaseService
-  def execute(branch_name, ref)
+  def execute(branch_name, ref, source_project: @project)
     valid_branch = Gitlab::GitRefValidator.validate(branch_name)
     if valid_branch == false
-      return error('Branch name invalid')
+      return error('Branch name is invalid')
     end
 
     repository = project.repository
@@ -13,7 +13,20 @@ class CreateBranchService < BaseService
       return error('Branch already exists')
     end
 
-    new_branch = repository.add_branch(current_user, branch_name, ref)
+    new_branch = nil
+    if source_project != @project
+      repository.with_tmp_ref do |tmp_ref|
+        repository.fetch_ref(
+          source_project.repository.path_to_repo,
+          "refs/heads/#{ref}",
+          tmp_ref
+        )
+
+        new_branch = repository.add_branch(current_user, branch_name, tmp_ref)
+      end
+    else
+      new_branch = repository.add_branch(current_user, branch_name, ref)
+    end
 
     if new_branch
       push_data = build_push_data(project, current_user, new_branch)
diff --git a/app/services/create_commit_builds_service.rb b/app/services/create_commit_builds_service.rb
index 759c334ebe96dff6b630effa700fb12d0c57376f..31b407efeb1fe60d0af3635ecafcc2553ef316d0 100644
--- a/app/services/create_commit_builds_service.rb
+++ b/app/services/create_commit_builds_service.rb
@@ -16,9 +16,23 @@ class CreateCommitBuildsService
       return false
     end
 
-    tag = Gitlab::Git.tag_ref?(origin_ref)
-    commit = project.ensure_ci_commit(sha)
+    commit = project.ci_commit(sha)
+    unless commit
+      commit = project.ci_commits.new(sha: sha)
+
+      # Skip creating ci_commit when no gitlab-ci.yml is found
+      unless commit.ci_yaml_file
+        return false
+      end
+
+      # Create a new ci_commit
+      commit.save!
+    end
+
+    # Skip creating builds for commits that have [ci skip]
     unless commit.skip_ci?
+      # Create builds for commit
+      tag = Gitlab::Git.tag_ref?(origin_ref)
       commit.update_committed!
       commit.create_builds(ref, tag, user)
     end
diff --git a/app/services/files/base_service.rb b/app/services/files/base_service.rb
index 9a67b160940bfe0ca30b28107c9a1314d002da3a..0326a8823e975c20a7a02825ba1b1da94f27868f 100644
--- a/app/services/files/base_service.rb
+++ b/app/services/files/base_service.rb
@@ -3,8 +3,10 @@ module Files
     class ValidationError < StandardError; end
 
     def execute
-      @current_branch = params[:current_branch]
+      @source_project = params[:source_project] || @project
+      @source_branch = params[:source_branch]
       @target_branch  = params[:target_branch]
+
       @commit_message = params[:commit_message]
       @file_path      = params[:file_path]
       @file_content   = if params[:file_content_encoding] == 'base64'
@@ -16,8 +18,8 @@ module Files
       # Validate parameters
       validate
 
-      # Create new branch if it different from current_branch
-      if @target_branch != @current_branch
+      # Create new branch if it different from source_branch
+      if different_branch?
         create_target_branch
       end
 
@@ -26,18 +28,14 @@ module Files
       else
         error("Something went wrong. Your changes were not committed")
       end
-    rescue Repository::CommitError, GitHooksService::PreReceiveError, ValidationError => ex
+    rescue Repository::CommitError, Gitlab::Git::Repository::InvalidBlobName, GitHooksService::PreReceiveError, ValidationError => ex
       error(ex.message)
     end
 
     private
 
-    def current_branch
-      @current_branch ||= params[:current_branch]
-    end
-
-    def target_branch
-      @target_branch ||= params[:target_branch]
+    def different_branch?
+      @source_branch != @target_branch || @source_project != @project
     end
 
     def raise_error(message)
@@ -52,11 +50,11 @@ module Files
       end
 
       unless project.empty_repo?
-        unless repository.branch_names.include?(@current_branch)
+        unless @source_project.repository.branch_names.include?(@source_branch)
           raise_error("You can only create or edit files when you are on a branch")
         end
 
-        if @current_branch != @target_branch
+        if different_branch?
           if repository.branch_names.include?(@target_branch)
             raise_error("Branch with such name already exists. You need to switch to this branch in order to make changes")
           end
@@ -65,10 +63,10 @@ module Files
     end
 
     def create_target_branch
-      result = CreateBranchService.new(project, current_user).execute(@target_branch, @current_branch)
+      result = CreateBranchService.new(project, current_user).execute(@target_branch, @source_branch, source_project: @source_project)
 
       unless result[:status] == :success
-        raise_error("Something went wrong when we tried to create #{@target_branch} for you")
+        raise_error("Something went wrong when we tried to create #{@target_branch} for you: #{result[:message]}")
       end
     end
   end
diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb
index 2348920cc58c25a1900f3a40dd46e3f56dcee36f..e4cde4a2fd84e1ec3143f937a129ab4fbb13662f 100644
--- a/app/services/files/create_service.rb
+++ b/app/services/files/create_service.rb
@@ -26,7 +26,7 @@ module Files
       unless project.empty_repo?
         @file_path.slice!(0) if @file_path.start_with?('/')
 
-        blob = repository.blob_at_branch(@current_branch, @file_path)
+        blob = repository.blob_at_branch(@source_branch, @file_path)
 
         if blob
           raise_error("Your changes could not be committed because a file with the same name already exists")
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index 3d85f97b7e5a357e4c8188053e5b521f5fe156a1..a1a20e476819df6d507312edd8667da35a4a0016 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -1,6 +1,11 @@
 module Issues
   class CloseService < Issues::BaseService
     def execute(issue, commit = nil)
+      if project.jira_tracker? && project.jira_service.active
+        project.jira_service.execute(commit, issue)
+        return issue
+      end
+
       if project.default_issues_tracker? && issue.close
         event_service.close_issue(issue, current_user)
         create_note(issue, commit)
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index b26c7513f5bd7ddd54e3f5a9244ae1815734a99a..8b3d56c2b4c1b574d496934cc71c82b35faa9d57 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -112,7 +112,7 @@ module MergeRequests
 
       merge_requests_for_source_branch.each do |merge_request|
         SystemNoteService.change_branch_presence(
-            merge_request, merge_request.project, @current_user,
+          merge_request, merge_request.project, @current_user,
             :source, @branch_name, presence)
       end
     end
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 69bdd045ddfeece023c92821cd7d7cdb3cd89853..895e089bea3c74f47cb41dd811efe5730cc09b5b 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -3,12 +3,16 @@ module Projects
     def execute
       # check that user is allowed to set specified visibility_level
       new_visibility = params[:visibility_level]
-      if new_visibility && new_visibility.to_i != project.visibility_level
-        unless can?(current_user, :change_visibility_level, project) &&
-          Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
-          deny_visibility_level(project, new_visibility)
-          return project
+      if new_visibility
+        if new_visibility.to_i != project.visibility_level
+          unless can?(current_user, :change_visibility_level, project) &&
+            Gitlab::VisibilityLevel.allowed_for?(current_user, new_visibility)
+            deny_visibility_level(project, new_visibility)
+            return project
+          end
         end
+
+        return false unless visibility_level_allowed?(new_visibility)
       end
 
       new_branch = params[:default_branch]
@@ -23,5 +27,19 @@ module Projects
         end
       end
     end
+
+    private
+
+    def visibility_level_allowed?(level)
+      return true if project.visibility_level_allowed?(level)
+
+      level_name = Gitlab::VisibilityLevel.level_name(level)
+      project.errors.add(
+        :visibility_level,
+        "#{level_name} could not be set as visibility level of this project - parent project settings are more restrictive"
+      )
+
+      false
+    end
   end
 end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 6975b2ee55b55f2a2c713799cc37221188b91f3c..98a71cbf1ada720854f7627ce00206d709b5206d 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -241,9 +241,14 @@ class SystemNoteService
       note_options.merge!(noteable: noteable)
     end
 
-    create_note(note_options)
+    if noteable.is_a?(ExternalIssue)
+      noteable.project.issues_tracker.create_cross_reference_note(noteable, mentioner, author)
+    else
+      create_note(note_options)
+    end
   end
 
+
   def self.cross_reference?(note_text)
     note_text.start_with?(cross_reference_note_prefix)
   end
@@ -259,7 +264,7 @@ class SystemNoteService
   #
   # Returns Boolean
   def self.cross_reference_disallowed?(noteable, mentioner)
-    return true if noteable.is_a?(ExternalIssue)
+    return true if noteable.is_a?(ExternalIssue) && !noteable.project.jira_tracker_active?
     return false unless mentioner.is_a?(MergeRequest)
     return false unless noteable.is_a?(Commit)
 
diff --git a/app/uploaders/artifact_uploader.rb b/app/uploaders/artifact_uploader.rb
index 1dccc39e7e2e4d5902948453b71e19aab275866c..1b0ae6c00569b56c26c68a64c93203ccd42ae49a 100644
--- a/app/uploaders/artifact_uploader.rb
+++ b/app/uploaders/artifact_uploader.rb
@@ -20,16 +20,12 @@ class ArtifactUploader < CarrierWave::Uploader::Base
     @build, @field = build, field
   end
 
-  def artifacts_path
-    File.join(build.created_at.utc.strftime('%Y_%m'), build.project.id.to_s, build.id.to_s)
-  end
-
   def store_dir
-    File.join(ArtifactUploader.artifacts_path, artifacts_path)
+    File.join(self.class.artifacts_path, @build.artifacts_path)
   end
 
   def cache_dir
-    File.join(ArtifactUploader.artifacts_cache_path, artifacts_path)
+    File.join(self.class.artifacts_cache_path, @build.artifacts_path)
   end
 
   def file_storage?
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 6c355366948ec61bc7b62913c1ecb9f51ddf178c..214e0209bb7e31c5bf28e52a0f8c7f62c74d13b6 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -104,6 +104,18 @@
           = f.label :signin_enabled do
             = f.check_box :signin_enabled
             Sign-in enabled
+    .form-group
+      = f.label :two_factor_authentication, 'Two-Factor authentication', class: 'control-label col-sm-2'
+      .col-sm-10
+        .checkbox
+          = f.label :require_two_factor_authentication do
+            = f.check_box :require_two_factor_authentication
+            Require all users to setup Two-Factor authentication
+    .form-group
+      = f.label :two_factor_authentication, 'Two-Factor grace period (hours)', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.number_field :two_factor_grace_period, min: 0, class: 'form-control', placeholder: '0'
+        .help-block Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication
     .form-group
       = f.label :restricted_signup_domains, 'Restricted domains for sign-ups', class: 'control-label col-sm-2'
       .col-sm-10
@@ -144,5 +156,82 @@
       .col-sm-10
         = f.number_field :max_artifacts_size, class: 'form-control'
 
+  %fieldset
+    %legend Metrics
+    %p
+      These settings require a restart to take effect.
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          = f.label :metrics_enabled do
+            = f.check_box :metrics_enabled
+            Enable InfluxDB Metrics
+    .form-group
+      = f.label :metrics_host, 'InfluxDB host', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.text_field :metrics_host, class: 'form-control', placeholder: 'influxdb.example.com'
+    .form-group
+      = f.label :metrics_port, 'InfluxDB port', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.text_field :metrics_port, class: 'form-control', placeholder: '8089'
+        .help-block
+          The UDP port to use for connecting to InfluxDB. InfluxDB requires that
+          your server configuration specifies a database to store data in when
+          sending messages to this port, without it metrics data will not be
+          saved.
+    .form-group
+      = f.label :metrics_username, 'InfluxDB username', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.text_field :metrics_username, class: 'form-control'
+    .form-group
+      = f.label :metrics_password, 'InfluxDB password', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.text_field :metrics_password, class: 'form-control'
+    .form-group
+      = f.label :metrics_pool_size, 'Connection pool size', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.number_field :metrics_pool_size, class: 'form-control'
+        .help-block
+          The amount of InfluxDB connections to open. Connections are opened
+          lazily. Users using multi-threaded application servers should ensure
+          enough connections are available (at minimum the amount of application
+          server threads).
+    .form-group
+      = f.label :metrics_timeout, 'Connection timeout', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.number_field :metrics_timeout, class: 'form-control'
+        .help-block
+          The amount of seconds after which an InfluxDB connection will time
+          out.
+    .form-group
+      = f.label :metrics_method_call_threshold, 'Method Call Threshold (ms)', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.number_field :metrics_method_call_threshold, class: 'form-control'
+        .help-block
+          A method call is only tracked when it takes longer to complete than
+          the given amount of milliseconds.
+
+  %fieldset
+    %legend Spam and Anti-bot Protection
+    .form-group
+      .col-sm-offset-2.col-sm-10
+        .checkbox
+          = f.label :recaptcha_enabled do
+            = f.check_box :recaptcha_enabled
+            Enable reCAPTCHA
+          %span.help-block#recaptcha_help_block Helps preventing bots from creating accounts
+
+    .form-group
+      = f.label :recaptcha_site_key, 'reCAPTCHA Site Key', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.text_field :recaptcha_site_key, class: 'form-control'
+        .help-block
+          Generate site and private keys here:
+          %a{ href: 'http://www.google.com/recaptcha', target: 'blank'} http://www.google.com/recaptcha
+    .form-group
+      = f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'control-label col-sm-2'
+      .col-sm-10
+        = f.text_field :recaptcha_private_key, class: 'form-control'
+
   .form-actions
     = f.submit 'Save', class: 'btn btn-primary'
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 8657d2c71fe83eae1a39a5b521ca922acbbdca4c..531247e9148565a0e3b475a435c5a5bd709858bb 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -79,6 +79,10 @@
         GitLab API
         %span.pull-right
           = API::API::version
+      %p
+        Git
+        %span.pull-right
+          = Gitlab::Git.version
       %p
         Ruby
         %span.pull-right
diff --git a/app/views/admin/identities/index.html.haml b/app/views/admin/identities/index.html.haml
index 8358a14445b24c20eaa0e7edc661f42fd1187c32..741d111fb7d40c3db8e27f3127784eefc652e345 100644
--- a/app/views/admin/identities/index.html.haml
+++ b/app/views/admin/identities/index.html.haml
@@ -1,6 +1,7 @@
 - page_title "Identities", @user.name, "Users"
 = render 'admin/users/head'
 
+= link_to 'New Identity', new_admin_user_identity_path, class: 'pull-right btn btn-new'
 - if @identities.present?
   .table-holder
     %table.table
diff --git a/app/views/admin/identities/new.html.haml b/app/views/admin/identities/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..e30bf0ef0ee23fd90f03946282c2ecf315e4b316
--- /dev/null
+++ b/app/views/admin/identities/new.html.haml
@@ -0,0 +1,4 @@
+- page_title "New Identity"
+%h3.page-title New identity
+%hr
+= render 'form'
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index c5fb3c95506e2ea52b4bcc2ae8b17d78525747d3..c407972cd0875dd3c4b329acd7c649216eccf0f5 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -3,7 +3,7 @@
     To register a new runner you should enter the following registration token.
     With this token the runner will request a unique runner token and use that for future communication.
     Registration token is
-    %code{ id: 'runners-token' } #{current_application_settings.ensure_runners_registration_token}
+    %code{ id: 'runners-token' } #{current_application_settings.runners_registration_token}
 
 .bs-callout.clearfix
   .pull-left
diff --git a/app/views/ci/lints/_create.html.haml b/app/views/ci/lints/_create.html.haml
index 77f78caa8d886ac22324b676429399862314e8e3..f7875e68b7e668745e10e238e7c7d1899b820a66 100644
--- a/app/views/ci/lints/_create.html.haml
+++ b/app/views/ci/lints/_create.html.haml
@@ -41,5 +41,3 @@
     %i.fa.fa-remove.incorrect-syntax
   %b Error:
   = @error
-
-    
diff --git a/app/views/ci/lints/create.js.haml b/app/views/ci/lints/create.js.haml
deleted file mode 100644
index a96c0b11b6e06cb89baed0c3730f8c028883f675..0000000000000000000000000000000000000000
--- a/app/views/ci/lints/create.js.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-:plain
-  $(".results").html("#{escape_javascript(render "create")}")
\ No newline at end of file
diff --git a/app/views/ci/lints/show.html.haml b/app/views/ci/lints/show.html.haml
index fb9057e4882069229f557c83af711e1dbc719ab3..a144c43be477a260ccdad87422f114634285f135 100644
--- a/app/views/ci/lints/show.html.haml
+++ b/app/views/ci/lints/show.html.haml
@@ -1,27 +1,17 @@
 %h2 Check your .gitlab-ci.yml
 %hr
 
-= form_tag ci_lint_path, method: :post, remote: true do
-  .control-group
-    = label_tag :content, "Content of .gitlab-ci.yml", class: 'control-label'
-    .controls
-      = text_area_tag :content, nil, class: 'form-control span1', rows: 7, require: true
+.row
+  = form_tag ci_lint_path, method: :post do
+    .form-group
+      = label_tag :content, 'Content of .gitlab-ci.yml', class: 'control-label text-nowrap'
+      .col-sm-12
+        = text_area_tag :content, nil, class: 'form-control span1', rows: 7, require: true
+    .col-sm-12
+      .pull-left.prepend-top-10
+        = submit_tag 'Validate', class: 'btn btn-success submit-yml'
 
-  .control-group.clearfix
-    .controls.pull-left.prepend-top-10
-      = submit_tag "Validate", class: 'btn btn-success submit-yml'
-
-
-%p.text-center.loading
-  %i.fa.fa-refresh.fa-spin
-
-.results.prepend-top-20
-
-:javascript
-  $(".loading").hide();
-  $('form').bind('ajax:beforeSend', function() {
-    $(".loading").show();
-  });
-  $('form').bind('ajax:complete', function() {
-    $(".loading").hide();
-  });
+.row.prepend-top-20
+  .col-sm-12
+    .results
+      = render partial: 'create' if defined?(@status)
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index 2e77afb7525923d48e085aaaf47d61cc39c1e781..f4a3e3162bf5da1eeaecc7d4b6b56f290a94f427 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -1,13 +1,20 @@
 = content_for :flash_message do
   = render 'shared/project_limit'
+.top-area
+  %ul.left-top-menu
+    = nav_link(page: [dashboard_projects_path, root_path]) do
+      = link_to dashboard_projects_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do
+        Your Projects
+    = nav_link(page: starred_dashboard_projects_path) do
+      = link_to starred_dashboard_projects_path, title: 'Starred Projects', data: {placement: 'right'} do
+        Starred Projects
+    = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path], html_options: { class: 'hidden-xs' }) do
+      = link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do
+        Explore Projects
 
-%ul.center-top-menu
-  = nav_link(page: [dashboard_projects_path, root_path]) do
-    = link_to dashboard_projects_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do
-      Your Projects
-  = nav_link(page: starred_dashboard_projects_path) do
-    = link_to starred_dashboard_projects_path, title: 'Starred Projects', data: {placement: 'right'} do
-      Starred Projects
-  = nav_link(page: [explore_root_path, trending_explore_projects_path, starred_explore_projects_path, explore_projects_path], html_options: { class: 'hidden-xs' }) do
-    = link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do
-      Explore Projects
+  .projects-search-form  
+    = search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs', spellcheck: false
+    - if current_user.can_create_project?
+      = link_to new_project_path, class: 'btn btn-green' do
+        %i.fa.fa-plus
+        New Project
diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml
index 44b7efe523277e32a59cef41fb0631b75068e2fe..4316c358dcb81c2aa0f87e490b95499d529b8156 100644
--- a/app/views/dashboard/milestones/show.html.haml
+++ b/app/views/dashboard/milestones/show.html.haml
@@ -1,18 +1,18 @@
 - page_title @milestone.title, "Milestones"
 - header_title "Milestones", dashboard_milestones_path
 
-.issuable-details
-  .page-title
-    .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" }
-      - if @milestone.closed?
-        Closed
-      - else
-        Open
+.detail-page-header
+  .status-box{ class: "status-box-#{@milestone.closed? ? 'closed' : 'open'}" }
+    - if @milestone.closed?
+      Closed
+    - else
+      Open
+  %span.identifier
     Milestone #{@milestone.title}
 
-  .gray-content-block.middle-block
-    %h2.issue-title
-      = markdown escape_once(@milestone.title), pipeline: :single_line
+.detail-page-description.gray-content-block.second-block
+  %h2.title
+    = markdown escape_once(@milestone.title), pipeline: :single_line
 
 - if @milestone.complete? && @milestone.active?
   .alert.alert-success.prepend-top-default
diff --git a/app/views/dashboard/projects/_projects.html.haml b/app/views/dashboard/projects/_projects.html.haml
index 81a5909e2d2ac5f01430f000bf0512306320cedd..cea9ffcc748ad866e87d924b1785da19b94f10e4 100644
--- a/app/views/dashboard/projects/_projects.html.haml
+++ b/app/views/dashboard/projects/_projects.html.haml
@@ -1,11 +1,3 @@
 .projects-list-holder
-  .projects-search-form
-    .input-group
-      = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
-      - if current_user.can_create_project?
-        %span.input-group-btn
-          = link_to new_project_path, class: 'btn btn-green' do
-            %i.fa.fa-plus
-            New Project
 
   = render 'shared/projects/list', projects: @projects, ci: true
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb
deleted file mode 100644
index 79d6c761d8fce48f4bf9e757392c13cff3ecf16d..0000000000000000000000000000000000000000
--- a/app/views/devise/mailer/unlock_instructions.html.erb
+++ /dev/null
@@ -1,7 +0,0 @@
-<p>Hello <%= @resource.email %>!</p>
-
-<p>Your account has been locked due to an excessive amount of unsuccessful sign in attempts.</p>
-
-<p>Click the link below to unlock your account:</p>
-
-<p><%= link_to 'Unlock your account', unlock_url(@resource, unlock_token: @token) %></p>
diff --git a/app/views/devise/mailer/unlock_instructions.html.haml b/app/views/devise/mailer/unlock_instructions.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..52b327e20c5f71dec4a876fa2585ebfc921066c1
--- /dev/null
+++ b/app/views/devise/mailer/unlock_instructions.html.haml
@@ -0,0 +1,10 @@
+%p
+Hello #{@resource.name}!
+
+%p
+  Your GitLab account has been locked due to an excessive amount of unsuccessful
+  sign in attempts. Your account will automatically unlock in
+  = time_ago_in_words(Devise.unlock_in.from_now)
+  or you may click the link below to unlock now.
+
+%p= link_to 'Unlock your account', unlock_url(@resource, unlock_token: @token)
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 9dc6aeffd5947b903780be359101ab3ae8aa2cb5..cb93ff2465e055a77f1ee1405d02b129ed199f0b 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -6,17 +6,21 @@
     .login-heading
       %h3 Create an account
   .login-body
+    - user = params[:user].present? ? params[:user] : {}
     = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
       .devise-errors
         = devise_error_messages!
       %div
-        = f.text_field :name, class: "form-control top", placeholder: "Name", required: true
+        = f.text_field :name, class: "form-control top", value: user[:name], placeholder: "Name", required: true
       %div
-        = f.text_field :username, class: "form-control middle", placeholder: "Username", required: true
+        = f.text_field :username, class: "form-control middle", value: user[:username], placeholder: "Username", required: true
       %div
-        = f.email_field :email, class: "form-control middle", placeholder: "Email", required: true
+        = f.email_field :email, class: "form-control middle", value: user[:email], placeholder: "Email", required: true
       .form-group.append-bottom-20#password-strength
-        = f.password_field :password, class: "form-control bottom", id: "user_password_sign_up", placeholder: "Password", required: true
+        = f.password_field :password, class: "form-control bottom", value: user[:password], id: "user_password_sign_up", placeholder: "Password", required: true
+      %div
+      - if current_application_settings.recaptcha_enabled
+        = recaptcha_tags
       %div
         = f.submit "Sign up", class: "btn-create btn"
 
diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb
deleted file mode 100644
index f9277d1673fe35c0ab7a80339cb20c1159871823..0000000000000000000000000000000000000000
--- a/app/views/devise/unlocks/new.html.erb
+++ /dev/null
@@ -1,12 +0,0 @@
-<h2>Resend unlock instructions</h2>
-
-<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
-  <%= devise_error_messages! %>
-
-  <div><%= f.label :email %><br />
-  <%= f.email_field :email %></div>
-
-  <div><%= f.submit "Resend unlock instructions" %></div>
-<% end %>
-
-<%= render partial: "devise/shared/links" %>
diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..49c087c0646e42112a6266225eb0ecf0aa225039
--- /dev/null
+++ b/app/views/devise/unlocks/new.html.haml
@@ -0,0 +1,14 @@
+.login-box
+  .login-heading
+    %h3 Resend unlock email
+  .login-body
+    = form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f|
+      .devise-errors
+        = devise_error_messages!
+      .clearfix.append-bottom-20
+        = f.email_field :email, class: 'form-control', placeholder: 'Email', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off'
+      .clearfix
+        = f.submit 'Resend unlock instructions', class: 'btn btn-success'
+
+.clearfix.prepend-top-20
+  = render 'devise/shared/sign_in_link'
diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml
index 76bdd68fd764b3f8a7f9f8d0f7683adb0fc06e35..b9a958fbe7be505ab4a7aa705e91beef3dc518d4 100644
--- a/app/views/explore/projects/index.html.haml
+++ b/app/views/explore/projects/index.html.haml
@@ -6,7 +6,7 @@
 - else
   = render 'explore/head'
 
-.gray-content-block.clearfix
+.gray-content-block.clearfix.second-block
   = render 'filter'
 = render 'projects', projects: @projects
 = paginate @projects, theme: "gitlab"
diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml
index e30c3633223c026e86400fa0c47a7283e63d0aa9..95d46e331f8a1d4dc41aeee78142645c349440cc 100644
--- a/app/views/explore/projects/starred.html.haml
+++ b/app/views/explore/projects/starred.html.haml
@@ -7,7 +7,7 @@
   = render 'explore/head'
 
 .explore-trending-block
-  .gray-content-block
+  .gray-content-block.second-block
     .pull-right
       = render 'explore/projects/dropdown'
     .oneline
diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml
index 1412b19acde9b2fa25ea5f5596a8e965d4d106ec..fa0b718e48b7b37c6fc02b2dd347b9875a5d8264 100644
--- a/app/views/explore/projects/trending.html.haml
+++ b/app/views/explore/projects/trending.html.haml
@@ -7,7 +7,7 @@
   = render 'explore/head'
 
 .explore-trending-block
-  .gray-content-block
+  .gray-content-block.second-block
     .pull-right
       = render 'explore/projects/dropdown'
     .oneline
diff --git a/app/views/groups/_projects.html.haml b/app/views/groups/_projects.html.haml
index 11d69977ef9e03b87fd2c5bb113cd131651fb1d7..bbafc08435af438ca1f99bd3948208d73138910f 100644
--- a/app/views/groups/_projects.html.haml
+++ b/app/views/groups/_projects.html.haml
@@ -1,5 +1,5 @@
-.panel.panel-default.projects-list-holder
-  .panel-heading.clearfix
+.projects-list-holder
+  .projects-search-form
     .input-group
       = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
       - if can? current_user, :create_projects, @group
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 8daac5859601fcff465dbe568f449a2db0b0fcf9..1dea77c2e96be9c8211f3157448d268d56e9d362 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -31,7 +31,7 @@
         .col-sm-10
           .checkbox
             = f.check_box :public
-            %span.descr Make this group public (even if there is no any public project inside this group)
+            %span.descr Make this group public (even if there are no public projects inside this group)
 
       .form-actions
         = f.submit 'Save group', class: "btn btn-save"
diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml
index 350e216fcc61f6e2a61c12fb197a9fb924534090..d063b257b5e6df7aae5f9d79fdbdfc165718f228 100644
--- a/app/views/groups/milestones/show.html.haml
+++ b/app/views/groups/milestones/show.html.haml
@@ -1,24 +1,24 @@
 - page_title @milestone.title, "Milestones"
 = render "header_title"
 
-.issuable-details
-  .page-title
-    .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" }
-      - if @milestone.closed?
-        Closed
-      - else
-        Open
+.detail-page-header
+  .status-box{ class: "status-box-#{@milestone.closed? ? 'closed' : 'open'}" }
+    - if @milestone.closed?
+      Closed
+    - else
+      Open
+  %span.identifier
     Milestone #{@milestone.title}
-    .pull-right
-      - if can?(current_user, :admin_milestones, @group)
-        - if @milestone.active?
-          = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close"
-        - else
-          = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen"
+  .pull-right
+    - if can?(current_user, :admin_milestones, @group)
+      - if @milestone.active?
+        = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close"
+      - else
+        = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen"
 
-  .gray-content-block.middle-block
-    %h2.issue-title
-      = markdown escape_once(@milestone.title), pipeline: :single_line
+.detail-page-description.gray-content-block.second-block
+  %h2.title
+    = markdown escape_once(@milestone.title), pipeline: :single_line
 
 - if @milestone.complete? && @milestone.active?
   .alert.alert-success.prepend-top-default
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index dc8e81323a63daf43f7e527162142042b3a37111..c2c7c581b3eff57c5ad3d522f86bc77544a72709 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -5,37 +5,47 @@
   - if current_user
     = auto_discovery_link_tag(:atom, group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} activity")
 
-.dashboard
-  .header-with-avatar.clearfix
-    = image_tag group_icon(@group), class: "avatar group-avatar s90"
-    %h3
-      = @group.name
-    .username
-      @#{@group.path}
-    - if @group.description.present?
-      .description
-        = markdown(@group.description, pipeline: :description)
-  %hr
-
-  = render 'shared/show_aside'
-
-  - if can?(current_user, :read_group, @group)
-    .row
-      %section.activities.col-md-7
-        .hidden-xs
-          - if current_user
-            = render "events/event_last_push", event: @last_push
-            .pull-right
-              = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'btn rss-btn' do
-                %i.fa.fa-rss
-
-            = render 'shared/event_filter'
-            %hr
-
-        .content_list
-        = spinner
-      %aside.side.col-md-5
-        = render "projects", projects: @projects
-  - else
-    %p
-      This group does not have public projects
+.cover-block
+  .avatar-holder
+    = link_to group_icon(@group), target: '_blank' do
+      = image_tag group_icon(@group), class: "avatar group-avatar s90"
+  .cover-title
+    = @group.name
+
+  .cover-desc.username
+    @#{@group.path}
+
+  - if @group.description.present?
+    .cover-desc.description
+      = markdown(@group.description, pipeline: :description)
+
+- if can?(current_user, :read_group, @group)
+  %ul.center-top-menu.no-top
+    %li.active
+      = link_to "#activity", 'data-toggle' => 'tab' do
+        Activity
+    - if @projects.present?
+      %li
+        = link_to "#projects", 'data-toggle' => 'tab' do
+          Projects
+
+  .tab-content
+    .tab-pane.active#activity
+      .gray-content-block.activity-filter-block
+        - if current_user
+          = render "events/event_last_push", event: @last_push
+          .pull-right
+            = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'btn rss-btn' do
+              %i.fa.fa-rss
+
+          = render 'shared/event_filter'
+
+      .content_list
+      = spinner
+
+    .tab-pane#projects
+      = render "projects", projects: @projects
+
+- else
+  %p
+    This group does not have public projects
diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml
index 7e801b5332d9cc848a98e92f51c8e84db0bed059..e8e331dd10902ca7af6cbba70b36b2eab26aa642 100644
--- a/app/views/help/_shortcuts.html.haml
+++ b/app/views/help/_shortcuts.html.haml
@@ -219,11 +219,3 @@
                 %td.shortcut
                   .key r
                 %td Reply (quoting selected text)
-
-
-:javascript
-  $('.js-more-help-button').click(function (e) {
-    $(this).remove()l
-    $('.hidden-shortcut').show();
-    e.preventDefault();
-  });
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index 74174a72f5a8c39d972e339c02d61f528063e8bf..2e0bd2007a3bf16b49c19741ebd638b570568466 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -1,10 +1,26 @@
-- page_title "GitLab"
-%head
+%head{prefix: "og: http://ogp.me/ns#"}
   %meta{charset: "utf-8"}
   %meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'}
-  %meta{content: "GitLab Community Edition", name: "description"}
   %meta{name: 'referrer', content: 'origin-when-cross-origin'}
 
+  %meta{name: "description", content: page_description}
+
+  -# Open Graph - http://ogp.me/
+  %meta{property: 'og:type',        content: "object"}
+  %meta{property: 'og:site_name',   content: "GitLab"}
+  %meta{property: 'og:title',       content: page_title}
+  %meta{property: 'og:description', content: page_description}
+  %meta{property: 'og:image',       content: page_image}
+  %meta{property: 'og:url',         content: request.base_url + request.fullpath}
+
+  -# Twitter Card - https://dev.twitter.com/cards/types/summary
+  %meta{property: 'twitter:card',         content: "summary"}
+  %meta{property: 'twitter:title',        content: page_title}
+  %meta{property: 'twitter:description',  content: page_description}
+  %meta{property: 'twitter:image',        content: page_image}
+  = page_card_meta_tags
+
+  - page_title "GitLab"
   %title= page_title
 
   = favicon_link_tag 'favicon.ico'
diff --git a/app/views/notify/_note_message.html.haml b/app/views/notify/_note_message.html.haml
index 27112c6745a657c3072e00385d230861fecff1cc..00cb4aa24cc28b60b4e1c2c98efc7eff2050a1b6 100644
--- a/app/views/notify/_note_message.html.haml
+++ b/app/views/notify/_note_message.html.haml
@@ -1,4 +1,2 @@
-%div
-  "#{link_to @note.author_name, user_url(@note.author)} wrote:"
 %div
   = markdown(@note.note, pipeline: :email)
diff --git a/app/views/profiles/keys/new.html.haml b/app/views/profiles/keys/new.html.haml
index 11166dc6d9985e4b626289a4e28b09c817533c78..13a18269d11b57c0dc2fd6ee3ca257ce59cd4306 100644
--- a/app/views/profiles/keys/new.html.haml
+++ b/app/views/profiles/keys/new.html.haml
@@ -12,6 +12,6 @@
         comment = val.match(/^\S+ \S+ (.+)\n?$/);
 
     if( comment && comment.length > 1 && title.val() == '' ){
-      $('#key_title').val( comment[1] );
+      $('#key_title').val( comment[1] ).change();
     }
   });
diff --git a/app/views/profiles/two_factor_auths/new.html.haml b/app/views/profiles/two_factor_auths/new.html.haml
index 92dc58c10d71f643e733a15773f2c02e39141395..1a5b6efce3558e457a129203bff3fad0589f28a2 100644
--- a/app/views/profiles/two_factor_auths/new.html.haml
+++ b/app/views/profiles/two_factor_auths/new.html.haml
@@ -38,3 +38,4 @@
       = text_field_tag :pin_code, nil, class: "form-control", required: true, autofocus: true
   .form-actions
     = submit_tag 'Submit', class: 'btn btn-success'
+    = link_to 'Configure it later', skip_profile_two_factor_auth_path, :method => :patch,  class: 'btn btn-cancel' if two_factor_skippable?
diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml
index 2fd3d9e1be454bc889bc57c9419f5c9b9583b502..640612ca433d0ac29e6bb6381d914c001a6925cf 100644
--- a/app/views/projects/_commit_button.html.haml
+++ b/app/views/projects/_commit_button.html.haml
@@ -2,3 +2,7 @@
   = button_tag 'Commit Changes', class: 'btn commit-btn js-commit-button btn-create'
   = link_to 'Cancel', cancel_path,
             class: 'btn btn-cancel', data: {confirm: leave_edit_message}
+
+  - unless can?(current_user, :push_code, @project)
+    .inline.prepend-left-10
+      = commit_in_fork_help
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index c1669ac046b4207ae92914d078b0871e8e8bec0b..e92115b9b987ba29111ba28c8f6be4991c7816c6 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -27,7 +27,7 @@
         = icon('rss')
 
   .project-repo-buttons
-    .split-one
+    .split-one.count-buttons
       = render 'projects/buttons/star'
       = render 'projects/buttons/fork'
 
@@ -38,3 +38,6 @@
       = render 'projects/buttons/dropdown'
 
     = render 'projects/buttons/notifications'
+
+:coffeescript
+  new Star()
\ No newline at end of file
diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml
index b1df8d19938326eab5ec0622846a3d401257a5d3..cdac50f7a8d3a5c7c14d57659c38b114ae8262e9 100644
--- a/app/views/projects/blob/_actions.html.haml
+++ b/app/views/projects/blob/_actions.html.haml
@@ -2,7 +2,7 @@
   = link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id),
       class: 'btn btn-sm', target: '_blank'
   -# only show normal/blame view links for text files
-  - if blob_viewable?(@blob)
+  - if blob_text_viewable?(@blob)
     - if current_page? namespace_project_blame_path(@project.namespace, @project, @id)
       = link_to 'Normal View', namespace_project_blob_path(@project.namespace, @project, @id),
           class: 'btn btn-sm'
@@ -14,13 +14,8 @@
   = link_to 'Permalink', namespace_project_blob_path(@project.namespace, @project,
       tree_join(@commit.sha, @path)), class: 'btn btn-sm'
 
-- if blob_editable?(@blob)
+- if current_user
   .btn-group{ role: "group" }
-    = edit_blob_link(@project, @ref, @path)
-    %button.btn.btn-default{ 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } Replace
-    %button.btn.btn-remove{ 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal' } Delete
-- elsif !on_top_of_branch?
-  .btn-group{ role: "group" }
-    %button.btn.btn-default.disabled.has_tooltip{title: "You can only edit files when you are on a branch.", data: {container: 'body'}} Edit
-    %button.btn.btn-default.disabled.has_tooltip{title: "You can only replace files when you are on a branch.", data: {container: 'body'}} Replace
-    %button.btn.btn-remove.disabled.has_tooltip{title: "You can only delete files when you are on a branch.", data: {container: 'body'}} Delete
+    = edit_blob_link
+    = replace_blob_link
+    = delete_blob_link
diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml
index fc6c9f5fd094d8f57c5252324e734852554f943c..084608bbba38c7a5f64fb923ec7ce9e868b88a86 100644
--- a/app/views/projects/blob/_new_dir.html.haml
+++ b/app/views/projects/blob/_new_dir.html.haml
@@ -17,5 +17,9 @@
             = submit_tag "Create directory", class: 'btn btn-create'
             = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
 
+            - unless can?(current_user, :push_code, @project)
+              .inline.prepend-left-10
+                = commit_in_fork_help
+
 :javascript
   new NewCommitForm($('.js-create-dir-form'))
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
index ecc90a30e78869103b0930f68e3d2d6cef7ba62d..676924dc6ca2d366ba98717f882c20a4b837682d 100644
--- a/app/views/projects/blob/_upload.html.haml
+++ b/app/views/projects/blob/_upload.html.haml
@@ -20,6 +20,11 @@
             = button_tag button_title, class: 'btn btn-small btn-create btn-upload-file', id: 'submit-all'
             = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
 
+            - unless can?(current_user, :push_code, @project)
+              .inline.prepend-left-10
+                = commit_in_fork_help
+
+
 :javascript
   disableButtonIfEmptyField($('.js-upload-blob-form').find('.js-commit-message'), '.btn-upload-file');
   new BlobFileDropzone($('.js-upload-blob-form'), '#{method}');
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index a47fe7ede8059d19e7839114d90d855970b3bdb3..09fa148b129b03ec047f78748462478afe4784df 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -20,7 +20,7 @@
     = hidden_field_tag 'last_commit', @last_commit
     = hidden_field_tag 'content', '', id: "file-content"
     = hidden_field_tag 'from_merge_request_id', params[:from_merge_request_id]
-    = render 'projects/commit_button', ref: @ref, cancel_path: @after_edit_path
+    = render 'projects/commit_button', ref: @ref, cancel_path: namespace_project_blob_path(@project.namespace, @project, @id)
 
 :javascript
   blob = new EditBlob(gon.relative_url_root + "#{Gitlab::Application.config.assets.prefix}", "#{@blob.language.try(:ace_mode)}")
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index 3f8d11ed8c85614ceec49bd1df31d3a63c77942c..6988039b6c7233e30de71f7fc300fa7a949b18d0 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -6,7 +6,7 @@
 %div#tree-holder.tree-holder
   = render 'blob', blob: @blob
 
-- if blob_editable?(@blob)
+- if can_edit_blob?(@blob)
   = render 'projects/blob/remove'
 
   - title = "Replace #{@blob.name}"
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 31943a2407a275fd00717251fdfb2f287678298d..c659af6338c477dacc83c28417567c7064f20c0b 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -9,11 +9,12 @@
   New Branch
 %hr
 
-= form_tag namespace_project_branches_path, method: :post, id: "new-branch-form", class: "form-horizontal js-requires-input" do
+= form_tag namespace_project_branches_path, method: :post, id: "new-branch-form", class: "form-horizontal js-create-branch-form js-requires-input" do
   .form-group
     = label_tag :branch_name, nil, class: 'control-label'
     .col-sm-10
-      = text_field_tag :branch_name, params[:branch_name], required: true, tabindex: 1, autofocus: true, class: 'form-control'
+      = text_field_tag :branch_name, params[:branch_name], required: true, tabindex: 1, autofocus: true, class: 'form-control js-branch-name'
+      .help-block.text-danger.js-branch-name-error
   .form-group
     = label_tag :ref, 'Create from', class: 'control-label'
     .col-sm-10
@@ -26,7 +27,4 @@
 :javascript
   var availableRefs = #{@project.repository.ref_names.to_json};
 
-  $("#ref").autocomplete({
-    source: availableRefs,
-    minLength: 1
-  });
+  new NewBranchForm($('.js-create-branch-form'), availableRefs)
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index 20a5b6a66e7038d573028777ec9c4c3a457ad9fb..5b7ecce86ab2b9041019e526650a50e45eb124a0 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -7,6 +7,10 @@
     %strong.monospace= link_to @build.commit.short_sha, ci_status_path(@build.commit)
     from
     = link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
+    - merge_request = @build.merge_request
+    - if merge_request
+      via
+      = link_to "merge request ##{merge_request.iid}", merge_request_path(merge_request)
 
   #up-build-trace
   - if @commit.matrix_for_ref?(@build.ref)
diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml
index b277b765b6b526a0c123e01823c0e9cdd9012f5a..1f639fecc308decd4fb7bff135ec9c6be8ca2108 100644
--- a/app/views/projects/buttons/_dropdown.html.haml
+++ b/app/views/projects/buttons/_dropdown.html.haml
@@ -18,10 +18,11 @@
           = link_to new_namespace_project_snippet_path(@project.namespace, @project) do
             = icon('file-text-o fw')
             New snippet
+
       - if can?(current_user, :push_code, @project)
         %li.divider
         %li
-          = link_to namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master'), title: 'New file' do
+          = link_to namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master') do
             = icon('file fw')
             New file
         %li
@@ -32,3 +33,20 @@
           = link_to new_namespace_project_tag_path(@project.namespace, @project) do
             = icon('tags fw')
             New tag
+      - elsif current_user && current_user.already_forked?(@project)
+        %li.divider
+        %li
+          = link_to namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master') do
+            = icon('file fw')
+            New file
+      - elsif can?(current_user, :fork_project, @project)
+        %li.divider
+        %li
+          - continue_params = { to:         namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master'),
+                                notice:     edit_in_new_fork_notice,
+                                notice_now: edit_in_new_fork_notice_now }
+          - fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key:  current_user.namespace.id,
+                                                                                  continue:       continue_params)
+          = link_to fork_path, method: :post do
+            = icon('file fw')
+            New file
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index 2d3abf09051852a7bab10bf71923ce8726e86614..133531887a202cfabb18762643723d48d437c55f 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -4,10 +4,15 @@
       = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has_tooltip' do
         = icon('code-fork fw')
         Fork
+      %div.count-with-arrow
+        %span.arrow
         %span.count
           = @project.forks_count
     - else
       = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has_tooltip' do
         = icon('code-fork fw')
+        Fork
+      %div.count-with-arrow
+        %span.arrow
         %span.count
           = @project.forks_count
diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml
index 41a3ec6d90fafbed9a389e5cd59486ad678c4837..21ba426aaa1e779a139aa29bc25ecc32be41c49f 100644
--- a/app/views/projects/buttons/_star.html.haml
+++ b/app/views/projects/buttons/_star.html.haml
@@ -1,19 +1,21 @@
 - if current_user
   = link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do
-    = icon('star fw')
-    %span.count
+    - if current_user.starred?(@project)
+      = icon('star fw')
+      %span.starred Unstar
+    - else
+      = icon('star-o fw')
+      %span Star
+  %div.count-with-arrow
+    %span.arrow
+    %span.count.star-count
       = @project.star_count
 
-  :javascript
-    $('.project-home-panel .toggle-star').on('ajax:success', function (e, data, status, xhr) {
-      $(this).replaceWith(data.html);
-    })
-    .on('ajax:error', function (e, xhr, status, error) {
-      new Flash('Star toggle failed. Try again later.', 'alert');
-    });
-
 - else
   = link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do
     = icon('star fw')
+    Star
+  %div.count-with-arrow
+    %span.arrow
     %span.count
       = @project.star_count
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 634924db247f4405c2be374e8c6dd0a0b60a7d60..ddb77fd796b13f03c74cc7e9aea68e8e0bc46e37 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -20,8 +20,8 @@
 
 %p
   %span.light Commit
-  = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace", data: { clipboard_text: @commit.id }
-  = clipboard_button
+  = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace"
+  = clipboard_button(clipboard_text: @commit.id)
 .commit-info-row
   %span.light Authored by
   %strong
@@ -40,7 +40,7 @@
   - @commit.parents.each do |parent|
     = link_to parent.short_id, namespace_project_commit_path(@project.namespace, @project, parent), class: "monospace"
 
-- if @ci_commit && @ci_commit.show_build_status?
+- if @ci_commit
   .pull-right
     = link_to ci_status_path(@ci_commit), class: "ci-status ci-#{@ci_commit.status}" do
       = ci_status_icon(@ci_commit)
diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml
index 45a00e4d259d82a8d6076939e22ea74250d87906..74a05df24d3db44b5365de2cc6f562325156cd12 100644
--- a/app/views/projects/commit_statuses/_commit_status.html.haml
+++ b/app/views/projects/commit_statuses/_commit_status.html.haml
@@ -19,11 +19,11 @@
 
   - if defined?(commit_sha) && commit_sha
     %td
-      = link_to commit_status.short_sha, namespace_project_commit_path(@project.namespace, @project, commit_status.sha), class: "monospace"
-
+      = link_to commit_status.short_sha, namespace_project_commit_path(commit_status.project.namespace, commit_status.project, commit_status.sha), class: "monospace"
+      
   %td
     - if commit_status.ref
-      = link_to commit_status.ref, namespace_project_commits_path(@project.namespace, @project, commit_status.ref)
+      = link_to commit_status.ref, namespace_project_commits_path(commit_status.project.namespace, commit_status.project, commit_status.ref)
     - else
       .light none
 
@@ -66,7 +66,7 @@
 
   %td
     .pull-right
-      - if current_user && can?(current_user, :download_build_artifacts, @project) && commit_status.download_url
+      - if current_user && can?(current_user, :download_build_artifacts, commit_status.project) && commit_status.download_url
         = link_to commit_status.download_url, title: 'Download artifacts' do
           %i.fa.fa-download
       - if current_user && can?(current_user, :manage_builds, commit_status.project)
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 1303b27c4f34b3b9a46613d22575ef07075d1fe0..28b82dd31f3eb549d1eb7111f0c4d501b09efb5f 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -17,7 +17,7 @@
           %a.text-expander.js-toggle-button ...
 
       .pull-right
-        - if ci_commit && ci_commit.show_build_status?
+        - if ci_commit
           = render_ci_status(ci_commit)
           &nbsp;
         = clipboard_button(clipboard_text: commit.id)
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 327e7d9245a625f916a538e0d3805a546c99d3db..517f6aef7c5a89e356407058e781455467cb8640 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -24,7 +24,7 @@
             = "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}"
 
       .diff-controls
-        - if blob_viewable?(blob)
+        - if blob_text_viewable?(blob)
           = link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do
             %i.fa.fa-comments
           &nbsp;
@@ -32,14 +32,15 @@
         - if editable_diff?(diff_file)
           = edit_blob_link(@merge_request.source_project,
               @merge_request.source_branch, diff_file.new_path,
-              after: '&nbsp;', from_merge_request_id: @merge_request.id)
+              from_merge_request_id: @merge_request.id)
+          &nbsp;
 
         = view_file_btn(diff_commit.id, diff_file, project)
 
   .diff-content.diff-wrap-lines
     -# Skipp all non non-supported blobs
     - return unless blob.respond_to?('text?')
-    - if blob_viewable?(blob)
+    - if blob_text_viewable?(blob)
       - if diff_view == 'parallel'
         = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i
       - else
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index f0b0a11c04a30de76383dd410d22bac157c3d580..8a2c027a45517d6ad288122d5b416c840f9ac006 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -43,4 +43,3 @@
       %i.fa.fa-spinner.fa-spin
       Forking repository
     %p Please wait a moment, this page will automatically refresh when ready.
-
diff --git a/app/views/projects/issues/_closed_by_box.html.haml b/app/views/projects/issues/_closed_by_box.html.haml
index 3c491c1a8b8a6a40077e8346ad6311f1a404b4ba..de415ae51a41d1979f408fc8102716dfd2c98f06 100644
--- a/app/views/projects/issues/_closed_by_box.html.haml
+++ b/app/views/projects/issues/_closed_by_box.html.haml
@@ -1,3 +1,2 @@
-.issue-closed-by-widget
-  = icon('check')
+.issue-closed-by-widget.gray-content-block.second-block.white
   This issue will be closed automatically when merge request #{markdown(merge_requests_sentence(@closed_by_merge_requests), pipeline: :gfm)} is accepted.
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index 405bae1bbb9148eb1479897f6aa3a5b3485bb9e7..dc434cf38c4ab006432903456cfd5dace77a4865 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -1,12 +1,9 @@
 - content_for :note_actions do
   - if can?(current_user, :update_issue, @issue)
     - if @issue.closed?
-      = link_to 'Reopen Issue', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-grouped btn-reopen js-note-target-reopen', title: 'Reopen Issue'
+      = link_to 'Reopen Issue', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-nr btn-grouped btn-reopen js-note-target-reopen', title: 'Reopen Issue'
     - else
-      = link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close js-note-target-close', title: 'Close Issue'
-
-.gray-content-block.second-block.oneline-block
-  = render 'votes/votes_block', votable: @issue
+      = link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-nr btn-grouped btn-close js-note-target-close', title: 'Close Issue'
 
 #notes
   = render 'projects/notes/notes_with_form'
diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml
index fe856ac991e17d07d1188914e71dd381e5be632d..254968e4f678f7850a25b3c74d33a77dd8b90531 100644
--- a/app/views/projects/issues/_merge_requests.html.haml
+++ b/app/views/projects/issues/_merge_requests.html.haml
@@ -15,9 +15,10 @@
         %span.merge-request-info
           %strong
             = link_to_gfm merge_request.title, merge_request_path(merge_request), class: "row_title"
-          in
-          - project = merge_request.target_project
-          = link_to project.name_with_namespace, namespace_project_path(project.namespace, project)
+          - unless @issue.project.id == merge_request.target_project.id
+            in
+            - project = merge_request.target_project
+            = link_to project.name_with_namespace, namespace_project_path(project.namespace, project)
         %span.merge-request-status.prepend-left-10
           - if merge_request.merged?
             MERGED
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index cc2cf8c871698721344641f0baba101f9f180da7..f931a0d3b92bcdfc6f2bfb8830f6f23ebfe43ada 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -1,61 +1,64 @@
-- page_title "#{@issue.title} (##{@issue.iid})", "Issues"
+- page_title           "#{@issue.title} (##{@issue.iid})", "Issues"
+- page_description     @issue.description
+- page_card_attributes @issue.card_attributes
+
 = render "header_title"
 
 .issue
+  .detail-page-header
+    .status-box{ class: "status-box-closed #{issue_button_visibility(@issue, false)}"} Closed
+    .status-box{ class: "status-box-open #{issue_button_visibility(@issue, true)}"} Open
+    %span.identifier
+      Issue ##{@issue.iid}
+    %span.creator
+      &middot;
+      opened by #{link_to_member(@project, @issue.author, size: 24)}
+      &middot;
+      = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago')
+      - if @issue.updated_at != @issue.created_at
+        %span
+          &middot;
+          = icon('edit', title: 'edited')
+          = time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago')
+
+    .pull-right
+      - if can?(current_user, :create_issue, @project)
+        = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-nr btn-grouped new-issue-link btn-success', title: 'New Issue', id: 'new_issue_link' do
+          = icon('plus')
+          New Issue
+      - if can?(current_user, :update_issue, @issue)
+        = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen Issue'
+        = link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-close #{issue_button_visibility(@issue, true)}", title: 'Close Issue'
+
+        = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-nr btn-grouped issuable-edit' do
+          = icon('pencil-square-o')
+          Edit
+
   .issue-details.issuable-details
-    .issuable-title
-      .issue-box{ class: issue_box_class(@issue) }
-        - if @issue.closed?
-          Closed
-        - else
-          Open
-      %span.issuable-id Issue ##{@issue.iid}
-      %span.creator
-        &middot;
-        opened by #{link_to_member(@project, @issue.author, size: 24)}
-        &middot;
-        = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago')
-        - if @issue.updated_at != @issue.created_at
-          %span
-            &middot;
-            = icon('edit', title: 'edited')
-            = time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago')
+    .detail-page-description.gray-content-block.second-block
+      %h2.title
+        = markdown escape_once(@issue.title), pipeline: :single_line
+      %div
+        - if @issue.description.present?
+          .description{class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : ''}
+            .wiki
+              = preserve do
+                = markdown(@issue.description, cache_key: [@issue, "description"])
+            %textarea.hidden.js-task-list-field
+              = @issue.description
 
-      .pull-right
-        - if can?(current_user, :create_issue, @project)
-          = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-grouped new-issue-link', title: 'New Issue', id: 'new_issue_link' do
-            = icon('plus')
-            New Issue
-        - if can?(current_user, :update_issue, @issue)
-          - if @issue.closed?
-            = link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true), method: :put, class: 'btn btn-grouped btn-reopen'
-          - else
-            = link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true), method: :put, class: 'btn btn-grouped btn-close', title: 'Close Issue'
+        .merge-requests
+          = render 'merge_requests'
 
-          = link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-grouped issuable-edit' do
-            = icon('pencil-square-o')
-            Edit
+    .gray-content-block.second-block.oneline-block
+      = render 'votes/votes_block', votable: @issue
+
+    - if @closed_by_merge_requests.present?
+      = render 'projects/issues/closed_by_box'
 
     .row
       %section.col-md-9
-        .gray-content-block
-          %h2.issue-title
-            = markdown escape_once(@issue.title), pipeline: :single_line
-          %div
-            - if @issue.description.present?
-              .description{class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : ''}
-                .wiki
-                  = preserve do
-                    = markdown(@issue.description, cache_key: [@issue, "description"])
-                %textarea.hidden.js-task-list-field
-                  = @issue.description
-
-            .merge-requests
-              = render 'merge_requests'
-
-        - if @closed_by_merge_requests.present?
-          = render 'projects/issues/closed_by_box'
-        .issue-discussion
+        .issuable-discussion
           = render 'projects/issues/discussion'
 
       %aside.col-md-3
diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml
index 7a7428d35ccc18bf7caf8e160db438fccf606b42..bff3c3b283ddf33a3fee9104980120eb62136021 100644
--- a/app/views/projects/merge_requests/_discussion.html.haml
+++ b/app/views/projects/merge_requests/_discussion.html.haml
@@ -1,11 +1,8 @@
 - content_for :note_actions do
   - if can?(current_user, :update_merge_request, @merge_request)
     - if @merge_request.open?
-      = link_to 'Close', merge_request_path(@merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-grouped btn-close close-mr-link js-note-target-close", title: "Close merge request"
+      = link_to 'Close', merge_request_path(@merge_request, merge_request: {state_event: :close }), method: :put, class: "btn btn-nr btn-grouped btn-close close-mr-link js-note-target-close", title: "Close merge request"
     - if @merge_request.closed?
-      = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request"
-
-.gray-content-block.second-block.oneline-block
-  = render 'votes/votes_block', votable: @merge_request
+      = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-nr btn-grouped btn-reopen reopen-mr-link js-note-target-reopen", title: "Reopen merge request"
 
 #notes= render "projects/notes/notes_with_form"
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 105c731c7e14a2327c9086107d20046ca7446160..a051729dc3202221a75da4595df695a9f4eaead2 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -17,7 +17,7 @@
 
       - if merge_request.open? && merge_request.broken?
         %li
-          = link_to merge_request_path(merge_request), class: "has_tooltip", title: "Cannot be merged automatically", data: {container: 'body'} do
+          = link_to merge_request_path(merge_request), class: "has_tooltip", title: "Cannot be merged automatically", data: { container: 'body' } do
             = icon('exclamation-triangle')
 
       - if merge_request.assignee
diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml
index 4172d5a4e88b4a06a99442c89e0ba90dcade23f6..a14943b15d3f1532ac6b0e94fb3162817988a16c 100644
--- a/app/views/projects/merge_requests/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/_new_submit.html.haml
@@ -23,15 +23,15 @@
       = link_to url_for(params), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
         Commits
         %span.badge= @commits.size
-    %li.diffs-tab.active
-      = link_to url_for(params), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
-        Changes
-        %span.badge= @diffs.size
     - if @ci_commit
       %li.builds-tab.active
         = link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do
           Builds
           %span.badge= @statuses.size
+    %li.diffs-tab.active
+      = link_to url_for(params), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
+        Changes
+        %span.badge= @diffs.size
 
   .tab-content
     #commits.commits.tab-pane
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index 04f8fd7442207094ef5596b8b6796f654e31f14e..ba7c2c01e93a7ac6760633a325672ab9db40b1e8 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -1,85 +1,91 @@
-- page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests"
+- page_title           "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests"
+- page_description     @merge_request.description
+- page_card_attributes @merge_request.card_attributes
+
 = render "header_title"
 
 - if params[:view] == 'parallel'
   - fluid_layout true
 
 .merge-request{'data-url' => merge_request_path(@merge_request)}
-  .merge-request-details.issuable-details
-    = render "projects/merge_requests/show/mr_title"
-    .row
-      %section.col-md-9
-        = render "projects/merge_requests/show/mr_box"
-        .append-bottom-default.mr-source-target.prepend-top-default
-          - if @merge_request.open?
-            .pull-right
-              - if @merge_request.source_branch_exists?
-                = link_to "#modal_merge_info", class: "btn btn-sm", "data-toggle" => "modal" do
-                  = icon('cloud-download fw')
-                  Check out branch
+  = render "projects/merge_requests/show/mr_title"
 
-              %span.dropdown
-                %a.btn.btn-sm.dropdown-toggle{ data: {toggle: :dropdown} }
-                  = icon('download')
-                  Download as
-                  %span.caret
-                %ul.dropdown-menu
-                  %li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch)
-                  %li= link_to "Plain Diff",    merge_request_path(@merge_request, format: :diff)
-          .normal
-            %span Request to merge
-            %span.label-branch= source_branch_with_namespace(@merge_request)
-            %span into
-            = link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
-              = @merge_request.target_branch
+  .merge-request-details.issuable-details
+    = render "projects/merge_requests/show/mr_box"
+    .append-bottom-default.mr-source-target.prepend-top-default
+      - if @merge_request.open?
+        .pull-right
+          - if @merge_request.source_branch_exists?
+            = link_to "#modal_merge_info", class: "btn btn-sm", "data-toggle" => "modal" do
+              = icon('cloud-download fw')
+              Check out branch
 
-        = render "projects/merge_requests/show/how_to_merge"
-        = render "projects/merge_requests/widget/show.html.haml"
+          %span.dropdown
+            %a.btn.btn-sm.dropdown-toggle{ data: {toggle: :dropdown} }
+              = icon('download')
+              Download as
+              %span.caret
+            %ul.dropdown-menu
+              %li= link_to "Email Patches", merge_request_path(@merge_request, format: :patch)
+              %li= link_to "Plain Diff",    merge_request_path(@merge_request, format: :diff)
+      .normal
+        %span Request to merge
+        %span.label-branch= source_branch_with_namespace(@merge_request)
+        %span into
+        = link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
+          = @merge_request.target_branch
 
-        - if @merge_request.open? && @merge_request.source_branch_exists? && @merge_request.can_be_merged? && @merge_request.can_be_merged_by?(current_user)
-          .light.prepend-top-default
-            You can also accept this merge request manually using the
-            = succeed '.' do
-              = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
+    = render "projects/merge_requests/show/how_to_merge"
+    = render "projects/merge_requests/widget/show.html.haml"
 
-        - if @commits.present?
-          %ul.merge-request-tabs.center-top-menu.no-top.no-bottom
-            %li.notes-tab
-              = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do
-                Discussion
-                %span.badge= @merge_request.mr_and_commit_notes.user.count
-            %li.commits-tab
-              = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
-                Commits
-                %span.badge= @commits.size
-            %li.diffs-tab
-              = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
-                Changes
-                %span.badge= @merge_request.diffs.size
-            - if @ci_commit
-              %li.builds-tab
-                = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
-                  Builds
-                  %span.badge= @statuses.size
+    - if @merge_request.open? && @merge_request.source_branch_exists? && @merge_request.can_be_merged? && @merge_request.can_be_merged_by?(current_user)
+      .light.prepend-top-default
+        You can also accept this merge request manually using the
+        = succeed '.' do
+          = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
 
-        .tab-content
-          #notes.notes.tab-pane.voting_notes
-            = render "projects/merge_requests/discussion"
-          #commits.commits.tab-pane
-            - # This tab is always loaded via AJAX
-          #diffs.diffs.tab-pane
-            - # This tab is always loaded via AJAX
-          #builds.builds.tab-pane
-            - # This tab is always loaded via AJAX
+    - if @commits.present?
+      %ul.merge-request-tabs.center-top-menu.no-top.no-bottom
+        %li.notes-tab
+          = link_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#notes', action: 'notes', toggle: 'tab'} do
+            Discussion
+            %span.badge= @merge_request.mr_and_commit_notes.user.count
+        %li.commits-tab
+          = link_to commits_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#commits', action: 'commits', toggle: 'tab'} do
+            Commits
+            %span.badge= @commits.size
+        - if @ci_commit
+          %li.builds-tab
+            = link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: '#builds', action: 'builds', toggle: 'tab'} do
+              Builds
+              %span.badge= @statuses.size
+        %li.diffs-tab
+          = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: {target: 'div#diffs', action: 'diffs', toggle: 'tab'} do
+            Changes
+            %span.badge= @merge_request.diffs.size
 
-        .mr-loading-status
-          = spinner
+      .tab-content
+        #notes.notes.tab-pane.voting_notes
+          .gray-content-block.second-block.oneline-block
+            = render 'votes/votes_block', votable: @merge_request
 
-      %aside.col-md-3
-        = render 'shared/issuable/sidebar', issuable: @merge_request
+          .row
+            %section.col-md-9
+              .issuable-discussion
+                = render "projects/merge_requests/discussion"
+            %aside.col-md-3
+              = render 'shared/issuable/sidebar', issuable: @merge_request
+            = render 'shared/show_aside'
 
-      = render 'shared/show_aside'
+        #commits.commits.tab-pane
+          - # This tab is always loaded via AJAX
+        #builds.builds.tab-pane
+          - # This tab is always loaded via AJAX
+        #diffs.diffs.tab-pane
+          - # This tab is always loaded via AJAX
 
+      .mr-loading-status
+        = spinner
 
 :javascript
   var merge_request;
diff --git a/app/views/projects/merge_requests/show/_how_to_merge.html.haml b/app/views/projects/merge_requests/show/_how_to_merge.html.haml
index 98f0357ce4ea4699632e01c2a6e469a68aa1eadd..877cc3d744b9bf6855d52efd241a78691e0a5139 100644
--- a/app/views/projects/merge_requests/show/_how_to_merge.html.haml
+++ b/app/views/projects/merge_requests/show/_how_to_merge.html.haml
@@ -8,8 +8,8 @@
         %p
           %strong Step 1.
           Fetch and check out the branch for this merge request
-        = clipboard_button
-        %pre.dark
+        = clipboard_button(clipboard_target: 'pre#merge-info-1')
+        %pre.dark#merge-info-1
           - if @merge_request.for_fork?
             :preserve
               git fetch #{h @merge_request.source_project.http_url_to_repo} #{h @merge_request.source_branch}
@@ -25,8 +25,8 @@
         %p
           %strong Step 3.
           Merge the branch and fix any conflicts that come up
-        = clipboard_button
-        %pre.dark
+        = clipboard_button(clipboard_target: 'pre#merge-info-3')
+        %pre.dark#merge-info-3
           - if @merge_request.for_fork?
             :preserve
               git checkout #{h @merge_request.target_branch}
@@ -38,8 +38,8 @@
         %p
           %strong Step 4.
           Push the result of the merge to GitLab
-        = clipboard_button
-        %pre.dark
+        = clipboard_button(clipboard_target: 'pre#merge-info-4')
+        %pre.dark#merge-info-4
           :preserve
             git push origin #{h @merge_request.target_branch}
         - unless @merge_request.can_be_merged_by?(current_user)
diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml
index 9bfe202589ec0a7d31fe18918ef2f3481baf244b..0f81e5e891424ff42f77c0011efc7e87cc79288c 100644
--- a/app/views/projects/merge_requests/show/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -1,5 +1,5 @@
-.gray-content-block.middle-block
-  %h2.issue-title
+.detail-page-description.gray-content-block.second-block
+  %h2.title
     = markdown escape_once(@merge_request.title), pipeline: :single_line
 
   %div
diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml
index d65c3b16618827f5891fdaa466fec1f7f57bf096..fc6fb2a0d42f56b243870a06a83d27d722a7d6ee 100644
--- a/app/views/projects/merge_requests/show/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_title.html.haml
@@ -1,7 +1,8 @@
-.issuable-title
-  .issue-box{ class: issue_box_class(@merge_request) }
+.detail-page-header
+  .status-box{ class: status_box_class(@merge_request) }
     = @merge_request.state_human_name
-  %span.issuable-id Merge Request ##{@merge_request.iid}
+  %span.identifier
+    Merge Request ##{@merge_request.iid}
   %span.creator
     &middot;
     opened by #{link_to_member(@project, @merge_request.author, size: 24)}
@@ -16,9 +17,9 @@
   .issue-btn-group.pull-right
     - if can?(current_user, :update_merge_request, @merge_request)
       - if @merge_request.open?
-        = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "btn btn-grouped btn-close", title: "Close merge request"
-        = link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "btn btn-grouped issuable-edit", id: "edit_merge_request" do
+        = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: 'btn btn-nr btn-grouped btn-close', title: 'Close merge request'
+        = link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'btn btn-nr btn-grouped issuable-edit', id: 'edit_merge_request' do
           %i.fa.fa-pencil-square-o
           Edit
       - if @merge_request.closed?
-        = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link", title: "Close merge request"
+        = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'btn btn-nr btn-grouped btn-reopen reopen-mr-link', title: 'Reopen merge request'
diff --git a/app/views/projects/merge_requests/widget/_merged.html.haml b/app/views/projects/merge_requests/widget/_merged.html.haml
index 6f52c963a530a6d6a2bcbe4f49af6a546777da06..d1d602eecdcdc08986ed25822956416b2c470904 100644
--- a/app/views/projects/merge_requests/widget/_merged.html.haml
+++ b/app/views/projects/merge_requests/widget/_merged.html.haml
@@ -8,19 +8,15 @@
         #{time_ago_with_tooltip(@merge_request.merge_event.created_at)}
     %div
       - if !@merge_request.source_branch_exists? || (params[:delete_source] == 'true')
-        = succeed '.' do
-          The changes were merged into
-          = link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
-            = @merge_request.target_branch
+        The changes were merged into
+        #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}.
         The source branch has been removed.
 
       - elsif @merge_request.can_remove_source_branch?(current_user)
         .remove_source_branch_widget
           %p
-            = succeed '.' do
-              The changes were merged into
-              = link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
-                = @merge_request.target_branch
+            The changes were merged into
+            #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}.
             You can remove the source branch now.
           = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-primary btn-sm remove_source_branch" do
             %i.fa.fa-times
diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml
index c6bc4ca5bebfaff1793a92c9ac44e20dda208561..d9a1730a8bc96f25c81d021d255ad33c36334aad 100644
--- a/app/views/projects/merge_requests/widget/open/_accept.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml
@@ -7,13 +7,13 @@
       .accept-action
         - if @ci_commit && @ci_commit.active?
           %span.btn-group
-            = link_to "#", class: "btn btn-create merge_when_build_succeeds" do
+            = button_tag class: "btn btn-create js-merge-button merge_when_build_succeeds" do
               Merge When Build Succeeds
-            %a.btn.btn-success.dropdown-toggle{ 'data-toggle' => 'dropdown' }
+            = button_tag class: "btn btn-success dropdown-toggle", 'data-toggle' => 'dropdown' do
               %span.caret
               %span.sr-only
                 Select Merge Moment
-            %ul.dropdown-menu.dropdown-menu-right{ role: 'menu' }
+            %ul.js-merge-dropdown.dropdown-menu.dropdown-menu-right{ role: 'menu' }
               %li
                 = link_to "#", class: "merge_when_build_succeeds" do
                   = icon('check fw')
@@ -23,7 +23,7 @@
                   = icon('warning fw')
                   Merge Immediately
         - else
-          = f.button class: "btn btn-create btn-grouped accept_merge_request #{status_class}" do
+          = f.button class: "btn btn-create btn-grouped js-merge-button accept_merge_request #{status_class}" do
             Accept Merge Request
       - if @merge_request.can_remove_source_branch?(current_user)
         .accept-control.checkbox
@@ -42,21 +42,19 @@
     = hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off"
 
   :javascript
-    $('.accept_merge_request').on('click', function() {
-      $(this).html("<i class='fa fa-spinner fa-spin'></i> Merge in progress");
-    });
-
     $('.accept-mr-form').on('ajax:send', function() {
       $(".accept-mr-form :input").disable();
     });
 
-    $('a.accept_merge_request').on('click', function(e) {
-      e.preventDefault();
-      $(this).closest("form").submit();
+    $('.accept_merge_request').on('click', function() {
+      $('.js-merge-button').html("<i class='fa fa-spinner fa-spin'></i> Merge in progress");
     });
 
-    $('a.merge_when_build_succeeds').on('click', function(e) {
-      e.preventDefault();
+    $('.merge_when_build_succeeds').on('click', function() {
       $("#merge_when_build_succeeds").val("1");
+    });
+
+    $('.js-merge-dropdown a').on('click', function(e) {
+      e.preventDefault();
       $(this).closest("form").submit();
     });
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 7ecee4403373311e5304895fb717c7afbb887c7b..1670ea8741a3a07065f93f38a89e4dc13b771812 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -1,44 +1,46 @@
-- page_title @milestone.title, "Milestones"
+- page_title       @milestone.title, "Milestones"
+- page_description @milestone.description
+
 = render "header_title"
 
-.issuable-details
-  .page-title
-    .issue-box{ class: issue_box_class(@milestone) }
-      - if @milestone.closed?
-        Closed
-      - elsif @milestone.expired?
-        Expired
-      - else
-        Open
+.detail-page-header
+  .status-box{ class: status_box_class(@milestone) }
+    - if @milestone.closed?
+      Closed
+    - elsif @milestone.expired?
+      Expired
+    - else
+      Open
+  %span.identifier
     Milestone ##{@milestone.iid}
-    - if @milestone.expires_at
-      %span.creator
-        &middot;
-        = @milestone.expires_at
-    .pull-right
-      - if can?(current_user, :admin_milestone, @project)
-        = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped" do
-          %i.fa.fa-pencil-square-o
-          Edit
-
-        - if @milestone.active?
-          = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped"
-        - else
-          = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped"
-
-        = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-remove" do
-          %i.fa.fa-trash-o
-          Delete
-
-  .gray-content-block.middle-block
-    %h2.issue-title
-      = markdown escape_once(@milestone.title), pipeline: :single_line
-    %div
-      - if @milestone.description.present?
-        .description
-          .wiki
-            = preserve do
-              = markdown @milestone.description
+  - if @milestone.expires_at
+    %span.creator
+      &middot;
+      = @milestone.expires_at
+  .pull-right
+    - if can?(current_user, :admin_milestone, @project)
+      - if @milestone.active?
+        = link_to 'Close Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-grouped"
+      - else
+        = link_to 'Reopen Milestone', namespace_project_milestone_path(@project.namespace, @project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-grouped"
+
+      = link_to namespace_project_milestone_path(@project.namespace, @project, @milestone), data: { confirm: 'Are you sure?' }, method: :delete, class: "btn btn-grouped btn-remove" do
+        %i.fa.fa-trash-o
+        Delete
+
+      = link_to edit_namespace_project_milestone_path(@project.namespace, @project, @milestone), class: "btn btn-grouped" do
+        %i.fa.fa-pencil-square-o
+        Edit
+
+.detail-page-description.gray-content-block.second-block
+  %h2.title
+    = markdown escape_once(@milestone.title), pipeline: :single_line
+  %div
+    - if @milestone.description.present?
+      .description
+        .wiki
+          = preserve do
+            = markdown @milestone.description
 
 - if @milestone.issues.any? && @milestone.can_be_closed?
   .alert.alert-success.prepend-top-default
diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml
index 88e711ab5341d848e3e76270338819d32e970fab..acb6dc52a8e204f7fecfc7d2f70eeabe844041dc 100644
--- a/app/views/projects/notes/_form.html.haml
+++ b/app/views/projects/notes/_form.html.haml
@@ -13,6 +13,6 @@
     .error-alert
 
   .note-form-actions.clearfix
-    = f.submit 'Add Comment', class: "btn btn-create comment-btn btn-grouped js-comment-button"
+    = f.submit 'Add Comment', class: "btn btn-nr btn-create comment-btn btn-grouped js-comment-button"
     = yield(:note_actions)
     %a.btn.btn-cancel.js-close-discussion-note-form Cancel
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 9c7a5584da9a1122a09121c940dc26c29da46461..7466a098e24d0ba1e735d307ffc41c17c7a458b2 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -71,7 +71,7 @@
   = render default_project_view
 
 - if current_user
-  - access = user_max_access_in_project(current_user, @project)
+  - access = user_max_access_in_project(current_user.id, @project)
   - if access
     .prepend-top-20.project-footer
       .gray-content-block.footer-block.center
diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml
index 1bc90edd8f0342c35352cd162328c55a14e3f00f..1927883513afbf2a2e0b96e8ea1973a97da658fe 100644
--- a/app/views/projects/tree/_tree_content.html.haml
+++ b/app/views/projects/tree/_tree_content.html.haml
@@ -29,7 +29,7 @@
   - if tree.readme
     = render "projects/tree/readme", readme: tree.readme
 
-- if allowed_tree_edit?
+- if can_edit_tree?
   = render 'projects/blob/upload', title: 'Upload New File', placeholder: 'Upload new file', button_title: 'Upload file', form_path: namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post
   = render 'projects/blob/new_dir'
 
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index cefe33e581f97d79fd9b318161946f291a50cbe6..3343288ad2b1da800a7ce50eca1176ea2c19ce9d 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -11,26 +11,65 @@
         = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
       - else
         = link_to title, '#'
-  - if allowed_tree_edit?
+
+  - if current_user
     %li
-      %span.dropdown
-        %a.dropdown-toggle.btn.btn-sm.add-to-tree{href: '#', "data-toggle" => "dropdown"}
+      - if !on_top_of_branch?
+        %span.btn.btn-sm.add-to-tree.disabled.has_tooltip{title: "You can only add files when you are on a branch", data: { container: 'body' }}
           = icon('plus')
-        %ul.dropdown-menu
-          %li
-            = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'Create file', id: 'new-file-link' do
-              = icon('pencil fw')
-              Create file
-          %li
-            = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do
-              = icon('file fw')
-              Upload file
-          %li.divider
-          %li
-            = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do
-              = icon('folder fw')
-              New directory
-  - elsif !on_top_of_branch?
-    %li
-      %span.btn.btn-sm.add-to-tree.disabled.has_tooltip{title: "You can only add files when you are on a branch.", data: {container: 'body'}}
-        = icon('plus')
+      - else
+        %span.dropdown
+          %a.dropdown-toggle.btn.btn-sm.add-to-tree{href: '#', "data-toggle" => "dropdown"}
+            = icon('plus')
+          %ul.dropdown-menu
+            - if can_edit_tree?
+              %li
+                = link_to namespace_project_new_blob_path(@project.namespace, @project, @id) do
+                  = icon('pencil fw')
+                  New file
+              %li
+                = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do
+                  = icon('file fw')
+                  Upload file
+              %li
+                = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do
+                  = icon('folder fw')
+                  New directory
+            - elsif can?(current_user, :fork_project, @project)
+              %li
+                - continue_params = { to:         namespace_project_new_blob_path(@project.namespace, @project, @id),
+                                      notice:     edit_in_new_fork_notice,
+                                      notice_now: edit_in_new_fork_notice_now }
+                - fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key:  current_user.namespace.id,
+                                                                                        continue:       continue_params)
+                = link_to fork_path, method: :post do
+                  = icon('pencil fw')
+                  New file
+              %li
+                - continue_params = { to:         request.fullpath,
+                                      notice:     edit_in_new_fork_notice + " Try to upload a file again.",
+                                      notice_now: edit_in_new_fork_notice_now }
+                - fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key:  current_user.namespace.id,
+                                                                                        continue:       continue_params)
+                = link_to fork_path, method: :post do
+                  = icon('file fw')
+                  Upload file
+              %li
+                - continue_params = { to:         request.fullpath,
+                                      notice:     edit_in_new_fork_notice + " Try to create a new directory again.",
+                                      notice_now: edit_in_new_fork_notice_now }
+                - fork_path = namespace_project_fork_path(@project.namespace, @project, namespace_key:  current_user.namespace.id,
+                                                                                        continue:       continue_params)
+                = link_to fork_path, method: :post do
+                  = icon('folder fw')
+                  New directory
+
+            %li.divider
+            %li
+              = link_to new_namespace_project_branch_path(@project.namespace, @project) do
+                = icon('code-fork fw')
+                New branch
+            %li
+              = link_to new_namespace_project_tag_path(@project.namespace, @project) do
+                = icon('tags fw')
+                New tag
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index ce8ddff955690ea4895580cdb23945e75fd8bd7d..45d700781f3e3d14547268ef9444810112a8e32e 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -6,7 +6,7 @@
   - if issue.description.present?
     .description.term
       = preserve do
-        = search_md_sanitize(markdown(issue.description))
+        = search_md_sanitize(markdown(issue.description, { project: issue.project }))
   %span.light
     #{issue.project.name_with_namespace}
   - if issue.closed?
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index edb5778f4240740ef66bbbf4560a3b0074b6e3b7..687a59c270f9f35d5b940aa740ac60b18f453839 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -1,10 +1,27 @@
 - project = project || @project
-.git-clone-holder.input-group
-  .input-group-addon.git-protocols
-    .input-group-btn
-      = ssh_clone_button(project)
-    .input-group-btn
-      = http_clone_button(project)
+
+.git-clone-holder
+  .btn-group.clone-options
+    %a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'}
+      %span
+        = default_clone_protocol.upcase
+      = icon('angle-down')
+    %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown
+      %li
+        %a#ssh-selector{href: @project.ssh_url_to_repo}
+          SSH
+      %li
+        %a#http-selector{href: @project.http_url_to_repo}
+          HTTPS
+
   = text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true
   .input-group-btn
     = clipboard_button(clipboard_target: '#project_clone')
+
+:javascript
+  $('ul.clone-options-dropdown a').on('click',function(e){
+    e.preventDefault();
+    var $this = $(this);
+    $('a.clone-dropdown-btn span').text($this.text());
+    $('#project_clone').val($this.attr('href'));
+  });
diff --git a/app/views/shared/_new_commit_form.html.haml b/app/views/shared/_new_commit_form.html.haml
index 111219f2064c69b8952b38f5e9935138570e5a20..0c8ac48bb58f8d3ced26fbbf7d54f7bb58f61d83 100644
--- a/app/views/shared/_new_commit_form.html.haml
+++ b/app/views/shared/_new_commit_form.html.haml
@@ -1,16 +1,22 @@
 = render 'shared/commit_message_container', placeholder: placeholder
 
-- unless @project.empty_repo?
-  .form-group.branch
-    = label_tag 'new_branch', 'Target branch', class: 'control-label'
-    .col-sm-10
-      = text_field_tag 'new_branch', @new_branch || tree_edit_branch, required: true, class: "form-control js-new-branch"
+- if @project.empty_repo?
+  = hidden_field_tag 'target_branch', @ref
+- else
+  - if can?(current_user, :push_code, @project)
+    .form-group.branch
+      = label_tag 'target_branch', 'Target branch', class: 'control-label'
+      .col-sm-10
+        = text_field_tag 'target_branch', @target_branch || tree_edit_branch, required: true, class: "form-control js-target-branch"
 
-      .js-create-merge-request-container
-        .checkbox
-          - nonce = SecureRandom.hex
-          = label_tag "create_merge_request-#{nonce}" do
-            = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}"
-            Start a <strong>new merge request</strong> with these changes
+        .js-create-merge-request-container
+          .checkbox
+            - nonce = SecureRandom.hex
+            = label_tag "create_merge_request-#{nonce}" do
+              = check_box_tag 'create_merge_request', 1, true, class: 'js-create-merge-request', id: "create_merge_request-#{nonce}"
+              Start a <strong>new merge request</strong> with these changes
+  - else
+    = hidden_field_tag 'target_branch', @target_branch || tree_edit_branch
+    = hidden_field_tag 'create_merge_request', 1
 
   = hidden_field_tag 'original_branch', @ref, class: 'js-original-branch'
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
index ac6c248ccf1df9f6e6b67dff7ce1ecb157f60b16..be06738eac900b5b1b07c87c2c0438187c145d1c 100644
--- a/app/views/shared/issuable/_filter.html.haml
+++ b/app/views/shared/issuable/_filter.html.haml
@@ -29,14 +29,14 @@
           = check_box_tag "check_all_issues", nil, false,
             class: "check_all_issues left"
       .issues-other-filters
-        .filter-item.inline
-          = users_select_tag(:assignee_id, selected: params[:assignee_id],
-            placeholder: 'Assignee', class: 'trigger-submit', any_user: "Any Assignee", null_user: true, first_user: true, current_user: true)
-
         .filter-item.inline
           = users_select_tag(:author_id, selected: params[:author_id],
             placeholder: 'Author', class: 'trigger-submit', any_user: "Any Author", first_user: true, current_user: true)
 
+        .filter-item.inline
+          = users_select_tag(:assignee_id, selected: params[:assignee_id],
+          placeholder: 'Assignee', class: 'trigger-submit', any_user: "Any Assignee", null_user: true, first_user: true, current_user: true)
+
         .filter-item.inline.milestone-filter
           = select_tag('milestone_title', projects_milestones_options,
             class: 'select2 trigger-submit', include_blank: true,
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 91ccd1ef6601f24986abf27f18affe227bcb7316..90dc00624818e2631f55a905b85a38be4fb74303 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -19,7 +19,7 @@
         - else
           Start the title with <code>[WIP]</code> or <code>WIP:</code> to prevent a
           <strong>Work In Progress</strong> merge request from being merged before it's ready.
-.form-group.issuable-description
+.form-group.detail-page-description
   = f.label :description, 'Description', class: 'control-label'
   .col-sm-10
 
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 0019f739b89d8d453a82c9791ffcff317112354e..79c5cc7f40aa27a1e7bde511f2aff57499a7f09e 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -1,13 +1,5 @@
 .issuable-sidebar.issuable-affix
   = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f|
-    .block
-      .title
-        Cross-project reference
-      .cross-project-reference
-        %span#cross-project-reference
-          = cross_project_reference(@project, issuable)
-        = clipboard_button(clipboard_target: 'span#cross-project-reference')
-
     .block.assignee
       .title
         %label
@@ -62,6 +54,14 @@
           = f.collection_select :label_ids, issuable.project.labels.all, :id, :name,
             { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" }
 
+    .block
+      .title
+        Cross-project reference
+      .cross-project-reference
+        %span#cross-project-reference
+          = cross_project_reference(@project, issuable)
+        = clipboard_button(clipboard_target: 'span#cross-project-reference')
+
     = render "shared/issuable/participants", participants: issuable.participants(current_user)
 
     - if current_user
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
index 669e6119fb65a54a8d29b52acf6d8b1881b5105d..aa5acee9c14c1e495826bdb6a9c0a58637691347 100644
--- a/app/views/shared/snippets/_header.html.haml
+++ b/app/views/shared/snippets/_header.html.haml
@@ -1,25 +1,25 @@
-.issuable-details
-  .page-title
-    .snippet-box.has_tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }}
-      = visibility_level_icon(@snippet.visibility_level, fw: false)
-      = visibility_level_label(@snippet.visibility_level)
+.detail-page-header
+  .snippet-box.has_tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }}
+    = visibility_level_icon(@snippet.visibility_level, fw: false)
+    = visibility_level_label(@snippet.visibility_level)
+  %span.identifier
     Snippet ##{@snippet.id}
-    %span.creator
-      &middot; created by #{link_to_member(@project, @snippet.author, size: 24)}
-      &middot;
-      = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
-      - if @snippet.updated_at != @snippet.created_at
-        %span
-          &middot;
-          = icon('edit', title: 'edited')
-          = time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago')
+  %span.creator
+    &middot; created by #{link_to_member(@project, @snippet.author, size: 24)}
+    &middot;
+    = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
+    - if @snippet.updated_at != @snippet.created_at
+      %span
+        &middot;
+        = icon('edit', title: 'edited')
+        = time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago')
 
-    .pull-right
-      - if @snippet.project_id?
-        = render "projects/snippets/actions"
-      - else
-        = render "snippets/actions"
+  .pull-right
+    - if @snippet.project_id?
+      = render "projects/snippets/actions"
+    - else
+      = render "snippets/actions"
 
-  .gray-content-block.middle-block
-    %h2.issue-title
-      = markdown escape_once(@snippet.title), pipeline: :single_line
+.detail-page-description.gray-content-block.second-block
+  %h2.title
+    = markdown escape_once(@snippet.title), pipeline: :single_line
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index a0a6e2d9810b0f071f61e95b33de961638dcefd0..0bca8177e14e43f7fd892579a99612adbe19df58 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -1,5 +1,6 @@
-- page_title    @user.name
-- header_title  @user.name, user_path(@user)
+- page_title       @user.name
+- page_description @user.bio
+- header_title     @user.name, user_path(@user)
 
 = content_for :meta_tags do
   = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity")
@@ -73,7 +74,7 @@
   .user-calendar-activities
 
 
-%ul.center-top-menu.no-top.no-bottom.bottom-border
+%ul.center-top-menu.no-top.no-bottom.bottom-border.wide
   %li.active
     = link_to "#activity", 'data-toggle' => 'tab' do
       Activity
diff --git a/app/views/votes/_votes_block.html.haml b/app/views/votes/_votes_block.html.haml
index 6071f1484c621f05b316a8b23555d66f1835e276..ce0a0113403328f7c4d75b540fab4d746c03714f 100644
--- a/app/views/votes/_votes_block.html.haml
+++ b/app/views/votes/_votes_block.html.haml
@@ -1,33 +1,46 @@
 .awards.votes-block
-  - votable.notes.awards.grouped_awards.each do |emoji, notes|
+  - awards_sort(votable.notes.awards.grouped_awards).each do |emoji, notes|
     .award{class: (note_active_class(notes, current_user)), title: emoji_author_list(notes, current_user)}
-      .icon{"data-emoji" => "#{emoji}"}
-        = image_tag url_to_emoji(emoji), height: "20px", width: "20px"
+      = emoji_icon(emoji)
       .counter
         = notes.count
 
   - if current_user
-    .dropdown.awards-controls
+    .awards-controls
       %a.add-award{"data-toggle" => "dropdown", "data-target" => "#", "href" => "#"}
         = icon('smile-o')
-      %ul.dropdown-menu.awards-menu
-        - emoji_list.each do |emoji|
-          %li{"data-emoji" => "#{emoji}"}= image_tag url_to_emoji(emoji), height: "20px", width: "20px"
+      .emoji-menu
+        .emoji-menu-content
+          = text_field_tag :emoji_search, "", class: "emoji-search search-input form-control"
+          - AwardEmoji.emoji_by_category.each do |category, emojis|
+            %h5= AwardEmoji::CATEGORIES[category]
+            %ul
+              - emojis.each do |emoji|
+                %li
+                  = emoji_icon(emoji["name"], emoji["unicode"], emoji["aliases"])
 
 - if current_user
   :coffeescript
     post_emoji_url = "#{award_toggle_namespace_project_notes_path(@project.namespace, @project)}"
     noteable_type = "#{votable.class.name.underscore}"
     noteable_id = "#{votable.id}"
-    aliases = #{AwardEmoji::ALIASES.to_json}
-    window.awards_handler = new AwardsHandler(post_emoji_url, noteable_type, noteable_id, aliases)
+    aliases = #{AwardEmoji.aliases.to_json}
 
-    $(".awards-menu li").click (e)->
-      emoji = $(this).data("emoji")
+    window.awards_handler = new AwardsHandler(
+      post_emoji_url,
+      noteable_type,
+      noteable_id,
+      aliases
+    )
+
+    $(".awards").on "click", ".emoji-menu-content li", (e) ->
+      emoji = $(this).find(".emoji-icon").data("emoji")
       awards_handler.addAward(emoji)
 
-    $(".awards").on "click", ".award", (e)->
+    $(".awards").on "click", ".award", (e) ->
       emoji = $(this).find(".icon").data("emoji")
       awards_handler.addAward(emoji)
 
     $(".award").tooltip()
+
+    $(".emoji-menu-content").niceScroll({cursorwidth: "7px", autohidemode: false})
diff --git a/config/database.yml.env b/config/database.yml.env
new file mode 100644
index 0000000000000000000000000000000000000000..b2ff23cb5abda9327b0e39d8bb5564b14cd092fe
--- /dev/null
+++ b/config/database.yml.env
@@ -0,0 +1,9 @@
+<%= ENV['RAILS_ENV'] %>:
+  adapter: <%= ENV['GITLAB_DATABASE_ADAPTER'] || 'postgresql' %>
+  encoding: <%= ENV['GITLAB_DATABASE_ENCODING'] || 'unicode' %>
+  database: <%= ENV['GITLAB_DATABASE_DATABASE'] || "gitlab_#{ENV['RAILS_ENV']}" %>
+  pool: <%= ENV['GITLAB_DATABASE_POOL'] || '10' %>
+  username: <%= ENV['GITLAB_DATABASE_USERNAME'] || 'root' %>
+  password: <%= ENV['GITLAB_DATABASE_PASSWORD'] || '' %>
+  host: <%= ENV['GITLAB_DATABASE_HOST'] || 'localhost' %>
+  port: <%= ENV['GITLAB_DATABASE_PORT'] || '5432' %>
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index db378118f8550d9e0589a4f70717f5e3d38b3f1d..2d9f730c1831e6de76b8d297089b484449588553 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -4,8 +4,8 @@
 #
 ###########################  NOTE  #####################################
 # This file should not receive new settings. All configuration options #
-# that do not require an application restart are being moved to        #
-# ApplicationSetting model!                                            #
+# * are being moved to ApplicationSetting model!                       #
+# If a setting requires an application restart say so in that screen.  #
 # If you change this file in a Merge Request, please also create       #
 # a MR on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests  #
 ########################################################################
@@ -144,6 +144,15 @@ production: &base
     # plain_url: "http://..."     # default: http://www.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
     # ssl_url:   "https://..."    # default: https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon
 
+  ## Auxiliary jobs
+  # Periodically executed jobs, to self-heal Gitlab, do external synchronizations, etc.
+  # Please read here for more information: https://github.com/ondrejbartas/sidekiq-cron#adding-cron-job
+  cron_jobs:
+    # Flag stuck CI builds as failed
+    stuck_ci_builds_worker:
+      cron: "0 0 * * *"
+
+
   #
   # 2. GitLab CI settings
   # ==========================
@@ -287,6 +296,15 @@ production: &base
     # arguments, followed by optional 'args' which can be either a hash or an array.
     # Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html
     providers:
+      # See omniauth-cas3 for more configuration details
+      # - { name: 'cas3',
+      #     label: 'cas3',
+      #     args: {
+      #             url: 'https://sso.example.com',
+      #             disable_ssl_verification: false,
+      #             login_url: '/cas/login',
+      #             service_validate_url: '/cas/p3/serviceValidate',
+      #             logout_url: '/cas/logout'} }
       # - { name: 'github',
       #     app_id: 'YOUR_APP_ID',
       #     app_secret: 'YOUR_APP_SECRET',
@@ -324,6 +342,10 @@ production: &base
       #       application_name: 'YOUR_APP_NAME',
       #       application_password: 'YOUR_APP_PASSWORD' } }
 
+    # SSO maximum session duration in seconds. Defaults to CAS default of 8 hours.
+    # cas3:
+    #   session_duration: 28800
+
   # Shared file storage settings
   shared:
     # path: /mnt/gitlab # Default: shared
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 63d8ae174365bc7f6613a109a42671745b573191..4fbd84ee8901067b0de09c27cc6d025e1f63d352 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -126,6 +126,11 @@ Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block
 Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil?
 
 Settings.omniauth['providers']  ||= []
+Settings.omniauth['cas3'] ||= Settingslogic.new({})
+Settings.omniauth.cas3['session_duration'] ||= 8.hours
+Settings.omniauth['session_tickets'] ||= Settingslogic.new({})
+Settings.omniauth.session_tickets['cas3'] = 'ticket'
+
 
 Settings['shared'] ||= Settingslogic.new({})
 Settings.shared['path'] = File.expand_path(Settings.shared['path'] || "shared", Rails.root)
@@ -140,16 +145,16 @@ Settings.gitlab['default_projects_limit'] ||= 10
 Settings.gitlab['default_branch_protection'] ||= 2
 Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
 Settings.gitlab['default_theme'] = Gitlab::Themes::APPLICATION_DEFAULT if Settings.gitlab['default_theme'].nil?
-Settings.gitlab['host']       ||= 'localhost'
+Settings.gitlab['host']       ||= ENV['GITLAB_HOST'] || 'localhost'
 Settings.gitlab['ssh_host']   ||= Settings.gitlab.host
 Settings.gitlab['https']        = false if Settings.gitlab['https'].nil?
 Settings.gitlab['port']       ||= Settings.gitlab.https ? 443 : 80
 Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || ''
 Settings.gitlab['protocol']   ||= Settings.gitlab.https ? "https" : "http"
 Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil?
-Settings.gitlab['email_from'] ||= "gitlab@#{Settings.gitlab.host}"
-Settings.gitlab['email_display_name'] ||= "GitLab"
-Settings.gitlab['email_reply_to'] ||= "noreply@#{Settings.gitlab.host}"
+Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings.gitlab.host}"
+Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab'
+Settings.gitlab['email_reply_to'] ||= ENV['GITLAB_EMAIL_REPLY_TO'] || "noreply@#{Settings.gitlab.host}"
 Settings.gitlab['base_url']   ||= Settings.send(:build_base_gitlab_url)
 Settings.gitlab['url']        ||= Settings.send(:build_gitlab_url)
 Settings.gitlab['user']       ||= 'git'
@@ -164,7 +169,7 @@ Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].
 Settings.gitlab['twitter_sharing_enabled'] ||= true if Settings.gitlab['twitter_sharing_enabled'].nil?
 Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
 Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
-Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?))+)' if Settings.gitlab['issue_closing_pattern'].nil?
+Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z]*-\d*))+)' if Settings.gitlab['issue_closing_pattern'].nil?
 Settings.gitlab['default_projects_features'] ||= {}
 Settings.gitlab['webhook_timeout'] ||= 10
 Settings.gitlab['max_attachment_size'] ||= 10
@@ -224,6 +229,15 @@ Settings.gravatar['plain_url']  ||= 'http://www.gravatar.com/avatar/%{hash}?s=%{
 Settings.gravatar['ssl_url']    ||= 'https://secure.gravatar.com/avatar/%{hash}?s=%{size}&d=identicon'
 Settings.gravatar['host']         = Settings.get_host_without_www(Settings.gravatar['plain_url'])
 
+#
+# Cron Jobs
+#
+Settings['cron_jobs'] ||= Settingslogic.new({})
+Settings.cron_jobs['stuck_ci_builds_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['stuck_ci_builds_worker']['cron'] ||= '0 0 * * *'
+Settings.cron_jobs['stuck_ci_builds_worker']['job_class'] = 'StuckCiBuildsWorker'
+
+
 #
 # GitLab Shell
 #
diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb
index bfb8656df552da088bf7848deaa77540945bead2..df28d30d750946bf32d3d4e5ae078bc7e3919ab0 100644
--- a/config/initializers/carrierwave.rb
+++ b/config/initializers/carrierwave.rb
@@ -31,11 +31,11 @@ if File.exists?(aws_file)
   if Rails.env.test?
     Fog.mock!
     connection = ::Fog::Storage.new(
-        aws_access_key_id: AWS_CONFIG['access_key_id'],
-        aws_secret_access_key: AWS_CONFIG['secret_access_key'],
-        provider: 'AWS',
-        region: AWS_CONFIG['region']
-      )
+      aws_access_key_id: AWS_CONFIG['access_key_id'],
+      aws_secret_access_key: AWS_CONFIG['secret_access_key'],
+      provider: 'AWS',
+      region: AWS_CONFIG['region']
+    )
     connection.directories.create(key: AWS_CONFIG['bucket'])
   end
 end
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 5fb43a86e13d385f5831108859636a28bce56384..d82cfb3ec0c787022f6b61fcab2f5104f0fee8f0 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -121,14 +121,14 @@ Devise.setup do |config|
   config.lock_strategy = :failed_attempts
 
   # Defines which key will be used when locking and unlocking an account
-  # config.unlock_keys = [ :email ]
+  config.unlock_keys = [ :email ]
 
   # Defines which strategy will be used to unlock an account.
   # :email = Sends an unlock link to the user email
   # :time  = Re-enables login after a certain amount of time (see :unlock_in below)
   # :both  = Enables both strategies
   # :none  = No unlock strategy. You should handle unlocking by yourself.
-  config.unlock_strategy = :time
+  config.unlock_strategy = :both
 
   # Number of authentication tries before locking an account if lock_strategy
   # is failed attempts.
@@ -241,6 +241,16 @@ Devise.setup do |config|
       # An Array from the configuration will be expanded.
       provider_arguments.concat provider['args']
     when Hash
+      # Add procs for handling SLO
+      if provider['name'] == 'cas3'
+        provider['args'][:on_single_sign_out]  = lambda do |request|
+          ticket = request.params[:session_index]
+          raise "Service Ticket not found." unless Gitlab::OAuth::Session.valid?(:cas3, ticket)
+          Gitlab::OAuth::Session.destroy(:cas3, ticket)
+          true
+        end
+      end
+
       # A Hash from the configuration will be passed as is.
       provider_arguments << provider['args'].symbolize_keys
     end
diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2e4908192a13ba6d03a3f3fec455fd2a9661cec7
--- /dev/null
+++ b/config/initializers/metrics.rb
@@ -0,0 +1,64 @@
+if Gitlab::Metrics.enabled?
+  require 'influxdb'
+  require 'socket'
+  require 'connection_pool'
+  require 'method_source'
+
+  # These are manually require'd so the classes are registered properly with
+  # ActiveSupport.
+  require 'gitlab/metrics/subscribers/action_view'
+  require 'gitlab/metrics/subscribers/active_record'
+
+  Gitlab::Application.configure do |config|
+    config.middleware.use(Gitlab::Metrics::RackMiddleware)
+  end
+
+  Sidekiq.configure_server do |config|
+    config.server_middleware do |chain|
+      chain.add Gitlab::Metrics::SidekiqMiddleware
+    end
+  end
+
+  # This instruments all methods residing in app/models that (appear to) use any
+  # of the ActiveRecord methods. This has to take place _after_ initializing as
+  # for some unknown reason calling eager_load! earlier breaks Devise.
+  Gitlab::Application.config.after_initialize do
+    Rails.application.eager_load!
+
+    models = Rails.root.join('app', 'models').to_s
+
+    regex = Regexp.union(
+      ActiveRecord::Querying.public_instance_methods(false).map(&:to_s)
+    )
+
+    Gitlab::Metrics::Instrumentation.
+      instrument_class_hierarchy(ActiveRecord::Base) do |klass, method|
+        # Instrumenting the ApplicationSetting class can lead to an infinite
+        # loop. Since the data is cached any way we don't really need to
+        # instrument it.
+        if klass == ApplicationSetting
+          false
+        else
+          loc = method.source_location
+
+          loc && loc[0].start_with?(models) && method.source =~ regex
+        end
+      end
+  end
+
+  Gitlab::Metrics::Instrumentation.configure do |config|
+    config.instrument_instance_methods(Gitlab::Shell)
+
+    config.instrument_methods(Gitlab::Git)
+
+    Gitlab::Git.constants.each do |name|
+      const = Gitlab::Git.const_get(name)
+
+      config.instrument_methods(const) if const.is_a?(Module)
+    end
+  end
+
+  GC::Profiler.enable
+
+  Gitlab::Metrics::Sampler.new.start
+end
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 2e3a71912ef6b26600838c8a35c4e142c648f614..dcf6ce74d96bbd1dc546a6d0934e5a611d7b8cd7 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -18,11 +18,12 @@ Sidekiq.configure_server do |config|
     chain.add Gitlab::SidekiqMiddleware::MemoryKiller if ENV['SIDEKIQ_MEMORY_KILLER_MAX_RSS']
   end
 
-  # Sidekiq-cron: load recurring jobs from schedule.yml
-  schedule_file = 'config/schedule.yml'
-  if File.exists?(schedule_file)
-    Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
-  end
+  # Sidekiq-cron: load recurring jobs from gitlab.yml
+  # UGLY Hack to get nested hash from settingslogic
+  cron_jobs = JSON.parse(Gitlab.config.cron_jobs.to_json)
+  # UGLY hack: Settingslogic doesn't allow 'class' key
+  cron_jobs.each { |k,v| cron_jobs[k]['class'] = cron_jobs[k].delete('job_class') }
+  Sidekiq::Cron::Job.load_from_hash! cron_jobs
 
   # Database pool should be at least `sidekiq_concurrency` + 2
   # For more info, see: https://github.com/mperham/sidekiq/blob/master/4.0-Upgrade.md
diff --git a/config/routes.rb b/config/routes.rb
index e2d4fcb65a8446acd6678229803abfb662021df9..3e7d9f78710fcc31b1ee2efbf5e25bc742278f8f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -188,7 +188,7 @@ Rails.application.routes.draw do
   namespace :admin do
     resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
       resources :keys, only: [:show, :destroy]
-      resources :identities, only: [:index, :edit, :update, :destroy]
+      resources :identities, except: [:show]
 
       delete 'stop_impersonation' => 'impersonation#destroy', on: :collection
 
@@ -297,6 +297,7 @@ Rails.application.routes.draw do
       resource :two_factor_auth, only: [:new, :create, :destroy] do
         member do
           post :codes
+          patch :skip
         end
       end
     end
@@ -441,7 +442,7 @@ Rails.application.routes.draw do
 
         scope do
           post(
-              '/create_dir/*id',
+            '/create_dir/*id',
               to: 'tree#create_dir',
               constraints: { id: /.+/ },
               as: 'create_dir'
diff --git a/config/schedule.rb b/config/schedule.rb
deleted file mode 100644
index 8122f7cc69c7e8165da16e9f2f4e2c935190d98b..0000000000000000000000000000000000000000
--- a/config/schedule.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# Use this file to easily define all of your cron jobs.
-#
-# If you make changes to this file, please create also an issue on
-# https://gitlab.com/gitlab-org/omnibus-gitlab/issues . This is necessary
-# because the omnibus packages manage cron jobs using Chef instead of Whenever.
-every 1.hour do
-  rake "ci:schedule_builds"
-end
diff --git a/config/schedule.yml b/config/schedule.yml
deleted file mode 100644
index 993a95fef565b87d049e4d6e15e3e0ed7c33ee2e..0000000000000000000000000000000000000000
--- a/config/schedule.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-# Here is a list of jobs that are scheduled to run periodically.
-# We use a UNIX cron notation to specify execution schedule.
-#
-# Please read here for more information:
-# https://github.com/ondrejbartas/sidekiq-cron#adding-cron-job
-
-stuck_ci_builds_worker:
-  cron: "0 0 * * *"
-  class: "StuckCiBuildsWorker"
-  queue: "default"
diff --git a/db/migrate/20151012173029_set_jira_service_api_url.rb b/db/migrate/20151012173029_set_jira_service_api_url.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2af99e0db0b3f3624b7ef7866609a247357addc3
--- /dev/null
+++ b/db/migrate/20151012173029_set_jira_service_api_url.rb
@@ -0,0 +1,50 @@
+class SetJiraServiceApiUrl < ActiveRecord::Migration
+  # This migration can be performed online without errors, but some Jira API calls may be missed
+  # when doing so because api_url is not yet available.
+
+  def build_api_url_from_project_url(project_url, api_version)
+    # this is the exact logic previously used to build the Jira API URL from project_url
+    server = URI(project_url)
+    default_ports = [80, 443].include?(server.port)
+    server_url = "#{server.scheme}://#{server.host}"
+    server_url.concat(":#{server.port}") unless default_ports
+    "#{server_url}/rest/api/#{api_version}"
+  end
+
+  def get_api_version_from_api_url(api_url)
+    match = /\/rest\/api\/(?<api_version>\w+)$/.match(api_url)
+    match && match['api_version']
+  end
+
+  def change
+    reversible do |dir|
+      select_all("SELECT id, properties FROM services WHERE services.type IN ('JiraService')").each do |jira_service|
+        id = jira_service["id"]
+        properties = JSON.parse(jira_service["properties"])
+        properties_was = properties.clone
+
+        dir.up do
+          # remove api_version and set api_url
+          if properties['api_version'].present? && properties['project_url'].present?
+            begin
+              properties['api_url'] ||= build_api_url_from_project_url(properties['project_url'], properties['api_version'])
+            rescue
+              # looks like project_url was not a valid URL. Do nothing.
+            end
+          end
+          properties.delete('api_version') if properties.include?('api_version')
+        end
+
+        dir.down do
+          # remove api_url and set api_version (default to '2')
+          properties['api_version'] ||= get_api_version_from_api_url(properties['api_url']) || '2'
+          properties.delete('api_url') if properties.include?('api_url')
+        end
+
+        if properties != properties_was
+          execute("UPDATE services SET properties = '#{quote_string(properties.to_json)}' WHERE id = #{id}")
+        end
+      end
+    end
+  end
+end
diff --git a/db/migrate/20151203162134_add_build_events_to_services.rb b/db/migrate/20151203162134_add_build_events_to_services.rb
index a84be7db3f15ba2d87f54bdd52560df34021c2af..c5542cb864da8ca5198f8d76dd8ff6fe61d991b5 100644
--- a/db/migrate/20151203162134_add_build_events_to_services.rb
+++ b/db/migrate/20151203162134_add_build_events_to_services.rb
@@ -1,5 +1,5 @@
 class AddBuildEventsToServices < ActiveRecord::Migration
-  def up
+  def change
     add_column :services, :build_events, :boolean, default: false, null: false
     add_column :web_hooks, :build_events, :boolean, default: false, null: false
   end
diff --git a/db/migrate/20151209144329_migrate_ci_web_hooks.rb b/db/migrate/20151209144329_migrate_ci_web_hooks.rb
index 825ba1973ff85a67a7d88fee7a416a94221d2f3e..d7e196e6763d442f4e650584f0378cb770d75c57 100644
--- a/db/migrate/20151209144329_migrate_ci_web_hooks.rb
+++ b/db/migrate/20151209144329_migrate_ci_web_hooks.rb
@@ -10,4 +10,7 @@ class MigrateCiWebHooks < ActiveRecord::Migration
       'JOIN projects ON ci_projects.gitlab_id = projects.id'
     )
   end
+
+  def down
+  end
 end
diff --git a/db/migrate/20151210030143_add_unlock_token_to_user.rb b/db/migrate/20151210030143_add_unlock_token_to_user.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0ea66ba65dfa6df8896b219dcedbb9aac460b9cd
--- /dev/null
+++ b/db/migrate/20151210030143_add_unlock_token_to_user.rb
@@ -0,0 +1,5 @@
+class AddUnlockTokenToUser < ActiveRecord::Migration
+  def change
+    add_column :users, :unlock_token, :string
+  end
+end
diff --git a/db/migrate/20151210125928_add_ci_to_project.rb b/db/migrate/20151210125928_add_ci_to_project.rb
index 8a65abab636bd9895cb93e913414275517326c08..8c167f64a2b59444c94a5b8a1f914a252e44aec1 100644
--- a/db/migrate/20151210125928_add_ci_to_project.rb
+++ b/db/migrate/20151210125928_add_ci_to_project.rb
@@ -1,5 +1,5 @@
 class AddCiToProject < ActiveRecord::Migration
-  def up
+  def change
     add_column :projects, :ci_id, :integer
     add_column :projects, :builds_enabled, :boolean, default: true, null: false
     add_column :projects, :shared_runners_enabled, :boolean, default: true, null: false
diff --git a/db/migrate/20151210125929_add_project_id_to_ci.rb b/db/migrate/20151210125929_add_project_id_to_ci.rb
index 5d1cf54357673f65f3c0d084bc39d8127453e2db..84273591fa2ede4f606e2ab9cae2418330e00cf1 100644
--- a/db/migrate/20151210125929_add_project_id_to_ci.rb
+++ b/db/migrate/20151210125929_add_project_id_to_ci.rb
@@ -1,5 +1,5 @@
 class AddProjectIdToCi < ActiveRecord::Migration
-  def up
+  def change
     add_column :ci_builds, :gl_project_id, :integer
     add_column :ci_runner_projects, :gl_project_id, :integer
     add_column :ci_triggers, :gl_project_id, :integer
diff --git a/db/migrate/20151210125930_migrate_ci_to_project.rb b/db/migrate/20151210125930_migrate_ci_to_project.rb
index 7dfe05174ee06be52419f4b63e0359c114183577..c32c7feb1931443f5e28b1ee0d56eae5cbe71674 100644
--- a/db/migrate/20151210125930_migrate_ci_to_project.rb
+++ b/db/migrate/20151210125930_migrate_ci_to_project.rb
@@ -14,6 +14,10 @@ class MigrateCiToProject < ActiveRecord::Migration
     migrate_ci_service
   end
 
+  def down
+    # We can't reverse the data
+  end
+
   def migrate_project_id_for_table(table)
     subquery = "SELECT gitlab_id FROM ci_projects WHERE ci_projects.id = #{table}.project_id"
     execute("UPDATE #{table} SET gl_project_id=(#{subquery}) WHERE gl_project_id IS NULL")
@@ -26,7 +30,8 @@ class MigrateCiToProject < ActiveRecord::Migration
 
   def migrate_project_column(column, new_column = nil)
     new_column ||= column
-    subquery = "SELECT ci_projects.#{column} FROM ci_projects WHERE projects.id = ci_projects.gitlab_id"
+    subquery = "SELECT ci_projects.#{column} FROM ci_projects WHERE projects.id = ci_projects.gitlab_id " \
+      'ORDER BY ci_projects.updated_at DESC LIMIT 1'
     execute("UPDATE projects SET #{new_column}=(#{subquery}) WHERE (#{subquery}) IS NOT NULL")
   end
 
diff --git a/db/migrate/20151210125931_add_index_to_ci_tables.rb b/db/migrate/20151210125931_add_index_to_ci_tables.rb
index 9fedb5d612ce3c801487b761de65207336a0af4f..5e129c9303d9b0bece0d8fc36100682f8a8a969f 100644
--- a/db/migrate/20151210125931_add_index_to_ci_tables.rb
+++ b/db/migrate/20151210125931_add_index_to_ci_tables.rb
@@ -1,5 +1,5 @@
 class AddIndexToCiTables < ActiveRecord::Migration
-  def up
+  def change
     add_index :ci_builds, :gl_project_id
     add_index :ci_runner_projects, :gl_project_id
     add_index :ci_triggers, :gl_project_id
diff --git a/db/migrate/20151210125932_drop_null_for_ci_tables.rb b/db/migrate/20151210125932_drop_null_for_ci_tables.rb
index 0b007430b0c17168447bc51f80059779f501764c..c520c2ed56f67e2f08d91fa29174d12bcb413ece 100644
--- a/db/migrate/20151210125932_drop_null_for_ci_tables.rb
+++ b/db/migrate/20151210125932_drop_null_for_ci_tables.rb
@@ -1,5 +1,5 @@
 class DropNullForCiTables < ActiveRecord::Migration
-  def up
+  def change
     remove_index :ci_variables, :project_id
     remove_index :ci_runner_projects, :project_id
     change_column_null :ci_triggers, :project_id, true
diff --git a/db/migrate/20151218154042_add_tfa_to_application_settings.rb b/db/migrate/20151218154042_add_tfa_to_application_settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dd95db775c5e5e548b8d567223fd8c9dc2607de0
--- /dev/null
+++ b/db/migrate/20151218154042_add_tfa_to_application_settings.rb
@@ -0,0 +1,8 @@
+class AddTfaToApplicationSettings < ActiveRecord::Migration
+  def change
+    change_table :application_settings do |t|
+      t.boolean :require_two_factor_authentication, default: false
+      t.integer :two_factor_grace_period, default: 48
+    end
+  end
+end
diff --git a/db/migrate/20151221234414_add_tfa_additional_fields.rb b/db/migrate/20151221234414_add_tfa_additional_fields.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c16df47932f6e902d58e5758bc5ff86047cfdfc8
--- /dev/null
+++ b/db/migrate/20151221234414_add_tfa_additional_fields.rb
@@ -0,0 +1,7 @@
+class AddTfaAdditionalFields < ActiveRecord::Migration
+  def change
+    change_table :users do |t|
+      t.datetime :otp_grace_period_started_at, null: true
+    end
+  end
+end
diff --git a/db/migrate/20151224123230_rename_emojis.rb b/db/migrate/20151224123230_rename_emojis.rb
new file mode 100644
index 0000000000000000000000000000000000000000..62d921dfdcce3e26b7efd0afd2a3dd192bddeead
--- /dev/null
+++ b/db/migrate/20151224123230_rename_emojis.rb
@@ -0,0 +1,15 @@
+# Migration type: online without errors (works on previous version and new one)
+class RenameEmojis < ActiveRecord::Migration
+  def up
+    # Renames aliases to main names
+    execute("UPDATE notes SET note ='thumbsup' WHERE is_award = true AND note = '+1'")
+    execute("UPDATE notes SET note ='thumbsdown' WHERE is_award = true AND note = '-1'")
+    execute("UPDATE notes SET note ='poop' WHERE is_award = true AND note = 'shit'")
+  end
+
+  def down
+    execute("UPDATE notes SET note ='+1' WHERE is_award = true AND note = 'thumbsup'")
+    execute("UPDATE notes SET note ='-1' WHERE is_award = true AND note = 'thumbsdown'")
+    execute("UPDATE notes SET note ='shit' WHERE is_award = true AND note = 'poop'")
+  end
+end
diff --git a/db/migrate/20151228150906_influxdb_settings.rb b/db/migrate/20151228150906_influxdb_settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3012bd52cfdd96c09ed4bd9cdd13996e41e65d1b
--- /dev/null
+++ b/db/migrate/20151228150906_influxdb_settings.rb
@@ -0,0 +1,18 @@
+class InfluxdbSettings < ActiveRecord::Migration
+  def change
+    add_column :application_settings, :metrics_enabled, :boolean, default: false
+
+    add_column :application_settings, :metrics_host, :string,
+      default: 'localhost'
+
+    add_column :application_settings, :metrics_database, :string,
+      default: 'gitlab'
+
+    add_column :application_settings, :metrics_username, :string
+    add_column :application_settings, :metrics_password, :string
+    add_column :application_settings, :metrics_pool_size, :integer, default: 16
+    add_column :application_settings, :metrics_timeout, :integer, default: 10
+    add_column :application_settings, :metrics_method_call_threshold,
+      :integer, default: 10
+  end
+end
diff --git a/db/migrate/20151228175719_add_recaptcha_to_application_settings.rb b/db/migrate/20151228175719_add_recaptcha_to_application_settings.rb
new file mode 100644
index 0000000000000000000000000000000000000000..259fd0248d2914c52f95a8353668458b8d0d9ce7
--- /dev/null
+++ b/db/migrate/20151228175719_add_recaptcha_to_application_settings.rb
@@ -0,0 +1,9 @@
+class AddRecaptchaToApplicationSettings < ActiveRecord::Migration
+  def change
+    change_table :application_settings do |t|
+      t.boolean :recaptcha_enabled, default: false
+      t.string :recaptcha_site_key
+      t.string :recaptcha_private_key
+    end
+  end
+end
diff --git a/db/migrate/20151229102248_influxdb_udp_port_setting.rb b/db/migrate/20151229102248_influxdb_udp_port_setting.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ae0499f936d6fcfd719c3c231e2ecabf975c4f26
--- /dev/null
+++ b/db/migrate/20151229102248_influxdb_udp_port_setting.rb
@@ -0,0 +1,5 @@
+class InfluxdbUdpPortSetting < ActiveRecord::Migration
+  def change
+    add_column :application_settings, :metrics_port, :integer, default: 8089
+  end
+end
diff --git a/db/migrate/20151229112614_influxdb_remote_database_setting.rb b/db/migrate/20151229112614_influxdb_remote_database_setting.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f0e1ee1e7a79a0d3720160796fc1ffa389039fc8
--- /dev/null
+++ b/db/migrate/20151229112614_influxdb_remote_database_setting.rb
@@ -0,0 +1,5 @@
+class InfluxdbRemoteDatabaseSetting < ActiveRecord::Migration
+  def change
+    remove_column :application_settings, :metrics_database
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0167e30ff8b90658ddd9a0796d3c5720a3be376a..df7f72d5ad4a7591dde54f7a9cdc18fc9a8b0871 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20151210125932) do
+ActiveRecord::Schema.define(version: 20151229112614) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -33,23 +33,36 @@ ActiveRecord::Schema.define(version: 20151210125932) do
     t.datetime "created_at"
     t.datetime "updated_at"
     t.string   "home_page_url"
-    t.integer  "default_branch_protection",    default: 2
-    t.boolean  "twitter_sharing_enabled",      default: true
+    t.integer  "default_branch_protection",         default: 2
+    t.boolean  "twitter_sharing_enabled",           default: true
     t.text     "restricted_visibility_levels"
-    t.boolean  "version_check_enabled",        default: true
-    t.integer  "max_attachment_size",          default: 10,    null: false
+    t.boolean  "version_check_enabled",             default: true
+    t.integer  "max_attachment_size",               default: 10,          null: false
     t.integer  "default_project_visibility"
     t.integer  "default_snippet_visibility"
     t.text     "restricted_signup_domains"
-    t.boolean  "user_oauth_applications",      default: true
+    t.boolean  "user_oauth_applications",           default: true
     t.string   "after_sign_out_path"
-    t.integer  "session_expire_delay",         default: 10080, null: false
+    t.integer  "session_expire_delay",              default: 10080,       null: false
     t.text     "import_sources"
     t.text     "help_page_text"
     t.string   "admin_notification_email"
-    t.boolean  "shared_runners_enabled",       default: true,  null: false
-    t.integer  "max_artifacts_size",           default: 100,   null: false
+    t.boolean  "shared_runners_enabled",            default: true,        null: false
+    t.integer  "max_artifacts_size",                default: 100,         null: false
     t.string   "runners_registration_token"
+    t.boolean  "require_two_factor_authentication", default: false
+    t.integer  "two_factor_grace_period",           default: 48
+    t.boolean  "metrics_enabled",                   default: false
+    t.string   "metrics_host",                      default: "localhost"
+    t.string   "metrics_username"
+    t.string   "metrics_password"
+    t.integer  "metrics_pool_size",                 default: 16
+    t.integer  "metrics_timeout",                   default: 10
+    t.integer  "metrics_method_call_threshold",     default: 10
+    t.boolean  "recaptcha_enabled",                 default: false
+    t.string   "recaptcha_site_key"
+    t.string   "recaptcha_private_key"
+    t.integer  "metrics_port",                      default: 8089
   end
 
   create_table "audit_events", force: :cascade do |t|
@@ -783,12 +796,12 @@ ActiveRecord::Schema.define(version: 20151210125932) do
   add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
 
   create_table "users", force: :cascade do |t|
-    t.string   "email",                      default: "",    null: false
-    t.string   "encrypted_password",         default: "",    null: false
+    t.string   "email",                       default: "",    null: false
+    t.string   "encrypted_password",          default: "",    null: false
     t.string   "reset_password_token"
     t.datetime "reset_password_sent_at"
     t.datetime "remember_created_at"
-    t.integer  "sign_in_count",              default: 0
+    t.integer  "sign_in_count",               default: 0
     t.datetime "current_sign_in_at"
     t.datetime "last_sign_in_at"
     t.string   "current_sign_in_ip"
@@ -796,22 +809,22 @@ ActiveRecord::Schema.define(version: 20151210125932) do
     t.datetime "created_at"
     t.datetime "updated_at"
     t.string   "name"
-    t.boolean  "admin",                      default: false, null: false
-    t.integer  "projects_limit",             default: 10
-    t.string   "skype",                      default: "",    null: false
-    t.string   "linkedin",                   default: "",    null: false
-    t.string   "twitter",                    default: "",    null: false
+    t.boolean  "admin",                       default: false, null: false
+    t.integer  "projects_limit",              default: 10
+    t.string   "skype",                       default: "",    null: false
+    t.string   "linkedin",                    default: "",    null: false
+    t.string   "twitter",                     default: "",    null: false
     t.string   "authentication_token"
-    t.integer  "theme_id",                   default: 1,     null: false
+    t.integer  "theme_id",                    default: 1,     null: false
     t.string   "bio"
-    t.integer  "failed_attempts",            default: 0
+    t.integer  "failed_attempts",             default: 0
     t.datetime "locked_at"
     t.string   "username"
-    t.boolean  "can_create_group",           default: true,  null: false
-    t.boolean  "can_create_team",            default: true,  null: false
+    t.boolean  "can_create_group",            default: true,  null: false
+    t.boolean  "can_create_team",             default: true,  null: false
     t.string   "state"
-    t.integer  "color_scheme_id",            default: 1,     null: false
-    t.integer  "notification_level",         default: 1,     null: false
+    t.integer  "color_scheme_id",             default: 1,     null: false
+    t.integer  "notification_level",          default: 1,     null: false
     t.datetime "password_expires_at"
     t.integer  "created_by_id"
     t.datetime "last_credential_check_at"
@@ -820,23 +833,25 @@ ActiveRecord::Schema.define(version: 20151210125932) do
     t.datetime "confirmed_at"
     t.datetime "confirmation_sent_at"
     t.string   "unconfirmed_email"
-    t.boolean  "hide_no_ssh_key",            default: false
-    t.string   "website_url",                default: "",    null: false
+    t.boolean  "hide_no_ssh_key",             default: false
+    t.string   "website_url",                 default: "",    null: false
     t.string   "notification_email"
-    t.boolean  "hide_no_password",           default: false
-    t.boolean  "password_automatically_set", default: false
+    t.boolean  "hide_no_password",            default: false
+    t.boolean  "password_automatically_set",  default: false
     t.string   "location"
     t.string   "encrypted_otp_secret"
     t.string   "encrypted_otp_secret_iv"
     t.string   "encrypted_otp_secret_salt"
-    t.boolean  "otp_required_for_login",     default: false, null: false
+    t.boolean  "otp_required_for_login",      default: false, null: false
     t.text     "otp_backup_codes"
-    t.string   "public_email",               default: "",    null: false
-    t.integer  "dashboard",                  default: 0
-    t.integer  "project_view",               default: 0
+    t.string   "public_email",                default: "",    null: false
+    t.integer  "dashboard",                   default: 0
+    t.integer  "project_view",                default: 0
     t.integer  "consumed_timestep"
-    t.integer  "layout",                     default: 0
-    t.boolean  "hide_project_limit",         default: false
+    t.integer  "layout",                      default: 0
+    t.boolean  "hide_project_limit",          default: false
+    t.string   "unlock_token"
+    t.datetime "otp_grace_period_started_at"
   end
 
   add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
diff --git a/doc/README.md b/doc/README.md
index a309809421078e82e1aaed7ce5cfd8eb04d5e71b..8a297f8267f11385dc4bcaaa4c25a39554b6fa4d 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -7,6 +7,7 @@
 - [GitLab Basics](gitlab-basics/README.md) Find step by step how to start working on your commandline and on GitLab.
 - [Importing to GitLab](workflow/importing/README.md).
 - [Markdown](markdown/markdown.md) GitLab's advanced formatting system.
+- [Migrating from SVN](migration/README.md) Convert a SVN repository to Git and GitLab
 - [Permissions](permissions/permissions.md) Learn what each role in a project (guest/reporter/developer/master/owner) can do.
 - [Profile Settings](profile/README.md)
 - [Project Services](project_services/project_services.md) Integrate a project with external services, such as CI and chat.
@@ -27,17 +28,18 @@
 - [Using SSH keys](ci/ssh_keys/README.md)
 - [User permissions](ci/permissions/README.md)
 - [API](ci/api/README.md)
+- [Triggering builds through the API](ci/triggers/README.md)
 
 ### CI Languages
 
-+ [Testing PHP](ci/languages/php.md)
+- [Testing PHP](ci/languages/php.md)
 
 ### CI Services
 
-+ [Using MySQL](ci/services/mysql.md)
-+ [Using PostgreSQL](ci/services/postgres.md)
-+ [Using Redis](ci/services/redis.md)
-+ [Using Other Services](ci/docker/using_docker_images.md#how-to-use-other-images-as-services)
+- [Using MySQL](ci/services/mysql.md)
+- [Using PostgreSQL](ci/services/postgres.md)
+- [Using Redis](ci/services/redis.md)
+- [Using Other Services](ci/docker/using_docker_images.md#how-to-use-other-images-as-services)
 
 ### CI Examples
 
@@ -54,6 +56,7 @@
 - [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages.
 - [Libravatar](customization/libravatar.md) Use Libravatar for user avatars.
 - [Log system](logs/logs.md) Log system.
+- [Environmental Variables](administration/environment_variables.md) to configure GitLab.
 - [Operations](operations/README.md) Keeping GitLab up and running
 - [Raketasks](raketasks/README.md) Backups, maintenance, automatic web hook setup and the importing of projects.
 - [Security](security/README.md) Learn what you can do to further secure your GitLab instance.
diff --git a/doc/administration/enviroment_variables.md b/doc/administration/enviroment_variables.md
new file mode 100644
index 0000000000000000000000000000000000000000..7d8f9d29eef2fdca00f1fc03d37afaf46578a49c
--- /dev/null
+++ b/doc/administration/enviroment_variables.md
@@ -0,0 +1,48 @@
+# Environment Variables
+
+## Introduction
+
+Commonly people configure GitLab via the gitlab.rb configuration file in the Omnibus package.
+
+But if you prefer to use environment variables we allow that too.
+
+## Supported environment variables
+
+Variable | Type | Explanation
+-------- | ---- | -----------
+GITLAB_ROOT_PASSWORD | string | sets the password for the `root` user on installation
+GITLAB_HOST | url | hostname of the GitLab server includes http or https
+RAILS_ENV | production / development / staging / test | Rails environment
+DATABASE_URL | url | For example: postgresql://localhost/blog_development?pool=5
+GITLAB_EMAIL_FROM | email | Email address used in the "From" field in mails sent by GitLab
+GITLAB_EMAIL_DISPLAY_NAME | string | Name used in the "From" field in mails sent by GitLab
+GITLAB_EMAIL_REPLY_TO | email | Email address used in the "Reply-To" field in mails sent by GitLab
+
+## Complete database variables
+
+As explained in the [Heroku documentation](https://devcenter.heroku.com/articles/rails-database-connection-behavior) the DATABASE_URL doesn't let you set:
+
+- adapter
+- database
+- username
+- password
+- host
+- port
+
+To do so please `cp config/database.yml.env config/database.yml` and use the following variables:
+
+Variable | Default
+--- | ---
+GITLAB_DATABASE_ADAPTER | postgresql
+GITLAB_DATABASE_ENCODING | unicode
+GITLAB_DATABASE_DATABASE | gitlab_#{ENV['RAILS_ENV']
+GITLAB_DATABASE_POOL | 10
+GITLAB_DATABASE_USERNAME | root
+GITLAB_DATABASE_PASSWORD |
+GITLAB_DATABASE_HOST | localhost
+GITLAB_DATABASE_PORT | 5432
+
+## Other variables
+
+We welcome merge requests to make more settings configurable via variables.
+Please stick to the naming scheme "GITLAB_#{name 1_settings.rb in upper case}".
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 366a1f8abecdcf7d692dbf442b20453c29a22d67..8bc0a67067a1a22685a7cbf8bac444b73d0c9201 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -4,8 +4,7 @@
 
 Get all merge requests for this project. 
 The `state` parameter can be used to get only merge requests with a given state (`opened`, `closed`, or `merged`) or all of them (`all`).
-The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests. With GitLab 8.2 the return fields `upvotes` and
-`downvotes` are deprecated and always return `0`.
+The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests.
 
 ```
 GET /projects/:id/merge_requests
@@ -58,7 +57,7 @@ Parameters:
 
 ## Get single MR
 
-Shows information about a single merge request. With GitLab 8.2 the return fields `upvotes` and `downvotes` are deprecated and always return `0`.
+Shows information about a single merge request.
 
 ```
 GET /projects/:id/merge_request/:merge_request_id
@@ -141,8 +140,6 @@ Parameters:
 ## Get single MR changes
 
 Shows information about the merge request including its files and changes.
-With GitLab 8.2 the return fields `upvotes` and `downvotes` are deprecated and
-always return `0`.
 
 ```
 GET /projects/:id/merge_request/:merge_request_id/changes
@@ -213,9 +210,7 @@ Parameters:
 
 ## Create MR
 
-Creates a new merge request. With GitLab 8.2 the return fields `upvotes` and `
-downvotes` are deprecated and always return `0`.
-
+Creates a new merge request.
 ```
 POST /projects/:id/merge_requests
 ```
@@ -266,8 +261,7 @@ If an error occurs, an error number and a message explaining the reason is retur
 
 ## Update MR
 
-Updates an existing merge request. You can change the target branch, title, or even close the MR. With GitLab 8.2 the return fields `upvotes` and `downvotes`
-are deprecated and always return `0`.
+Updates an existing merge request. You can change the target branch, title, or even close the MR.
 
 ```
 PUT /projects/:id/merge_request/:merge_request_id
@@ -318,8 +312,7 @@ If an error occurs, an error number and a message explaining the reason is retur
 
 ## Accept MR
 
-Merge changes submitted with MR using this API. With GitLab 8.2 the return
-fields `upvotes` and `downvotes` are deprecated and always return `0`.
+Merge changes submitted with MR using this API.
 
 If merge success you get `200 OK`.
 
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 4d7ef288df8ae45e2d0ab82bf4528b1342c3ae04..d4d63e825abe801e09dd17e282a22f6110a41790 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -6,8 +6,7 @@ Notes are comments on snippets, issues or merge requests.
 
 ### List project issue notes
 
-Gets a list of all notes for a single issue. With GitLab 8.2 the return fields
-`upvote` and `downvote` are deprecated and always return `false`.
+Gets a list of all notes for a single issue.
 
 ```
 GET /projects/:id/issues/:issue_id/notes
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 1a52440062758f3eff1115b29cdc9d3eb8f8468d..0ca81ffd49ee1b39636a9d9045d2e6d8022523b6 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -58,6 +58,7 @@ Parameters:
     "path": "diaspora-client",
     "path_with_namespace": "diaspora/diaspora-client",
     "issues_enabled": true,
+    "open_issues_count": 1,
     "merge_requests_enabled": true,
     "builds_enabled": true,
     "wiki_enabled": true,
@@ -100,6 +101,7 @@ Parameters:
     "path": "puppet",
     "path_with_namespace": "brightbox/puppet",
     "issues_enabled": true,
+    "open_issues_count": 1,
     "merge_requests_enabled": true,
     "builds_enabled": true,
     "wiki_enabled": true,
@@ -116,6 +118,16 @@ Parameters:
       "path": "brightbox",
       "updated_at": "2013-09-30T13:46:02Z"
     },
+    "permissions": {
+      "project_access": {
+        "access_level": 10,
+        "notification_level": 3
+      },
+      "group_access": {
+        "access_level": 50,
+        "notification_level": 3
+      }
+    },
     "archived": false,
     "avatar_url": null
   }
@@ -137,6 +149,21 @@ Parameters:
 - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
 - `search` (optional) - Return list of authorized projects according to a search criteria
 
+### List starred projects
+
+Get a list of projects which are starred by the authenticated user.
+
+```
+GET /projects/starred
+```
+
+Parameters:
+
+- `archived` (optional) - if passed, limit by archived status
+- `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at`
+- `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc`
+- `search` (optional) - Return list of authorized projects according to a search criteria
+
 ### List ALL projects
 
 Get a list of all GitLab projects (admin only).
@@ -189,6 +216,7 @@ Parameters:
   "path": "diaspora-project-site",
   "path_with_namespace": "diaspora/diaspora-project-site",
   "issues_enabled": true,
+  "open_issues_count": 1,
   "merge_requests_enabled": true,
   "builds_enabled": true,
   "wiki_enabled": true,
diff --git a/doc/api/users.md b/doc/api/users.md
index 7ba2db248ff0568cb2f24f524ac479beb000385d..66d2fd52526fda22713743ae6a16e0b7fdc84b49 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -90,7 +90,17 @@ GET /users
 
 You can search for users by email or username with: `/users?search=John`
 
-Also see `def search query` in `app/models/user.rb`.
+In addition, you can lookup users by username:
+
+```
+GET /users?username=:username
+```
+
+For example:
+
+```
+GET /users?username=jack_smith
+```
 
 ## Single user
 
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 5d9d7a81db349d197491dfafc9675841cddd67cb..a1f5513d88e5079e5c919ce13da55ae3ae29b0d8 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -2,28 +2,30 @@
 
 ### User documentation
 
-+ [Quick Start](quick_start/README.md)
-+ [Configuring project (.gitlab-ci.yml)](yaml/README.md)
-+ [Configuring runner](runners/README.md)
-+ [Configuring deployment](deployment/README.md)
-+ [Using Docker Images](docker/using_docker_images.md)
-+ [Using Docker Build](docker/using_docker_build.md)
-+ [Using Variables](variables/README.md)
-+ [Using SSH keys](ssh_keys/README.md)
+* [Quick Start](quick_start/README.md)
+* [Configuring project (.gitlab-ci.yml)](yaml/README.md)
+* [Configuring runner](runners/README.md)
+* [Configuring deployment](deployment/README.md)
+* [Using Docker Images](docker/using_docker_images.md)
+* [Using Docker Build](docker/using_docker_build.md)
+* [Using Variables](variables/README.md)
+* [Using SSH keys](ssh_keys/README.md)
+* [Triggering builds through the API](triggers/README.md)
 
 ### Languages
 
-+ [Testing PHP](languages/php.md)
+* [Testing PHP](languages/php.md)
 
 ### Services
 
-+ [Using MySQL](services/mysql.md)
-+ [Using PostgreSQL](services/postgres.md)
-+ [Using Redis](services/redis.md)
-+ [Using Other Services](docker/using_docker_images.md#how-to-use-other-images-as-services)
+* [Using MySQL](services/mysql.md)
+* [Using PostgreSQL](services/postgres.md)
+* [Using Redis](services/redis.md)
+* [Using Other Services](docker/using_docker_images.md#how-to-use-other-images-as-services)
 
 ### Examples
 
++ [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)
 + [Test and deploy Ruby applications to Heroku](examples/test-and-deploy-ruby-application-to-heroku.md)
 + [Test and deploy Python applications to Heroku](examples/test-and-deploy-python-application-to-heroku.md)
 + [Test Clojure applications](examples/test-clojure-application.md)
@@ -31,5 +33,5 @@
 
 ### Administrator documentation
 
-+ [User permissions](permissions/README.md)
-+ [API](api/README.md)
+* [User permissions](permissions/README.md)
+* [API](api/README.md)
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 8d4bd44053e06eb14c0f1160d865443320351a48..31458d61674d1c45e82907443d65638abfe23f42 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -1,11 +1,11 @@
 # Using Docker Images
 
-GitLab CI in conjuction with [GitLab Runner](../runners/README.md) can use
+GitLab CI in conjunction with [GitLab Runner](../runners/README.md) can use
 [Docker Engine](https://www.docker.com/) to test and build any application.
 
 Docker is an open-source project that allows you to use predefined images to
 run applications in independent "containers" that are run within a single Linux
-instance. [Docker Hub][hub] has a rich database of prebuilt images that can be
+instance. [Docker Hub][hub] has a rich database of pre-built images that can be
 used to test and build your applications.
 
 Docker, when used with GitLab CI, runs each build in a separate and isolated
@@ -136,6 +136,24 @@ Look for the `[runners.docker]` section:
 The image and services defined this way will be added to all builds run by
 that runner.
 
+## Define an image from a private Docker registry
+
+Starting with GitLab Runner 0.6.0, you are able to define images located to
+private registries that could also require authentication.
+
+All you have to do is be explicit on the image definition in `.gitlab-ci.yml`.
+
+```yaml
+image: my.registry.tld:5000/namepace/image:tag
+```
+
+In the example above, GitLab Runner will look at `my.registry.tld:5000` for the
+image `namespace/image:tag`.
+
+If the repository is private you need to authenticate your GitLab Runner in the
+registry. Learn how to do that on
+[GitLab Runner's documentation][runner-priv-reg].
+
 ## Accessing the services
 
 Let's say that you need a Wordpress instance to test some API integration with
@@ -258,3 +276,4 @@ creation.
 [tutum/wordpress]: https://registry.hub.docker.com/u/tutum/wordpress/
 [postgres-hub]: https://registry.hub.docker.com/u/library/postgres/
 [mysql-hub]: https://registry.hub.docker.com/u/library/mysql/
+[runner-priv-reg]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9f7c1bfe6a036a22f19e5b00ffbe82b45ca5449b
--- /dev/null
+++ b/doc/ci/triggers/README.md
@@ -0,0 +1,172 @@
+# Triggering Builds through the API
+
+_**Note:** This feature was [introduced][ci-229] in GitLab CE 7.14_
+
+Triggers can be used to force a rebuild of a specific branch, tag or commit,
+with an API call.
+
+## Add a trigger
+
+You can add a new trigger by going to your project's **Settings > Triggers**.
+The **Add trigger** button will create a new token which you can then use to
+trigger a rebuild of this particular project.
+
+Every new trigger you create, gets assigned a different token which you can
+then use inside your scripts or `.gitlab-ci.yml`. You also have a nice
+overview of the time the triggers were last used.
+
+![Triggers page overview](img/triggers_page.png)
+
+## Revoke a trigger
+
+You can revoke a trigger any time by going at your project's
+**Settings > Triggers** and hitting the **Revoke** button. The action is
+irreversible.
+
+## Trigger a build
+
+To trigger a build you need to send a `POST` request to GitLab's API endpoint:
+
+```
+POST /projects/:id/trigger/builds
+```
+
+The required parameters are the trigger's `token` and the Git `ref` on which
+the trigger will be performed. Valid refs are the branch, the tag or the commit
+SHA. The `:id` of a project can be found by [querying the API](../api/projects.md)
+or by visiting the **Triggers** page which provides self-explanatory examples.
+
+When a rebuild is triggered, the information is exposed in GitLab's UI under
+the **Builds** page and the builds are marked as `triggered`.
+
+![Marked rebuilds as triggered on builds page](img/builds_page.png)
+
+---
+
+You can see which trigger caused the rebuild by visiting the single build page.
+The token of the trigger is exposed in the UI as you can see from the image
+below.
+
+![Marked rebuilds as triggered on a single build page](img/trigger_single_build.png)
+
+---
+
+See the [Examples](#examples) section for more details on how to actually
+trigger a rebuild.
+
+## Pass build variables to a trigger
+
+You can pass any number of arbitrary variables in the trigger API call and they
+will be available in GitLab CI so that they can be used in your `.gitlab-ci.yml`
+file. The parameter is of the form:
+
+```
+variables[key]=value
+```
+
+This information is also exposed in the UI.
+
+![Build variables in UI](img/trigger_variables.png)
+
+---
+
+See the [Examples](#examples) section below for more details.
+
+## Examples
+
+Using cURL you can trigger a rebuild with minimal effort, for example:
+
+```bash
+curl -X POST \
+     -F token=TOKEN \
+     -F ref=master \
+     https://gitlab.example.com/api/v3/projects/9/trigger/builds
+```
+
+In this case, the project with ID `9` will get rebuilt on `master` branch.
+
+
+### Triggering a build within `.gitlab-ci.yml`
+
+You can also benefit by using triggers in your `.gitlab-ci.yml`. Let's say that
+you have two projects, A and B, and you want to trigger a rebuild on the `master`
+branch of project B whenever a tag on project A is created. This is the job you
+need to add in project's A `.gitlab-ci.yml`:
+
+```yaml
+build_docs:
+  stage: deploy
+  script:
+  - "curl -X POST -F token=TOKEN -F ref=master https://gitlab.example.com/api/v3/projects/9/trigger/builds"
+  only:
+  - tags
+```
+
+Now, whenever a new tag is pushed on project A, the build will run and the
+`build_docs` job will be executed, triggering a rebuild of project B. The
+`stage: deploy` ensures that this job will run only after all jobs with
+`stage: test` complete successfully.
+
+_**Note:** If your project is public, passing the token in plain text is
+probably not the wisest idea, so you might want to use a
+[secure variable](../variables/README.md#user-defined-variables-secure-variables)
+for that purpose._
+
+### Making use of trigger variables
+
+Using trigger variables can be proven useful for a variety of reasons.
+
+* Identifiable jobs. Since the variable is exposed in the UI you can know
+  why the rebuild was triggered if you pass a variable that explains the
+  purpose.
+* Conditional job processing. You can have conditional jobs that run whenever
+  a certain variable is present.
+
+Consider the following `.gitlab-ci.yml` where we set three
+[stages](../yaml/README.md#stages) and the `upload_package` job is run only
+when all jobs from the test and build stages pass. When the `UPLOAD_TO_S3`
+variable is non-zero, `make upload` is run.
+
+```yaml
+stages:
+- test
+- build
+- package
+
+run_tests:
+  script:
+  - make test
+
+build_package:
+  stage: build
+  script:
+  - make build
+
+upload_package:
+  stage: package
+  script:
+  - if [ -n "${UPLOAD_TO_S3}" ]; then make upload; fi
+```
+
+You can then trigger a rebuild while you pass the `UPLOAD_TO_S3` variable
+and the script of the `upload_package` job will run:
+
+```bash
+curl -X POST \
+  -F token=TOKEN \
+  -F ref=master \
+  -F "variables[UPLOAD_TO_S3]=true" \
+  https://gitlab.example.com/api/v3/projects/9/trigger/builds
+```
+
+### Using cron to trigger nightly builds
+
+Whether you craft a script or just run cURL directly, you can trigger builds
+in conjunction with cron. The example below triggers a build on the `master`
+branch of project with ID `9` every night at `00:30`:
+
+```bash
+30 0 * * * curl -X POST -F token=TOKEN -F ref=master https://gitlab.example.com/api/v3/projects/9/trigger/builds
+```
+
+[ci-229]: https://gitlab.com/gitlab-org/gitlab-ci/merge_requests/229
diff --git a/doc/ci/triggers/img/builds_page.png b/doc/ci/triggers/img/builds_page.png
new file mode 100644
index 0000000000000000000000000000000000000000..e78794fbee767d82382d2d97e7c9f91a9d9c09c7
Binary files /dev/null and b/doc/ci/triggers/img/builds_page.png differ
diff --git a/doc/ci/triggers/img/trigger_single_build.png b/doc/ci/triggers/img/trigger_single_build.png
new file mode 100644
index 0000000000000000000000000000000000000000..c25f27409d65ce5548cd26940cc568c62fcd5425
Binary files /dev/null and b/doc/ci/triggers/img/trigger_single_build.png differ
diff --git a/doc/ci/triggers/img/trigger_variables.png b/doc/ci/triggers/img/trigger_variables.png
new file mode 100644
index 0000000000000000000000000000000000000000..2207e8b34cbd6b42970e3e47e0740973e0ca655f
Binary files /dev/null and b/doc/ci/triggers/img/trigger_variables.png differ
diff --git a/doc/ci/triggers/img/triggers_page.png b/doc/ci/triggers/img/triggers_page.png
new file mode 100644
index 0000000000000000000000000000000000000000..268368dc3c5b7c6046c2c15f0819641699e9d9a6
Binary files /dev/null and b/doc/ci/triggers/img/triggers_page.png differ
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 022afb700424c25eab121cc08d00e667d4999e7f..b99ea25a3fe33ef74ceef3a9a4202452e897e95e 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -27,7 +27,6 @@ The API_TOKEN will take the Secure Variable value: `SECURE`.
 | **CI_BUILD_TAG**        | 0.5 | The commit tag name. Present only when building tags. |
 | **CI_BUILD_NAME**       | 0.5 | The name of the build as defined in `.gitlab-ci.yml` |
 | **CI_BUILD_STAGE**      | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
-| **CI_BUILD_BEFORE_SHA** | all | The first commit that were included in push request |
 | **CI_BUILD_REF_NAME**   | all | The branch or tag name for which project is built |
 | **CI_BUILD_ID**         | all | The unique id of the current build that GitLab CI uses internally |
 | **CI_BUILD_REPO**       | all | The URL to clone the Git repository |
@@ -40,7 +39,6 @@ The API_TOKEN will take the Secure Variable value: `SECURE`.
 Example values:
 
 ```bash
-export CI_BUILD_BEFORE_SHA="9df57456fa9de2a6d335ca5edf9750ed812b9df0"
 export CI_BUILD_ID="50"
 export CI_BUILD_REF="1ecfd275763eff1d6b4844ea3168962458c9f27a"
 export CI_BUILD_REF_NAME="master"
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 7e2edb945da6035e586d7fbd7cf3e8c0cb2c07c5..fd0d49de4e438ba654ee160276733cb38768069d 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1,9 +1,12 @@
 # Configuration of your builds with .gitlab-ci.yml
-From version 7.12, GitLab CI uses a [YAML](https://en.wikipedia.org/wiki/YAML) file (**.gitlab-ci.yml**) for the project configuration.
-It is placed in the root of your repository and contains definitions of how your project should be built.
 
-The YAML file defines a set of jobs with constraints stating when they should be run.
-The jobs are defined as top-level elements with a name and always have to contain the `script` clause:
+From version 7.12, GitLab CI uses a [YAML](https://en.wikipedia.org/wiki/YAML)
+file (`.gitlab-ci.yml`) for the project configuration. It is placed in the root
+of your repository and contains definitions of how your project should be built.
+
+The YAML file defines a set of jobs with constraints stating when they should
+be run. The jobs are defined as top-level elements with a name and always have
+to contain the `script` clause:
 
 ```yaml
 job1:
@@ -13,15 +16,21 @@ job2:
   script: "execute-script-for-job2"
 ```
 
-The above example is the simplest possible CI configuration with two separate jobs,
-where each of the jobs executes a different command.
-Of course a command can execute code directly (`./configure;make;make install`) or run a script (`test.sh`) in the repository.
+The above example is the simplest possible CI configuration with two separate
+jobs, where each of the jobs executes a different command.
+
+Of course a command can execute code directly (`./configure;make;make install`)
+or run a script (`test.sh`) in the repository.
 
-Jobs are used to create builds, which are then picked up by [runners](../runners/README.md) and executed within the environment of the runner.
-What is important, is that each job is run independently from each other.
+Jobs are used to create builds, which are then picked up by
+[runners](../runners/README.md) and executed within the environment of the
+runner. What is important, is that each job is run independently from each
+other.
 
 ## .gitlab-ci.yml
-The YAML syntax allows for using more complex job specifications than in the above example:
+
+The YAML syntax allows for using more complex job specifications than in the
+above example:
 
 ```yaml
 image: ruby:2.1
@@ -46,26 +55,31 @@ job1:
     - docker
 ```
 
-There are a few `keywords` that can't be used as job names:
+There are a few reserved `keywords` that **cannot** be used as job names:
 
-| keyword       | required | description |
+| Keyword       | Required | Description |
 |---------------|----------|-------------|
-| image         | optional | Use docker image, covered in [Use Docker](../docker/README.md) |
-| services      | optional | Use docker services, covered in [Use Docker](../docker/README.md) |
-| stages        | optional | Define build stages |
-| types         | optional | Alias for `stages` |
-| before_script | optional | Define commands prepended for each job's script |
-| variables     | optional | Define build variables |
-| cache         | optional | Define list of files that should be cached between subsequent runs |
+| image         | no | Use docker image, covered in [Use Docker](../docker/README.md) |
+| services      | no | Use docker services, covered in [Use Docker](../docker/README.md) |
+| stages        | no | Define build stages |
+| types         | no | Alias for `stages` |
+| before_script | no | Define commands that run before each job's script |
+| variables     | no | Define build variables |
+| cache         | no | Define list of files that should be cached between subsequent runs |
 
 ### image and services
-This allows to specify a custom Docker image and a list of services that can be used for time of the build.
-The configuration of this feature is covered in separate document: [Use Docker](../docker/README.md).
+
+This allows to specify a custom Docker image and a list of services that can be
+used for time of the build. The configuration of this feature is covered in
+separate document: [Use Docker](../docker/README.md).
 
 ### before_script
-`before_script` is used to define the command that should be run before all builds, including deploy builds. This can be an array or a multiline string.
+
+`before_script` is used to define the command that should be run before all
+builds, including deploy builds. This can be an array or a multi-line string.
 
 ### stages
+
 `stages` is used to define build stages that can be used by jobs.
 The specification of `stages` allows for having flexible multi stage pipelines.
 
@@ -75,7 +89,8 @@ The ordering of elements in `stages` defines the ordering of builds' execution:
 1. Builds of next stage are run after success.
 
 Let's consider the following example, which defines 3 stages:
-```
+
+```yaml
 stages:
   - build
   - test
@@ -86,21 +101,26 @@ stages:
 1. If all jobs of `build` succeeds, the `test` jobs are executed in parallel.
 1. If all jobs of `test` succeeds, the `deploy` jobs are executed in parallel.
 1. If all jobs of `deploy` succeeds, the commit is marked as `success`.
-1. If any of the previous jobs fails, the commit is marked as `failed` and no jobs of further stage are executed.
+1. If any of the previous jobs fails, the commit is marked as `failed` and no
+   jobs of further stage are executed.
 
 There are also two edge cases worth mentioning:
 
-1. If no `stages` is defined in `.gitlab-ci.yml`, then by default the `build`, `test` and `deploy` are allowed to be used as job's stage by default.
+1. If no `stages` is defined in `.gitlab-ci.yml`, then by default the `build`,
+   `test` and `deploy` are allowed to be used as job's stage by default.
 2. If a job doesn't specify `stage`, the job is assigned the `test` stage.
 
 ### types
+
 Alias for [stages](#stages).
 
 ### variables
-**This feature requires `gitlab-runner` with version equal or greater than 0.5.0.**
 
-GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in build environment.
-The variables are stored in repository and are meant to store non-sensitive project configuration, ie. RAILS_ENV or DATABASE_URL.
+_**Note:** Introduced in GitLab Runner v0.5.0._
+
+GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in build
+environment. The variables are stored in the git repository and are meant to
+store non-sensitive project configuration, for example:
 
 ```yaml
 variables:
@@ -109,18 +129,23 @@ variables:
 
 These variables can be later used in all executed commands and scripts.
 
-The YAML-defined variables are also set to all created service containers, thus allowing to fine tune them.
+The YAML-defined variables are also set to all created service containers,
+thus allowing to fine tune them.
 
 ### cache
-`cache` is used to specify list of files and directories which should be cached between builds.
-Caches are stored according to the branch/ref and the job name. Caches are not
-currently shared between different job names or between branches/refs. This means
-caching will benefit you if you push subsequent commits to an existing feature branch.
 
-**The global setting allows to specify default cached files for all jobs.**
+`cache` is used to specify a list of files and directories which should be
+cached between builds. Caches are stored according to the branch/ref and the
+job name. They are not currently shared between different job names or between
+branches/refs, which means that caching will benefit you if you push subsequent
+commits to an existing feature branch.
+
+If `cache` is defined outside the scope of the jobs, it means it is set
+globally and all jobs will use its definition.
 
 To cache all git untracked files and files in `binaries`:
-```
+
+```yaml
 cache:
   untracked: true
   paths:
@@ -128,9 +153,10 @@ cache:
 ```
 
 ## Jobs
-`.gitlab-ci.yml` allows you to specify an unlimited number of jobs.
-Each job has to have a unique `job_name`, which is not one of the keywords mentioned above.
-A job is defined by a list of parameters that define the build behaviour.
+
+`.gitlab-ci.yml` allows you to specify an unlimited number of jobs. Each job
+must have a unique name, which is not one of the Keywords mentioned above.
+A job is defined by a list of parameters that define the build behavior.
 
 ```yaml
 job_name:
@@ -148,21 +174,22 @@ job_name:
   allow_failure: true
 ```
 
-| keyword       | required | description |
+| Keyword       | Required | Description |
 |---------------|----------|-------------|
-| script        | required | Defines a shell script which is executed by runner |
-| stage         | optional (default: test) | Defines a build stage |
-| type          | optional | Alias for `stage` |
-| only          | optional | Defines a list of git refs for which build is created |
-| except        | optional | Defines a list of git refs for which build is not created |
-| tags          | optional | Defines a list of tags which are used to select runner |
-| allow_failure | optional | Allow build to fail. Failed build doesn't contribute to commit status |
-| when          | optional | Define when to run build. Can be `on_success`, `on_failure` or `always` |
-| artifacts     | optional | Define list build artifacts |
-| cache         | optional | Define list of files that should be cached between subsequent runs |
+| script        | yes | Defines a shell script which is executed by runner |
+| stage         | no (default: `test`) | Defines a build stage |
+| type          | no | Alias for `stage` |
+| only          | no | Defines a list of git refs for which build is created |
+| except        | no | Defines a list of git refs for which build is not created |
+| tags          | no | Defines a list of tags which are used to select runner |
+| allow_failure | no | Allow build to fail. Failed build doesn't contribute to commit status |
+| when          | no | Define when to run build. Can be `on_success`, `on_failure` or `always` |
+| artifacts     | no | Define list build artifacts |
+| cache         | no | Define list of files that should be cached between subsequent runs |
 
 ### script
-`script` is a shell script which is executed by runner. The shell script is prepended with `before_script`.
+
+`script` is a shell script which is executed by the runner. For example:
 
 ```yaml
 job:
@@ -170,6 +197,7 @@ job:
 ```
 
 This parameter can also contain several commands using an array:
+
 ```yaml
 job:
   script:
@@ -178,31 +206,45 @@ job:
 ```
 
 ### stage
-`stage` allows to group build into different stages. Builds of the same `stage` are executed in `parallel`.
-For more info about the use of `stage` please check the [stages](#stages).
+
+`stage` allows to group build into different stages. Builds of the same `stage`
+are executed in `parallel`. For more info about the use of `stage` please check
+[stages](#stages).
 
 ### only and except
-This are two parameters that allow for setting a refs policy to limit when jobs are built:
-1. `only` defines the names of branches and tags for which job will be built.
-2. `except` defines the names of branches and tags for which the job wil **not** be built.
 
-There are a few rules that apply to usage of refs policy:
+`only` and `except` are two parameters that set a refs policy to limit when
+jobs are built:
 
-1. `only` and `except` are inclusive. If both `only` and `except` are defined in job specification the ref is filtered by `only` and `except`.
-1. `only` and `except` allow for using the regexp expressions.
-1. `only` and `except` allow for using special keywords: `branches` and `tags`.
-These names can be used for example to exclude all tags and all branches.
+1. `only` defines the names of branches and tags for which the job will be
+    built.
+2. `except` defines the names of branches and tags for which the job will
+    **not** be built.
+
+There are a few rules that apply to the usage of refs policy:
+
+* `only` and `except` are inclusive. If both `only` and `except` are defined
+   in a job specification, the ref is filtered by `only` and `except`.
+* `only` and `except` allow the use of regular expressions.
+* `only` and `except` allow the use of special keywords: `branches` and `tags`.
+* `only` and `except` allow to specify a repository path to filter jobs for
+   forks.
+
+In the example below, `job` will run only for refs that start with `issue-`,
+whereas all branches will be skipped.
 
 ```yaml
 job:
+  # use regexp
   only:
-    - /^issue-.*$/ # use regexp
+    - /^issue-.*$/
+  # use special keyword
   except:
-    - branches # use special keyword
+    - branches
 ```
 
-1. `only` and `except` allow for specify repository path to filter jobs for forks.
-The repository path can be used to have jobs executed only for parent repository.
+The repository path can be used to have jobs executed only for the parent
+repository and not forks:
 
 ```yaml
 job:
@@ -211,33 +253,47 @@ job:
   except:
     - master@gitlab-org/gitlab-ce
 ```
-The above will run `job` for all branches on `gitlab-org/gitlab-ce`, except master .
+
+The above example will run `job` for all branches on `gitlab-org/gitlab-ce`,
+except master.
 
 ### tags
-`tags` is used to select specific runners from the list of all runners that are allowed to run this project.
 
-During registration of a runner, you can specify the runner's tags, ie.: `ruby`, `postgres`, `development`.
-`tags` allow you to run builds with runners that have the specified tags assigned:
+`tags` is used to select specific runners from the list of all runners that are
+allowed to run this project.
 
-```
+During the registration of a runner, you can specify the runner's tags, for
+example `ruby`, `postgres`, `development`.
+
+`tags` allow you to run builds with runners that have the specified tags
+assigned to them:
+
+```yaml
 job:
   tags:
     - ruby
     - postgres
 ```
 
-The above specification will make sure that `job` is built by a runner that have `ruby` AND `postgres` tags defined.
+The specification above, will make sure that `job` is built by a runner that
+has both `ruby` AND `postgres` tags defined.
 
 ### when
-`when` is used to implement jobs that are run in case of failure or despite the failure.
+
+`when` is used to implement jobs that are run in case of failure or despite the
+failure.
 
 `when` can be set to one of the following values:
 
-1. `on_success` - execute build only when all builds from prior stages succeeded. This is the default.
-1. `on_failure` - execute build only when at least one build from prior stages failed.
+1. `on_success` - execute build only when all builds from prior stages
+    succeeded. This is the default.
+1. `on_failure` - execute build only when at least one build from prior stages
+    failed.
 1. `always` - execute build despite the status of builds from prior stages.
 
-```
+For example:
+
+```yaml
 stages:
 - build
 - cleanup_build
@@ -245,28 +301,28 @@ stages:
 - deploy
 - cleanup
 
-build:
+build_job:
   stage: build
   script:
   - make build
 
-cleanup_build:
+cleanup_build_job:
   stage: cleanup_build
   script:
   - cleanup build when failed
   when: on_failure
 
-test:
+test_job:
   stage: test
   script:
   - make test
 
-deploy:
+deploy_job:
   stage: deploy
   script:
   - make deploy
 
-cleanup:
+cleanup_job:
   stage: cleanup
   script:
   - cleanup after builds
@@ -274,84 +330,108 @@ cleanup:
 ```
 
 The above script will:
-1. Execute `cleanup_build` only when the `build` failed,
-2. Always execute `cleanup` as the last step in pipeline.
+
+1. Execute `cleanup_build_job` only when `build_job` fails
+2. Always execute `cleanup_job` as the last step in pipeline.
 
 ### artifacts
-`artifacts` is used to specify list of files and directories which should be attached to build after success.
 
-1. Send all files in `binaries` and `.config`:
+_**Note:** Introduced in GitLab Runner v0.7.0. Also, the Windows shell executor
+ does not currently support artifact uploads._
 
-        artifacts:
-          paths:
-          - binaries/
-          - .config
+`artifacts` is used to specify list of files and directories which should be
+attached to build after success. Below are some examples.
 
-2. Send all git untracked files:
+Send all files in `binaries` and `.config`:
 
-        artifacts:
-          untracked: true
+```yaml
+artifacts:
+  paths:
+  - binaries/
+  - .config
+```
 
-3. Send all git untracked files and files in `binaries`:
+Send all git untracked files:
 
-        artifacts:
-          untracked: true
-          paths:
-          - binaries/
+```yaml
+artifacts:
+  untracked: true
+```
+
+Send all git untracked files and files in `binaries`:
 
-The artifacts will be send after the build success to GitLab and will be accessible in GitLab interface to download.
+```yaml
+artifacts:
+  untracked: true
+  paths:
+  - binaries/
+```
 
-This feature requires GitLab Runner v0.7.0 or higher.
+The artifacts will be send after a successful build success to GitLab, and will
+be accessible in the GitLab UI to download.
 
 ### cache
-`cache` is used to specify list of files and directories which should be cached between builds.
 
-1. Cache all files in `binaries` and `.config`:
+_**Note:** Introduced in GitLab Runner v0.7.0._
 
-        rspec:
-          script: test
-          cache:
-            paths:
-            - binaries/
-            - .config
+`cache` is used to specify list of files and directories which should be cached
+between builds. Below are some examples:
 
-2. Cache all git untracked files:
+Cache all files in `binaries` and `.config`:
 
-        rspec:
-          script: test
-          cache:
-            untracked: true
-            
-3. Cache all git untracked files and files in `binaries`:
+```yaml
+rspec:
+  script: test
+  cache:
+    paths:
+    - binaries/
+    - .config
+```
 
-        rspec:
-          script: test
-          cache:
-            untracked: true
-            paths:
-            - binaries/
+Cache all git untracked files:
 
-4. Locally defined cache overwrites globally defined options. This will cache only `binaries/`:
+```yaml
+rspec:
+  script: test
+  cache:
+    untracked: true
+```
+
+Cache all git untracked files and files in `binaries`:
+
+```yaml
+rspec:
+  script: test
+  cache:
+    untracked: true
+    paths:
+    - binaries/
+```
 
-        cache:
-          paths:
-          - my/files
-        
-        rspec:
-          script: test
-          cache:
-            paths:
-            - binaries/
+Locally defined cache overwrites globally defined options. This will cache only
+`binaries/`:
 
-The cache is provided on best effort basis, so don't expect that cache will be present.
-For implementation details please check GitLab Runner.
+```yaml
+cache:
+  paths:
+  - my/files
 
-This feature requires GitLab Runner v0.7.0 or higher.
+rspec:
+  script: test
+  cache:
+    paths:
+    - binaries/
+```
 
+The cache is provided on best effort basis, so don't expect that cache will be
+always present. For implementation details please check GitLab Runner.
 
 ## Validate the .gitlab-ci.yml
+
 Each instance of GitLab CI has an embedded debug tool called Lint.
-You can find the link to the Lint in the project's settings page or use short url `/lint`.
+You can find the link under `/ci/lint` of your gitlab instance.
 
 ## Skipping builds
-There is one more way to skip all builds, if your commit message contains tag [ci skip]. In this case, commit will be created but builds will be skipped
+
+If your commit message contains `[ci skip]`, the commit will be created but the
+builds will be skipped.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index f8116a8a31c2b9afa199cfda8e84057d16eb6052..81edd8da2b845f055bba5f964dc6b3c98a979ac5 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -348,7 +348,7 @@ GitLab Shell is an SSH access and repository management software developed speci
     cd /home/git
     sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-workhorse.git
     cd gitlab-workhorse
-    sudo -u git -H git checkout 0.4.2
+    sudo -u git -H git checkout 0.5.1
     sudo -u git -H make
 
 ### Initialize Database and Activate Advanced Features
diff --git a/doc/integration/README.md b/doc/integration/README.md
index eff39a626ae6205a122558fd5f8990882d930b04..2a9f76533b733a224af1389fef13caf00dac73ef 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -4,13 +4,16 @@ GitLab integrates with multiple third-party services to allow external issue tra
 
 See the documentation below for details on how to configure these services.
 
+- [Jira](jira.md) Integrate with the JIRA issue tracker
 - [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
 - [LDAP](ldap.md) Set up sign in via LDAP
 - [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth.
 - [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider
+- [CAS](cas.md) Configure GitLab to sign in using CAS
 - [Slack](slack.md) Integrate with the Slack chat service
 - [OAuth2 provider](oauth_provider.md) OAuth2 application creation
 - [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages
+- [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users
 
 GitLab Enterprise Edition contains [advanced JIRA support](http://doc.gitlab.com/ee/integration/jira.html) and [advanced Jenkins support](http://doc.gitlab.com/ee/integration/jenkins.html).
 
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
new file mode 100644
index 0000000000000000000000000000000000000000..e6b2071f193cd5ca5e424960f4ac9a198de7fbcd
--- /dev/null
+++ b/doc/integration/cas.md
@@ -0,0 +1,62 @@
+# CAS OmniAuth Provider
+
+To enable the CAS OmniAuth provider you must register your application with your CAS instance. This requires the service URL GitLab will supply to CAS. It should be something like: `https://gitlab.example.com:443/users/auth/cas3/callback?url`. By default handling for SLO is enabled, you only need to configure CAS for backchannel logout.
+
+1.  On your GitLab server, open the configuration file.
+
+    For omnibus package:
+
+    ```sh
+      sudo editor /etc/gitlab/gitlab.rb
+    ```
+
+    For installations from source:
+
+    ```sh
+      cd /home/git/gitlab
+
+      sudo -u git -H editor config/gitlab.yml
+    ```
+
+1.  See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1.  Add the provider configuration:
+
+    For omnibus package:
+
+    ```ruby
+      gitlab_rails['omniauth_providers'] = [
+        {
+          name: "cas3",
+          label: "cas",
+          args: {
+                  url: 'CAS_SERVER',
+                  login_url: '/CAS_PATH/login',
+                  service_validate_url: '/CAS_PATH/p3/serviceValidate',
+                  logout_url: '/CAS_PATH/logout'} }
+          }
+        }
+      ]
+    ```
+
+    For installations from source:
+
+    ```
+      - { name: 'cas3',
+          label: 'cas',
+          args: {
+                  url: 'CAS_SERVER',
+                  login_url: '/CAS_PATH/login',
+                  service_validate_url: '/CAS_PATH/p3/serviceValidate',
+                  logout_url: '/CAS_PATH/logout'} }
+    ```
+
+1.  Change 'CAS_PATH' to the root of your CAS instance (ie. `cas`).
+
+1.  If your CAS instance does not use default TGC lifetimes, update the `cas3.session_duration` to at least the current TGC maximum lifetime. To explicitly disable SLO, regardless of CAS settings, set this to 0.
+
+1.  Save the configuration file.
+
+1.  Restart GitLab for the changes to take effect.
+
+On the sign in page there should now be a CAS tab in the sign in form.
diff --git a/doc/integration/jira.md b/doc/integration/jira.md
new file mode 100644
index 0000000000000000000000000000000000000000..624601d0faccb8e0192d7d7865168a9da0798255
--- /dev/null
+++ b/doc/integration/jira.md
@@ -0,0 +1,113 @@
+# GitLab Jira integration
+
+GitLab can be configured to interact with Jira.
+Configuration happens via username and password.
+Connecting to a Jira server via CAS is not possible.
+
+Each project can be configured to connect to a different Jira instance, configuration is explained [here](#configuration).
+If you have one Jira instance you can pre-fill the settings page with a default template. To configure the template [see external issue tracker document](external-issue-tracker.md#service-template)).
+
+Once the project is connected to Jira, you can reference and close the issues in Jira directly from GitLab.
+
+
+## Table of Contents
+
+* [Referencing Jira Issues from GitLab](#referencing-jira-issues)
+* [Closing Jira Issues from GitLab](#closing-jira-issues)
+* [Configuration](#configuration)
+
+### Referencing Jira Issues
+
+When GitLab project has Jira issue tracker configured and enabled, mentioning Jira issue in GitLab will automatically add a comment in Jira issue with the link back to GitLab. This means that in comments in merge requests and commits referencing an issue, eg. `PROJECT-7`, will add a comment in Jira issue in the format:
+
+
+```
+ USER mentioned this issue in LINK_TO_THE_MENTION
+```
+
+* `USER` A user that mentioned the issue. This is the link to the user profile in GitLab.
+* `LINK_TO_THE_MENTION` Link to the origin of mention with a name of the entity where Jira issue was mentioned.
+Can be commit or merge request.
+
+
+![example of mentioning or closing the Jira issue](jira_issue_reference.png)
+
+
+### Closing Jira Issues
+
+Jira issues can be closed directly from GitLab by using trigger words, eg. `Resolves PROJECT-1`, `Closes PROJECT-1` or `Fixes PROJECT-1`, in commits and merge requests.
+When a commit which contains the trigger word in the commit message is pushed, GitLab will add a comment in the mentioned Jira issue.
+
+For example, for project named PROJECT in Jira, we implemented a new feature and created a merge request in GitLab.
+
+This feature was requested in Jira issue PROJECT-7. Merge request in GitLab contains the improvement and in merge request description we say that this merge request `Closes PROJECT-7` issue.
+
+Once this merge request is merged, Jira issue will be automatically closed with a link to the commit that resolved the issue.
+
+![A Git commit that causes the Jira issue to be closed](merge_request_close_jira.png)
+
+
+![The GitLab integration user leaves a comment on Jira](jira_service_close_issue.png)
+
+
+## Configuration
+
+### Configuring JIRA
+
+We need to create a user in JIRA which will have access to all projects that need to integrate with GitLab.
+Login to your JIRA instance as admin and under Administration go to User Management and create a new user.
+As an example, we'll create a user named `gitlab` and add it to `jira-developers` group.
+
+**It is important that the user `gitlab` has write-access to projects in JIRA**
+
+### Configuring GitLab
+
+### GitLab 7.8 EE and up with JIRA v6.x
+
+To enable JIRA integration in a project, navigate to the project Settings page and go to Services. Here you will find JIRA.
+
+Fill in the required details on the page:
+
+![Jira service page](jira_service_page.png)
+
+* `description` A name for the issue tracker (to differentiate between instances, for instance).
+* `project url` The URL to the JIRA project which is being linked to this GitLab project.
+* `issues url` The URL to the JIRA project issues overview for the project that is linked to this GitLab project.
+* `new issue url` This is the URL to create a new issue in JIRA for the project linked to this GitLab project.
+* `api url` The base URL of the JIRA API. It may be omitted, in which case GitLab will automatically use API version `2` based on the `project url`, i.e. `https://jira.example.com/rest/api/2`.
+* `username` The username of the user created in [configuring JIRA step](#configuring-jira).
+* `password` The password of the user created in [configuring JIRA step](#configuring-jira).
+* `Jira issue transition` This is the id of a transition that moves issues to a closed state. You can find this number under [JIRA workflow administration, see screenshot](jira_workflow_screenshot.png).  By default, this id is `2`. (In the example image, this is `2` as well)
+
+After saving the configuration, your GitLab project will be able to interact with the linked JIRA project.
+
+
+### GitLab 6.x-7.7 with JIRA v6.x
+
+**Note: GitLab 7.8 and up contain various integration improvements. We strongly recommend upgrading.**
+
+
+In `gitlab.yml` enable [JIRA issue tracker section by uncommenting the lines](https://gitlab.com/subscribers/gitlab-ee/blob/6-8-stable-ee/config/gitlab.yml.example#L111-115).
+This will make sure that all issues within GitLab are pointing to the JIRA issue tracker.
+
+We can also enable JIRA service that will allow us to interact with JIRA issues.
+
+For example, we can close issues in JIRA by a commit in GitLab.
+
+Go to project settings page and fill in the project name for the JIRA project:
+
+![Set the JIRA project name in GitLab to 'NEW'](jira_project_name.png)
+
+Next, go to the services page and find JIRA.
+
+![Jira services page](jira_service.png)
+
+1. Tick the active check box to enable the service.
+1. Supply the url to JIRA server, for example http://jira.sample
+1. Supply the username of a user we created under `Configuring JIRA` section, for example `gitlab`
+1. Supply the password of the user
+1. Optional: supply the JIRA api version, default is version
+1. Optional: supply the JIRA issue transition ID (issue transition to closed). This is dependant on JIRA settings, default is 2
+1. Save
+
+Now we should be able to interact with JIRA issues.
diff --git a/doc/integration/jira_issue_reference.png b/doc/integration/jira_issue_reference.png
new file mode 100644
index 0000000000000000000000000000000000000000..15739a22dc7151af663316c1d44e8fcda704ce29
Binary files /dev/null and b/doc/integration/jira_issue_reference.png differ
diff --git a/doc/integration/jira_project_name.png b/doc/integration/jira_project_name.png
new file mode 100644
index 0000000000000000000000000000000000000000..5986fdb63fb8727b339b69d7fa6b64d3ef5f4b17
Binary files /dev/null and b/doc/integration/jira_project_name.png differ
diff --git a/doc/integration/jira_service.png b/doc/integration/jira_service.png
new file mode 100644
index 0000000000000000000000000000000000000000..1f6628c43719edd55d415f80d28d8d4423002586
Binary files /dev/null and b/doc/integration/jira_service.png differ
diff --git a/doc/integration/jira_service_close_issue.png b/doc/integration/jira_service_close_issue.png
new file mode 100644
index 0000000000000000000000000000000000000000..67dfc6144c44f0643e1373bef9961bf0c3a458fb
Binary files /dev/null and b/doc/integration/jira_service_close_issue.png differ
diff --git a/doc/integration/jira_service_page.png b/doc/integration/jira_service_page.png
new file mode 100644
index 0000000000000000000000000000000000000000..69ec44e826fb82702103f7cf1fd4299084e24151
Binary files /dev/null and b/doc/integration/jira_service_page.png differ
diff --git a/doc/integration/jira_workflow_screenshot.png b/doc/integration/jira_workflow_screenshot.png
new file mode 100644
index 0000000000000000000000000000000000000000..8635a32eb6874fa64bc53ba671794c20e9df2f00
Binary files /dev/null and b/doc/integration/jira_workflow_screenshot.png differ
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
new file mode 100644
index 0000000000000000000000000000000000000000..a301d1a613c3a8e8800911fd0a48a41bccb1f3e3
--- /dev/null
+++ b/doc/integration/recaptcha.md
@@ -0,0 +1,23 @@
+# reCAPTCHA
+
+GitLab leverages [Google's reCAPTCHA](https://www.google.com/recaptcha/intro/index.html)
+to protect against spam and abuse. GitLab displays the CAPTCHA form on the sign-up page
+to confirm that a real user, not a bot, is attempting to create an account.
+
+## Configuration
+
+To use reCAPTCHA, first you must create a site and private key.
+
+1. Go to the URL: https://www.google.com/recaptcha/admin
+
+2. Fill out the form necessary to obtain reCAPTCHA keys.
+
+3. Login to your GitLab server, with administrator credentials.
+
+4. Go to Applications Settings on Admin Area (`admin/application_settings`)
+
+5. Fill all recaptcha fields with keys from previous steps
+
+6. Check the `Enable reCAPTCHA` checkbox
+
+7.  Save the configuration.
diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md
index bcd00cfc6bf82f44c19fdc96980a6c19377bbfa7..1be78ac1823f4470c40d3e1148ffcd233f25f4af 100644
--- a/doc/permissions/permissions.md
+++ b/doc/permissions/permissions.md
@@ -6,11 +6,11 @@ If a user is both in a project group and in the project itself, the highest perm
 
 If a user is a GitLab administrator they receive all permissions.
 
-On public projects the Guest role is not enforced.  
-All users will be able to create issues, leave comments, and pull or download the project code.  
+On public projects the Guest role is not enforced.
+All users will be able to create issues, leave comments, and pull or download the project code.
 
 To add or import a user, you can follow the [project users and members
-documentation](doc/workflow/add-user/add-user.md).
+documentation](../workflow/add-user/add-user.md).
 
 ## Project
 
diff --git a/doc/security/README.md b/doc/security/README.md
index fba6013d9c153ac2d91aa7252dfe547aaab299a7..f34c792d00549596d2860c18f2985d84bca37090 100644
--- a/doc/security/README.md
+++ b/doc/security/README.md
@@ -6,3 +6,5 @@
 - [Information exclusivity](information_exclusivity.md)
 - [Reset your root password](reset_root_password.md)
 - [User File Uploads](user_file_uploads.md)
+- [How we manage the CRIME vulnerability](crime_vulnerability.md)
+- [Enforce Two-Factor authentication](two_factor_authentication.md)
diff --git a/doc/security/crime_vulnerability.md b/doc/security/crime_vulnerability.md
new file mode 100644
index 0000000000000000000000000000000000000000..94ba5d1375dd550178deecce20d36851054119a5
--- /dev/null
+++ b/doc/security/crime_vulnerability.md
@@ -0,0 +1,63 @@
+# How we manage the TLS protocol CRIME vulnerability
+
+> CRIME ("Compression Ratio Info-leak Made Easy") is a security exploit against
+secret web cookies over connections using the HTTPS and SPDY protocols that also
+use data compression. When used to recover the content of secret
+authentication cookies, it allows an attacker to perform session hijacking on an
+authenticated web session, allowing the launching of further attacks.
+([CRIME](https://en.wikipedia.org/w/index.php?title=CRIME&oldid=692423806))
+
+### Description
+
+The TLS Protocol CRIME Vulnerability affects compression over HTTPS, therefore
+it warns against using SSL Compression (for example gzip) or SPDY which
+optionally uses compression as well.
+
+GitLab supports both gzip and [SPDY][ngx-spdy] and mitigates the CRIME
+vulnerability by deactivating gzip when HTTPS is enabled. You can see the
+sources of the files in question:
+
+* [Source installation NGINX file][source-nginx]
+* [Omnibus installation NGINX file][omnibus-nginx]
+
+Although SPDY is enabled in Omnibus installations, CRIME relies on compression
+(the 'C') and the default compression level in NGINX's SPDY module is 0
+(no compression).
+
+### Nessus
+
+The Nessus scanner, [reports a possible CRIME vulnerability][nessus] in GitLab
+similar to the following format:
+
+```
+Description
+
+This remote service has one of two configurations that are known to be required for the CRIME attack:
+SSL/TLS compression is enabled.
+TLS advertises the SPDY protocol earlier than version 4.
+
+...
+
+Output
+
+The following configuration indicates that the remote service may be vulnerable to the CRIME attack:
+SPDY support earlier than version 4 is advertised.
+```
+
+From the report above it is important to note that Nessus is only checking if
+TLS advertises the SPDY protocol earlier than version 4, it does not perform an
+attack nor does it check if compression is enabled. With just this approach, it
+cannot tell that SPDY's compression is disabled and not subject to the CRIME
+vulnerability.
+
+### References
+
+* Nginx ["Module ngx_http_spdy_module"][ngx-spdy]
+* Tenable Network Security, Inc. ["Transport Layer Security (TLS) Protocol CRIME Vulnerability"][nessus]
+* Wikipedia contributors, ["CRIME"][wiki-crime] Wikipedia, The Free Encyclopedia
+
+[source-nginx]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/gitlab-ssl
+[omnibus-nginx]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/templates/default/nginx-gitlab-http.conf.erb
+[ngx-spdy]: http://nginx.org/en/docs/http/ngx_http_spdy_module.html
+[nessus]: https://www.tenable.com/plugins/index.php?view=single&id=62565
+[wiki-crime]: https://en.wikipedia.org/wiki/CRIME
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
new file mode 100644
index 0000000000000000000000000000000000000000..4e25a1fdc3ff381c271726b968da2e01d0b97f79
--- /dev/null
+++ b/doc/security/two_factor_authentication.md
@@ -0,0 +1,38 @@
+# Enforce Two-factor Authentication (2FA)
+
+Two-factor Authentication (2FA) provides an additional level of security to your
+users' GitLab account. Once enabled, in addition to supplying their username and
+password to login, they'll be prompted for a code generated by an application on
+their phone.
+
+You can read more about it here:
+[Two-factor Authentication (2FA)](doc/profile/two_factor_authentication.md)
+
+## Enabling 2FA
+
+Users on GitLab, can enable it without any admin's intervention. If you want to
+enforce everyone to setup 2FA, you can choose from two different ways:
+
+ 1. Enforce on next login
+ 2. Suggest on next login, but allow a grace period before enforcing.
+
+In the Admin area under **Settings** (`/admin/application_settings`), look for
+the "Sign-in Restrictions" area, where you can configure both.
+
+If you want 2FA enforcement to take effect on next login, change the grace
+period to `0`
+
+## Disabling 2FA for everyone
+
+There may be some special situations where you want to disable 2FA for everyone
+even when forced 2FA is disabled. There is a rake task for that:
+
+```
+# use this command if you've installed GitLab with the Omnibus package
+sudo gitlab-rake gitlab:two_factor:disable_for_all_users
+
+# if you've installed GitLab from source
+sudo -u git -H bundle exec rake gitlab:two_factor:disable_for_all_users RAILS_ENV=production
+```
+
+**IMPORTANT: this is a permanent and irreversible action. Users will have to reactivate 2FA from scratch if they want to use it again.**
diff --git a/doc/update/8.2-to-8.3.md b/doc/update/8.2-to-8.3.md
index e69c4f7ed3c2da2ec9330ceb54ee37e7c57ff49f..3748941b7815a93c9de94fe1ace36496e1d01b29 100644
--- a/doc/update/8.2-to-8.3.md
+++ b/doc/update/8.2-to-8.3.md
@@ -67,7 +67,7 @@ sudo -u git -H git checkout 8-3-stable-ee
 ```bash
 cd /home/git/gitlab-shell
 sudo -u git -H git fetch --all
-sudo -u git -H git checkout v2.6.8
+sudo -u git -H git checkout v2.6.9
 ```
 
 ### 5. Update gitlab-workhorse
@@ -78,7 +78,7 @@ which should already be on your system from GitLab 8.1.
 ```bash
 cd /home/git/gitlab-workhorse
 sudo -u git -H git fetch --all
-sudo -u git -H git checkout 0.4.2
+sudo -u git -H git checkout 0.5.1
 sudo -u git -H make
 ```
 
@@ -99,8 +99,6 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
 # Clean up assets and cache
 sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
 
-# Update init.d script
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
 ```
 
 ### 7. Update configuration files
@@ -115,6 +113,12 @@ git diff origin/8-2-stable:config/gitlab.yml.example origin/8-3-stable:config/gi
 
 #### Nginx configuration
 
+GitLab 8.3 introduces major changes in the NGINX configuration.
+Because all HTTP requests pass through gitlab-workhorse now a lot of
+directives need to be removed from NGINX. During future upgrades there
+should be much less changes in the NGINX configuration because of
+this.
+
 View changes between the previous recommended Nginx configuration and the
 current one:
 
@@ -134,6 +138,18 @@ via [/etc/default/gitlab].
 [Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
 [/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-3-stable/lib/support/init.d/gitlab.default.example#L34
 
+#### Init script
+
+We updated the init script for GitLab in order to pass new
+configuration options to gitlab-workhorse. We let gitlab-workhorse
+connect to the Rails application via a Unix domain socket and we tell
+it where the 'public' directory of GitLab is.
+
+```
+cd /home/git/gitlab
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
 ### 8. Use Redis v2.8.0+
 
 Previous versions of GitLab allowed Redis versions >= 2.0 to be used, but
diff --git a/doc/workflow/README.md b/doc/workflow/README.md
index d2642495c9a45938e6f31c2415ba4b9bbf90aa11..3651b55f438ee3c9d45e56e6daf69dd5e8c6a3b3 100644
--- a/doc/workflow/README.md
+++ b/doc/workflow/README.md
@@ -19,3 +19,4 @@
 - ["Work In Progress" Merge Requests](wip_merge_requests.md)
 - [Merge When Build Succeeds](merge_when_build_succeeds.md)
 - [Manage large binaries with Git LFS](lfs/manage_large_binaries_with_git_lfs.md)
+- [Importing from SVN, GitHub, BitBucket, etc](importing/README.md)
diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md
index 7ccf06fbd60b8ef634dc98ce93c1537f9af44e76..18e5d950866a4c16f70a5155848bce9b74f0f80d 100644
--- a/doc/workflow/importing/README.md
+++ b/doc/workflow/importing/README.md
@@ -1,13 +1,17 @@
 # Migrating projects to a GitLab instance
 
 1. [Bitbucket](import_projects_from_bitbucket.md)
-2. [GitHub](import_projects_from_github.md)
-3. [GitLab.com](import_projects_from_gitlab_com.md)
-4. [FogBugz](import_projects_from_fogbugz.md)
-4. [SVN](migrating_from_svn.md)
+1. [GitHub](import_projects_from_github.md)
+1. [GitLab.com](import_projects_from_gitlab_com.md)
+1. [FogBugz](import_projects_from_fogbugz.md)
+1. [SVN](migrating_from_svn.md)
 
-### Note
-* If you'd like to migrate from a self-hosted GitLab instance to GitLab.com, you can copy your repos by changing the remote and pushing to the new server; but issues and merge requests can't be imported.
+In addition to the specific migration documentation above, you can import any
+Git repository via HTTP from the New Project page. Be aware that if the
+repository is too large the import can timeout.
+
+### Migrating from self-hosted GitLab to GitLab.com
+
+You can copy your repos by changing the remote and pushing to the new server;
+but issues and merge requests can't be imported.
 
-* You can import any Git repository via HTTP from the New Project page.
-If the repository is too large, it can timeout. 
diff --git a/doc/workflow/importing/migrating_from_svn.md b/doc/workflow/importing/migrating_from_svn.md
index 1938ccd0c264c42b2d42b7772f85980e1d1d262d..b355a91b5a6e693ba060a5b49beca7ae0c9c635d 100644
--- a/doc/workflow/importing/migrating_from_svn.md
+++ b/doc/workflow/importing/migrating_from_svn.md
@@ -1,17 +1,78 @@
 # Migrating from SVN to GitLab
 
-SVN stands for Subversion and is a version control system (VCS).
-Git is a distributed version control system.
+Subversion (SVN) is a central version control system (VCS) while
+Git is a distributed version control system. There are some major differences
+between the two, for more information consult your favorite search engine.
 
-There are some major differences between the two, for more information consult your favorite search engine.
+If you are currently using an SVN repository, you can migrate the repository
+to Git and GitLab. We recommend a hard cut over - run the migration command once
+and then have all developers start using the new GitLab repository immediately.
+Otherwise, it's hard to keep changing in sync in both directions. The conversion
+process should be run on a local workstation.
 
-Git has tools for migrating SVN repositories to git, namely `git svn`. You can read more about this at
-[git documentation pages](https://git-scm.com/book/en/Git-and-Other-Systems-Git-and-Subversion).
+Install `svn2git`. On all systems you can install as a Ruby gem if you already
+have Ruby and Git installed.
 
-Apart from the [official git documentation](https://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git) there is also
-user created step by step guide for migrating from SVN to GitLab.
+```bash
+sudo gem install svn2git
+```
 
-[Benjamin New](https://github.com/leftclickben) wrote [a guide that shows how to do a migration](https://gist.github.com/leftclickben/322b7a3042cbe97ed2af). Mirrors can be found [here](https://gitlab.com/snippets/2168) and [here](https://gist.github.com/maxlazio/f1b593b0d00aa966e9ca).
+On Debian-based Linux distributions you can install the native packages:
+
+```bash
+sudo apt-get install git-core git-svn ruby
+```
+
+Optionally, prepare an authors file so `svn2git` can map SVN authors to Git authors.
+If you choose not to create the authors file then commits will not be attributed
+to the correct GitLab user. Some users may not consider this a big issue while
+others will want to ensure they complete this step. If you choose to map authors
+you will be required to map every author that is present on changes in the SVN
+repository. If you don't, the conversion will fail and you will have to update
+the author file accordingly. The following command will search through the
+repository and output a list of authors.
+
+```bash
+svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq
+```
+
+Use the output from the last command to construct the authors file.
+Create a file called `authors.txt` and add one mapping per line.
+
+```
+janedoe = Jane Doe <janedoe@example.com>
+johndoe = John Doe <johndoe@example.com>
+```
+
+If your SVN repository is in the standard format (trunk, branches, tags,
+not nested) the conversion is simple. For a non-standard repository see
+[svn2git documentation](https://github.com/nirvdrum/svn2git). The following
+command will checkout the repository and do the conversion in the current
+working directory. Be sure to create a new directory for each repository before
+running the `svn2git` command. The conversion process will take some time.
+
+```bash
+svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt
+```
+
+If your SVN repository requires a username and password add the
+`--username <username>` and `--password <password` flags to the above command.
+`svn2git` also supports excluding certain file paths, branches, tags, etc. See
+[svn2git documentation](https://github.com/nirvdrum/svn2git) or run
+`svn2git --help` for full documentation on all of the available options.
+
+Create a new GitLab project, where you will eventually push your converted code.
+Copy the SSH or HTTP(S) repository URL from the project page. Add the GitLab
+repository as a Git remote and push all the changes. This will push all commits,
+branches and tags.
+
+```bash
+git remote add origin git@gitlab.com:<group>/<project>.git
+git push --all origin
+```
 
 ## Contribute to this guide
-We welcome all contributions that would expand this guide with instructions on how to migrate from SVN and other version control systems.
+We welcome all contributions that would expand this guide with instructions on
+how to migrate from SVN and other version control systems.
+
+
diff --git a/features/project/commits/branches.feature b/features/project/commits/branches.feature
index 5103ca1294756abebba39fd1c97034612ff274ec..2c17d32154a9788bcb168213358aa305e506c154 100644
--- a/features/project/commits/branches.feature
+++ b/features/project/commits/branches.feature
@@ -25,6 +25,7 @@ Feature: Project Commits Branches
     And I click branch 'improve/awesome' delete link
     Then I should not see branch 'improve/awesome'
 
+  @javascript
   Scenario: I create a branch with invalid name
     Given I visit project branches page
     And I click new branch link
diff --git a/features/project/create.feature b/features/project/create.feature
index a86079143e58ad86233cd5c37ff71de859d8def2..27136798e36d14f9b2b55a306f8b8bc30b189297 100644
--- a/features/project/create.feature
+++ b/features/project/create.feature
@@ -1,3 +1,4 @@
+@project-create
 Feature: Project Create
   In order to get access to project sections
   A user with ability to create a project
diff --git a/features/project/issues/award_emoji.feature b/features/project/issues/award_emoji.feature
index 0ce99e855c6f91b0c8d0c16af8f065963647146e..9a06fdc2ee6eb5ea0a40a84ea441a31cc3b5ebdc 100644
--- a/features/project/issues/award_emoji.feature
+++ b/features/project/issues/award_emoji.feature
@@ -13,7 +13,18 @@ Feature: Award Emoji
     Then I have award added
     And I can remove it by clicking to icon
 
+  @javascript
+  Scenario: I can see the list of emoji categories
+    Given I click to emoji-picker
+    Then I can see the activity and food categories
+
+  @javascript
+  Scenario: I can search emoji
+    Given I click to emoji-picker
+    And I search "hand"
+    Then I see search result for "hand"
+
   @javascript
   Scenario: I add award emoji using regular comment
-  Given I leave comment with a single emoji
-  Then I have award added
+    Given I leave comment with a single emoji
+    Then I have award added
diff --git a/features/project/merge_requests/accept.feature b/features/project/merge_requests/accept.feature
index d5e4f2b0bd8c4755d616fd5a76b44574cd1d9be1..330ec8ae0fe552cc9b4480525724626135a584d8 100644
--- a/features/project/merge_requests/accept.feature
+++ b/features/project/merge_requests/accept.feature
@@ -12,6 +12,14 @@ Feature: Project Merge Requests Acceptance
     Then I should see merge request merged
     And I should not see the Remove Source Branch button
 
+  @javascript
+  Scenario: Accepting the Merge Request when URL has an anchor
+    Given I am on the Merge Request detail with note anchor page
+    When I click on "Remove source branch" option
+    And I click on Accept Merge Request
+    Then I should see merge request merged
+    And I should not see the Remove Source Branch button
+
   @javascript
   Scenario: Accepting the Merge Request without removing the source branch
     Given I am on the Merge Request detail page
diff --git a/features/project/service.feature b/features/project/service.feature
index ff3e7a0b38e6bd063878f3246d9806c8aa876275..3a7b830852489d2560619a4aabc6203023827cff 100644
--- a/features/project/service.feature
+++ b/features/project/service.feature
@@ -55,6 +55,12 @@ Feature: Project Services
     And I fill email on push settings
     Then I should see email on push service settings saved
 
+  Scenario: Activate JIRA service
+    When I visit project "Shop" services page
+    And I click jira service link
+    And I fill jira settings
+    Then I should see jira service settings saved
+
   Scenario: Activate Irker (IRC Gateway) service
     When I visit project "Shop" services page
     And I click Irker service link
diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature
index 02159ee3776e9dafa46905e7f0bb248946b31ba8..a8c276b949ea51f9b928c72acdf6d5b4fd414e0b 100644
--- a/features/project/source/browse_files.feature
+++ b/features/project/source/browse_files.feature
@@ -24,6 +24,12 @@ Feature: Project Source Browse Files
     Given I click on "New file" link in repo
     Then I can see new file page
 
+  Scenario: I can create file when I don't have write access
+    Given I don't have write access
+    And I click on "New file" link in repo
+    Then I should see a notice about a new fork having been created
+    Then I can see new file page
+
   @javascript
   Scenario: I can create and commit file
     Given I click on "New file" link in repo
@@ -34,6 +40,17 @@ Feature: Project Source Browse Files
     Then I am redirected to the new file
     And I should see its new content
 
+  @javascript
+  Scenario: I can create and commit file when I don't have write access
+    Given I don't have write access
+    And I click on "New file" link in repo
+    And I edit code
+    And I fill the new file name
+    And I fill the commit message
+    And I click on "Commit Changes"
+    Then I am redirected to the fork's new merge request page
+    And I can see the new commit message
+
   @javascript
   Scenario: I can create and commit file with new lines at the end of file
     Given I click on "New file" link in repo
@@ -45,6 +62,17 @@ Feature: Project Source Browse Files
     And I click button "Edit"
     And I should see its content with new lines preserved at end of file
 
+  @javascript
+  Scenario: I can create and commit file and specify new branch
+    Given I click on "New file" link in repo
+    And I edit code
+    And I fill the new file name
+    And I fill the commit message
+    And I fill the new branch name
+    And I click on "Commit Changes"
+    Then I am redirected to the new merge request page
+    And I should see its new content
+
   @javascript
   Scenario: I can upload file and commit
     Given I click on "Upload file" link in repo
@@ -56,6 +84,19 @@ Feature: Project Source Browse Files
     And I am redirected to the new merge request page
     And I can see the new commit message
 
+  @javascript
+  Scenario: I can upload file and commit when I don't have write access
+    Given I don't have write access
+    And I click on "Upload file" link in repo
+    Then I should see a notice about a new fork having been created
+    When I click on "Upload file" link in repo
+    And I upload a new text file
+    And I fill the upload file commit message
+    And I click on "Upload file"
+    Then I can see the new text file
+    And I am redirected to the fork's new merge request page
+    And I can see the new commit message
+
   @javascript
   Scenario: I can replace file and commit
     Given I click on ".gitignore" file in repo
@@ -68,15 +109,19 @@ Feature: Project Source Browse Files
     And I can see the replacement commit message
 
   @javascript
-  Scenario: I can create and commit file and specify new branch
-    Given I click on "New file" link in repo
-    And I edit code
-    And I fill the new file name
-    And I fill the commit message
-    And I fill the new branch name
-    And I click on "Commit Changes"
-    Then I am redirected to the new merge request page
-    And I should see its new content
+  Scenario: I can replace file and commit when I don't have write access
+    Given I don't have write access
+    And I click on ".gitignore" file in repo
+    And I see the ".gitignore"
+    And I click on "Replace"
+    Then I should see a notice about a new fork having been created
+    When I click on "Replace"
+    And I replace it with a text file
+    And I fill the replace file commit message
+    And I click on "Replace file"
+    Then I can see the new text file
+    And I am redirected to the fork's new merge request page
+    And I can see the replacement commit message
 
   @javascript
   Scenario: I can create file in empty repo
@@ -117,6 +162,14 @@ Feature: Project Source Browse Files
     And I click button "Edit"
     Then I can edit code
 
+  @javascript
+  Scenario: I can edit file when I don't have write access
+    Given I don't have write access
+    And I click on ".gitignore" file in repo
+    And I click button "Edit"
+    Then I should see a notice about a new fork having been created
+    And I can edit code
+
   Scenario: If the file is binary the edit link is hidden
     Given I visit a binary file in the repo
     Then I cannot see the edit button
@@ -131,6 +184,17 @@ Feature: Project Source Browse Files
     Then I am redirected to the ".gitignore"
     And I should see its new content
 
+  @javascript
+  Scenario: I can edit and commit file when I don't have write access
+    Given I don't have write access
+    And I click on ".gitignore" file in repo
+    And I click button "Edit"
+    And I edit code
+    And I fill the commit message
+    And I click on "Commit Changes"
+    Then I am redirected to the fork's new merge request page
+    And I can see the new commit message
+
   @javascript
   Scenario: I can edit and commit file to new branch
     Given I click on ".gitignore" file in repo
@@ -161,6 +225,17 @@ Feature: Project Source Browse Files
     And I click on "Create directory"
     Then I am redirected to the new merge request page
 
+  @javascript
+  Scenario: I can create directory in repo when I don't have write access
+    Given I don't have write access
+    When I click on "New directory" link in repo
+    Then I should see a notice about a new fork having been created
+    When I click on "New directory" link in repo
+    And I fill the new directory name
+    And I fill the commit message
+    And I click on "Create directory"
+    Then I am redirected to the fork's new merge request page
+
   @javascript
   Scenario: I attempt to create an existing directory
     When I click on "New directory" link in repo
@@ -188,6 +263,19 @@ Feature: Project Source Browse Files
     Then I am redirected to the files URL
     And I don't see the ".gitignore"
 
+  @javascript
+  Scenario: I can delete file and commit when I don't have write access
+    Given I don't have write access
+    And I click on ".gitignore" file in repo
+    And I see the ".gitignore"
+    And I click on "Delete"
+    Then I should see a notice about a new fork having been created
+    When I click on "Delete"
+    And I fill the commit message
+    And I click on "Delete file"
+    Then I am redirected to the fork's new merge request page
+    And I can see the new commit message
+
   Scenario: I can browse directory with Browse Dir
     Given I click on files directory
     And I click on History link
diff --git a/features/project/star.feature b/features/project/star.feature
index a45f9c470ea8921eb2f023899752af0af6e83d38..618f44fe6dc31cc2a4ce916debbcca2a85cfc233 100644
--- a/features/project/star.feature
+++ b/features/project/star.feature
@@ -1,3 +1,4 @@
+@project-stars
 Feature: Project Star
   Scenario: New projects have 0 stars
     Given public project "Community"
diff --git a/features/steps/explore/groups.rb b/features/steps/explore/groups.rb
index 87cd33c37eb2d187556e1d7222dcb803ba96cdcd..87f32e70d59257c2b9365c692451d12ad55848d1 100644
--- a/features/steps/explore/groups.rb
+++ b/features/steps/explore/groups.rb
@@ -75,18 +75,18 @@ class Spinach::Features::ExploreGroups < Spinach::FeatureSteps
       name: projectname,
       path: "#{groupname}-#{projectname}",
       visibility_level: visibility_level
-    )
+                    )
     create(:issue,
       title: "#{projectname} feature",
       project: project
-    )
+          )
     create(:merge_request,
       title: "#{projectname} feature implemented",
       source_project: project,
       target_project: project
-    )
+          )
     create(:closed_issue_event,
       project: project
-    )
+          )
   end
 end
diff --git a/features/steps/explore/projects.rb b/features/steps/explore/projects.rb
index f819dec219231e5fd8eede68794a500fed569244..742ba5d71f66680adc64c3ea41da634543258509 100644
--- a/features/steps/explore/projects.rb
+++ b/features/steps/explore/projects.rb
@@ -61,11 +61,11 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
     create(:issue,
        title: "Bug",
        project: public_project
-      )
+          )
     create(:issue,
        title: "New feature",
        project: public_project
-      )
+          )
     visit namespace_project_issues_path(public_project.namespace, public_project)
   end
 
@@ -80,11 +80,11 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
     create(:issue,
        title: "Internal Bug",
        project: internal_project
-      )
+          )
     create(:issue,
        title: "New internal feature",
        project: internal_project
-      )
+          )
     visit namespace_project_issues_path(internal_project.namespace, internal_project)
   end
 
@@ -104,7 +104,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
       title: "Bug fix for public project",
       source_project: public_project,
       target_project: public_project,
-    )
+          )
   end
 
   step 'I should see list of merge requests for "Community" project' do
@@ -121,7 +121,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
       title: "Feature implemented",
       source_project: internal_project,
       target_project: internal_project
-    )
+          )
   end
 
   step 'I should see list of merge requests for "Internal" project' do
diff --git a/features/steps/groups.rb b/features/steps/groups.rb
index f5e3fee61c0f08fcd26677b5a0c20106b25bb91a..4c5122d1b7d505b9d0afe2dae55972cf3e63a541 100644
--- a/features/steps/groups.rb
+++ b/features/steps/groups.rb
@@ -85,7 +85,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
 
   step 'I should see new group "Owned" avatar' do
     expect(owned_group.avatar).to be_instance_of AvatarUploader
-    expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{ Group.find_by(name:"Owned").id }/banana_sample.gif"
+    expect(owned_group.avatar.url).to eq "/uploads/group/avatar/#{Group.find_by(name:"Owned").id}/banana_sample.gif"
   end
 
   step 'I should see the "Remove avatar" button' do
diff --git a/features/steps/profile/profile.rb b/features/steps/profile/profile.rb
index 40b2aa7c357761bde578679b678d1bf39a1cb6ae..0305f7e6da0bc76e7ae831e86238505a7a3115c8 100644
--- a/features/steps/profile/profile.rb
+++ b/features/steps/profile/profile.rb
@@ -34,7 +34,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
 
   step 'I should see new avatar' do
     expect(@user.avatar).to be_instance_of AvatarUploader
-    expect(@user.avatar.url).to eq "/uploads/user/avatar/#{ @user.id }/banana_sample.gif"
+    expect(@user.avatar.url).to eq "/uploads/user/avatar/#{@user.id}/banana_sample.gif"
   end
 
   step 'I should see the "Remove avatar" button' do
diff --git a/features/steps/project/commits/branches.rb b/features/steps/project/commits/branches.rb
index 338f5e8d3ee66ce7c2ed50bf4f3695b2e7a6e614..0a42931147dc1ee7f78562f97c6fe1172ec1fec1 100644
--- a/features/steps/project/commits/branches.rb
+++ b/features/steps/project/commits/branches.rb
@@ -61,7 +61,8 @@ class Spinach::Features::ProjectCommitsBranches < Spinach::FeatureSteps
   end
 
   step 'I should see new an error that branch is invalid' do
-    expect(page).to have_content 'Branch name invalid'
+    expect(page).to have_content 'Branch name is invalid'
+    expect(page).to have_content "can't contain spaces"
   end
 
   step 'I should see new an error that ref is invalid' do
diff --git a/features/steps/project/create.rb b/features/steps/project/create.rb
index f90218f379162380cdc78d46168dd27ca63a7b72..8a0e8fc2b6c8998937c4140558cc882e877d5a20 100644
--- a/features/steps/project/create.rb
+++ b/features/steps/project/create.rb
@@ -26,7 +26,8 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps
   end
 
   step 'I click on HTTP' do
-    click_button 'HTTP'
+    find('#clone-dropdown').click
+    find('#http-selector').click
   end
 
   step 'Remote url should update to http link' do
@@ -34,7 +35,8 @@ class Spinach::Features::ProjectCreate < Spinach::FeatureSteps
   end
 
   step 'If I click on SSH' do
-    click_button 'SSH'
+    find('#clone-dropdown').click
+    find('#ssh-selector').click
   end
 
   step 'Remote url should update to ssh link' do
diff --git a/features/steps/project/forked_merge_requests.rb b/features/steps/project/forked_merge_requests.rb
index d3675060994c820d0b1fd67838ed4e8f0e6f319d..cbdce78dc0ca300923c36096b632463d35821e09 100644
--- a/features/steps/project/forked_merge_requests.rb
+++ b/features/steps/project/forked_merge_requests.rb
@@ -41,7 +41,8 @@ class Spinach::Features::ProjectForkedMergeRequests < Spinach::FeatureSteps
 
     click_button "Compare branches and continue"
 
-    expect(page).to have_content "New Merge Request"
+    expect(page).to have_css("h3.page-title", text: "New Merge Request")
+
     fill_in "merge_request_title", with: "Merge Request On Forked Project"
   end
 
diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb
index 325eaf2ea6a5834ea388eed6e1244e152b372a88..2c2ed08655ee722e077139a9e27eeeaca5d9660d 100644
--- a/features/steps/project/issues/award_emoji.rb
+++ b/features/steps/project/issues/award_emoji.rb
@@ -15,22 +15,31 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
   end
 
   step 'I click to emoji in the picker' do
-    page.within '.awards-menu' do
-      page.first('img').click
+    page.within '.emoji-menu-content' do
+      page.first('.emoji-icon').click
     end
   end
 
   step 'I can remove it by clicking to icon' do
     page.within '.awards' do
-      page.first('.award').click
-      expect(page).to_not have_selector '.award'
+      expect do
+        page.find('.award.active').click
+        sleep 0.3
+      end.to change{ page.all(".award").size }.from(3).to(2)
+    end
+  end
+
+  step 'I can see the activity and food categories' do
+    page.within '.emoji-menu' do
+      expect(page).to_not have_selector 'Activity'
+      expect(page).to_not have_selector 'Food'
     end
   end
 
   step 'I have award added' do
     page.within '.awards' do
       expect(page).to have_selector '.award'
-      expect(page.find('.award .counter')).to have_content '1'
+      expect(page.find('.award.active .counter')).to have_content '1'
     end
   end
 
@@ -45,4 +54,16 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
       click_button 'Add Comment'
     end
   end
+
+  step 'I search "hand"' do
+    page.within('.emoji-menu-content') do
+      fill_in 'emoji_search', with: 'hand'
+    end
+  end
+
+  step 'I see search result for "hand"' do
+    page.within '.emoji-menu-content' do
+      expect(page).to have_selector '[data-emoji="raised_hand"]'
+    end
+  end
 end
diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb
index 4a7ff21d385334f159f83034dea163727efa9ee8..8e8c9c57452f5218de00570885a90de15efaa855 100644
--- a/features/steps/project/issues/issues.rb
+++ b/features/steps/project/issues/issues.rb
@@ -59,15 +59,14 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
   end
 
   step 'I click "author" dropdown' do
-    first('.ajax-users-select').click
+    first('#s2id_author_id').click
   end
 
   step 'I see current user as the first user' do
-    expect(page).to have_selector('.user-result', visible: true, count: 4)
+    expect(page).to have_selector('.user-result', visible: true, count: 3)
     users = page.all('.user-name')
-    expect(users[0].text).to eq 'Any Assignee'
-    expect(users[1].text).to eq 'Unassigned'
-    expect(users[2].text).to eq current_user.name
+    expect(users[0].text).to eq 'Any Author'
+    expect(users[1].text).to eq current_user.name
   end
 
   step 'I submit new issue "500 error on profile"' do
diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb
index 0d340d97ff915a2893fa916e816d634ecaaa57fc..be993d11093edf42d08122f946436980361575b4 100644
--- a/features/steps/project/merge_requests.rb
+++ b/features/steps/project/merge_requests.rb
@@ -273,7 +273,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I should see merged request' do
-    page.within '.issue-box' do
+    page.within '.status-box' do
       expect(page).to have_content "Merged"
     end
   end
@@ -283,7 +283,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
   end
 
   step 'I should see reopened merge request "Bug NS-04"' do
-    page.within '.issue-box' do
+    page.within '.status-box' do
       expect(page).to have_content "Open"
     end
   end
diff --git a/features/steps/project/merge_requests/acceptance.rb b/features/steps/project/merge_requests/acceptance.rb
index 383c055c4efeb7926a7164e65eb557afc4b0563e..2685f5fd6b4b5f891fe4fb75afb7128d55fbd0f2 100644
--- a/features/steps/project/merge_requests/acceptance.rb
+++ b/features/steps/project/merge_requests/acceptance.rb
@@ -6,6 +6,10 @@ class Spinach::Features::ProjectMergeRequestsAcceptance < Spinach::FeatureSteps
     visit merge_request_path(@merge_request)
   end
 
+  step 'I am on the Merge Request detail with note anchor page' do
+    visit merge_request_path(@merge_request, anchor: 'note_123')
+  end
+
   step 'I click on "Remove source branch" option' do
     check('Remove source branch')
   end
diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb
index 9ca7c8ebbc7ef8ed8efcbeb3f7f137d14e16c5eb..37bf52b4a95ac1eda2d568a60fd24015c33d6f86 100644
--- a/features/steps/project/project.rb
+++ b/features/steps/project/project.rb
@@ -37,7 +37,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps
   step 'I should see new project avatar' do
     expect(@project.avatar).to be_instance_of AvatarUploader
     url = @project.avatar.url
-    expect(url).to eq "/uploads/project/avatar/#{ @project.id }/banana_sample.gif"
+    expect(url).to eq "/uploads/project/avatar/#{@project.id}/banana_sample.gif"
   end
 
   step 'I should see the "Remove avatar" button' do
diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb
index ed3957ca87364b9b3cbd75b1f62b3ca2d10333b0..536199ddb4fd7c25f766b7a93b5a74dd992490e0 100644
--- a/features/steps/project/services.rb
+++ b/features/steps/project/services.rb
@@ -173,6 +173,24 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
     expect(find_field('Sound').find('option[selected]').value).to eq 'bike'
   end
 
+  step 'I click jira service link' do
+    click_link 'JIRA'
+  end
+
+  step 'I fill jira settings' do
+    fill_in 'Project url', with: 'http://jira.example'
+    fill_in 'Username', with: 'gitlab'
+    fill_in 'Password', with: 'gitlab'
+    fill_in 'Api url', with: 'http://jira.example/rest/api/2'
+    click_button 'Save'
+  end
+
+  step 'I should see jira service settings saved' do
+    expect(find_field('Project url').value).to eq 'http://jira.example'
+    expect(find_field('Username').value).to eq 'gitlab'
+    expect(find_field('Api url').value).to eq 'http://jira.example/rest/api/2'
+  end
+
   step 'I click Atlassian Bamboo CI service link' do
     click_link 'Atlassian Bamboo CI'
   end
diff --git a/features/steps/project/snippets.rb b/features/steps/project/snippets.rb
index a3aef9bf8c30c417093bb70d34489fd6b05a93fd..504654f90ddd12a28980281778bcae256015bd23 100644
--- a/features/steps/project/snippets.rb
+++ b/features/steps/project/snippets.rb
@@ -42,7 +42,7 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps
   end
 
   step 'I click link "Edit"' do
-    page.within ".page-title" do
+    page.within ".detail-page-header" do
       click_link "Edit"
     end
   end
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index b88709620ab82f7e90c1cd21f5c32eed629236aa..d08935aa1010a9f10be706ba03f8e87edba1d53d 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -5,6 +5,12 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   include SharedPaths
   include RepoHelpers
 
+  step "I don't have write access" do
+    @project = create(:project, name: "Other Project", path: "other-project")
+    @project.team << [@user, :reporter]
+    visit namespace_project_tree_path(@project.namespace, @project, root_ref)
+  end
+
   step 'I should see files from repository' do
     expect(page).to have_content "VERSION"
     expect(page).to have_content ".gitignore"
@@ -75,7 +81,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I fill the new branch name' do
-    fill_in :new_branch, with: 'new_branch_name', visible: true
+    fill_in :target_branch, with: 'new_branch_name', visible: true
   end
 
   step 'I fill the new file name with an illegal name' do
@@ -87,7 +93,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I fill the commit message' do
-    fill_in :commit_message, with: 'Not yet a commit message.', visible: true
+    fill_in :commit_message, with: 'New commit message', visible: true
   end
 
   step 'I click link "Diff"' do
@@ -103,7 +109,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I click on "Delete"' do
-    click_button 'Delete'
+    click_on 'Delete'
   end
 
   step 'I click on "Delete file"' do
@@ -111,7 +117,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I click on "Replace"' do
-    click_button  "Replace"
+    click_on  "Replace"
   end
 
   step 'I click on "Replace file"' do
@@ -124,7 +130,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
 
   step 'I click on "New file" link in repo' do
     find('.add-to-tree').click
-    click_link 'Create file'
+    click_link 'New file'
   end
 
   step 'I click on "Upload file" link in repo' do
@@ -155,7 +161,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I can see the new commit message' do
-    expect(page).to have_content "New upload commit message"
+    expect(page).to have_content "New commit message"
   end
 
   step 'I upload a new text file' do
@@ -164,7 +170,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
 
   step 'I fill the upload file commit message' do
     page.within('#modal-upload-blob') do
-      fill_in :commit_message, with: 'New upload commit message'
+      fill_in :commit_message, with: 'New commit message'
     end
   end
 
@@ -238,22 +244,27 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
   end
 
   step 'I am redirected to the new file' do
-    expect(current_path).to eq(namespace_project_blob_path(
-      @project.namespace, @project, 'master/' + new_file_name))
+    expect(current_path).to eq(
+      namespace_project_blob_path(@project.namespace, @project, 'master/' + new_file_name))
   end
 
   step 'I am redirected to the new file with directory' do
-    expect(current_path).to eq(namespace_project_blob_path(
-      @project.namespace, @project, 'master/' + new_file_name_with_directory))
+    expect(current_path).to eq(
+      namespace_project_blob_path(@project.namespace, @project, 'master/' + new_file_name_with_directory))
   end
 
   step 'I am redirected to the new merge request page' do
     expect(current_path).to eq(new_namespace_project_merge_request_path(@project.namespace, @project))
   end
 
+  step "I am redirected to the fork's new merge request page" do
+    fork = @user.fork_of(@project)
+    expect(current_path).to eq(new_namespace_project_merge_request_path(fork.namespace, fork))
+  end
+
   step 'I am redirected to the root directory' do
-    expect(current_path).to eq(namespace_project_tree_path(
-      @project.namespace, @project, 'master/'))
+    expect(current_path).to eq(
+      namespace_project_tree_path(@project.namespace, @project, 'master'))
   end
 
   step "I don't see the permalink link" do
@@ -332,8 +343,12 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
     expect(page).to have_content 'Permalink'
     expect(page).not_to have_content 'Edit'
     expect(page).not_to have_content 'Blame'
-    expect(page).not_to have_content 'Delete'
-    expect(page).not_to have_content 'Replace'
+    expect(page).to have_content 'Delete'
+    expect(page).to have_content 'Replace'
+  end
+
+  step 'I should see a notice about a new fork having been created' do
+    expect(page).to have_content "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
   end
 
   private
diff --git a/features/steps/project/star.rb b/features/steps/project/star.rb
index bd2e0619cddd8be94d6717fec3d268a41313cc14..9f7c748a3b78ff3bae147189db11af8c430908e2 100644
--- a/features/steps/project/star.rb
+++ b/features/steps/project/star.rb
@@ -32,6 +32,6 @@ class Spinach::Features::ProjectStar < Spinach::FeatureSteps
   protected
 
   def has_n_stars(n)
-    expect(page).to have_css(".star-btn .count", text: n, visible: true)
+    expect(page).to have_css(".star-count", text: n, visible: true)
   end
 end
diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb
index dd466cde28d0efb5fa6a2c0bfab6cdea68053fee..c6a0ae2ba38e06110bce21311a248aaccd74d27c 100644
--- a/features/steps/shared/diff_note.rb
+++ b/features/steps/shared/diff_note.rb
@@ -166,7 +166,7 @@ module SharedDiffNote
   end
 
   step 'I should see add a diff comment button' do
-    expect(page).to have_css('.js-add-diff-note-button', visible: true)
+    expect(page).to have_css('.js-add-diff-note-button')
   end
 
   step 'I should see an empty diff comment form' do
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index c74a5fd3bc7e7cfa7d044ccb3182622847b0baa6..b33bd332655849909229518a722539a9323cc23c 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -212,8 +212,8 @@ module SharedPaths
   end
 
   step 'I visit a binary file in the repo' do
-    visit namespace_project_blob_path(@project.namespace, @project, File.join(
-      root_ref, 'files/images/logo-black.png'))
+    visit namespace_project_blob_path(@project.namespace, @project,
+      File.join(root_ref, 'files/images/logo-black.png'))
   end
 
   step "I visit my project's commits page" do
@@ -316,8 +316,8 @@ module SharedPaths
   end
 
   step 'I am on the ".gitignore" edit file page' do
-    expect(current_path).to eq(namespace_project_edit_blob_path(
-      @project.namespace, @project, File.join(root_ref, '.gitignore')))
+    expect(current_path).to eq(
+      namespace_project_edit_blob_path(@project.namespace, @project, File.join(root_ref, '.gitignore')))
   end
 
   step 'I visit project source page for "6d39438"' do
diff --git a/features/steps/snippets/snippets.rb b/features/steps/snippets/snippets.rb
index 80d1ddeef055177d7df0d3ef3e2e46843e2a3609..023032e679f219001de31470cb25f97410b823a9 100644
--- a/features/steps/snippets/snippets.rb
+++ b/features/steps/snippets/snippets.rb
@@ -13,7 +13,7 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps
   end
 
   step 'I click link "Edit"' do
-    page.within ".page-title" do
+    page.within ".detail-page-header" do
       click_link "Edit"
     end
   end
diff --git a/fixtures/emojis/aliases.json b/fixtures/emojis/aliases.json
new file mode 100644
index 0000000000000000000000000000000000000000..547ce7978b389ca4a5273cdbdbbcabb9bb42d275
--- /dev/null
+++ b/fixtures/emojis/aliases.json
@@ -0,0 +1,367 @@
+{  
+   "northeast_pointing_airplane":"airplane_northeast",
+   "small_airplane":"airplane_small",
+   "up_pointing_small_airplane":"airplane_small_up",
+   "up_pointing_airplane":"airplane_up",
+   "left_anger_bubble":"anger_left",
+   "right_anger_bubble":"anger_right",
+   "ballot_box_with_ballot":"ballot_box",
+   "ballot_box_with_bold_check":"ballot_box_check",
+   "ballot_box_with_script_x":"ballot_box_x",
+   "ballot_script_x":"ballot_x",
+   "beach_with_umbrella":"beach",
+   "bellhop_bell":"bellhop",
+   "bouquet_of_flowers":"bouquet2",
+   "bullhorn_with_sound_waves":"bullhorn_waves",
+   "pocket calculator":"calculator",
+   "spiral_calendar_pad":"calendar_spiral",
+   "card_file_box":"card_box",
+   "tape_cartridge":"cartridge",
+   "city_sunrise":"city_sunset",
+   "mantlepiece_clock":"clock",
+   "clockwise_right_and_left_semicircle_arrows":"clockwise_arrows",
+   "cloud_with_lightning":"cloud_lightning",
+   "cloud_with_rain":"cloud_rain",
+   "cloud_with_snow":"cloud_snow",
+   "cloud_with_tornado":"cloud_tornado",
+   "old_personal_computer":"computer_old",
+   "building_construction":"contruction_site",
+   "couch_and_lamp":"couch",
+   "couple_with_heart_mm":"couple_mm",
+   "couple_with_heart_ww":"couple_ww",
+   "lower_left_crayon":"crayon",
+   "heavy_latin_cross":"cross_heavy",
+   "white_latin_cross":"cross_white",
+   "black_skull_and_crossbones":"crossbones",
+   "passenger_ship":"cruise_ship",
+   "dagger_knife":"dagger",
+   "desktop_computer":"desktop",
+   "card_index_dividers":"dividers",
+   "document_with_text":"document_text",
+   "dove_of_peace":"dove",
+   "email":"e-mail",
+   "back_of_envelope":"envelope_back",
+   "flying_envelope":"envelope_flying",
+   "stamped_envelope":"envelope_stamped",
+   "pen_over_stamped_envelope":"envelope_stamped_pen",
+   "white_down_pointing_left_hand_index":"finger_pointing_down",
+   "sideways_white_down_pointing_index":"finger_pointing_down2",
+   "sideways_white_left_pointing_index":"finger_pointing_left",
+   "sideways_white_right_pointing_index":"finger_pointing_right",
+   "sideways_white_up_pointing_index":"finger_pointing_up",
+   "flame":"fire",
+   "oncoming_fire_engine":"fire_engine_oncoming",
+   "ac":"flag_ac",
+   "ad":"flag_ad",
+   "ae":"flag_ae",
+   "af":"flag_af",
+   "ag":"flag_ag",
+   "ai":"flag_ai",
+   "al":"flag_al",
+   "am":"flag_am",
+   "ao":"flag_ao",
+   "ar":"flag_ar",
+   "at":"flag_at",
+   "au":"flag_au",
+   "aw":"flag_aw",
+   "az":"flag_az",
+   "ba":"flag_ba",
+   "bb":"flag_bb",
+   "bd":"flag_bd",
+   "be":"flag_be",
+   "bf":"flag_bf",
+   "bg":"flag_bg",
+   "bh":"flag_bh",
+   "bi":"flag_bi",
+   "bj":"flag_bj",
+   "waving_black_flag":"flag_black",
+   "bm":"flag_bm",
+   "bn":"flag_bn",
+   "bo":"flag_bo",
+   "br":"flag_br",
+   "bs":"flag_bs",
+   "bt":"flag_bt",
+   "bw":"flag_bw",
+   "by":"flag_by",
+   "bz":"flag_bz",
+   "ca":"flag_ca",
+   "congo":"flag_cd",
+   "cf":"flag_cf",
+   "cg":"flag_cg",
+   "ch":"flag_ch",
+   "ci":"flag_ci",
+   "chile":"flag_cl",
+   "cm":"flag_cm",
+   "cn":"flag_cn",
+   "co":"flag_co",
+   "cr":"flag_cr",
+   "cu":"flag_cu",
+   "cv":"flag_cv",
+   "cy":"flag_cy",
+   "cz":"flag_cz",
+   "de":"flag_de",
+   "dj":"flag_dj",
+   "dk":"flag_dk",
+   "dm":"flag_dm",
+   "do":"flag_do",
+   "dz":"flag_dz",
+   "ec":"flag_ec",
+   "ee":"flag_ee",
+   "eg":"flag_eg",
+   "eh":"flag_eh",
+   "er":"flag_er",
+   "es":"flag_es",
+   "et":"flag_et",
+   "fi":"flag_fi",
+   "fj":"flag_fj",
+   "fk":"flag_fk",
+   "fm":"flag_fm",
+   "fo":"flag_fo",
+   "fr":"flag_fr",
+   "ga":"flag_ga",
+   "gb":"flag_gb",
+   "gd":"flag_gd",
+   "ge":"flag_ge",
+   "gh":"flag_gh",
+   "gi":"flag_gi",
+   "gl":"flag_gl",
+   "gm":"flag_gm",
+   "gn":"flag_gn",
+   "gq":"flag_gq",
+   "gr":"flag_gr",
+   "gt":"flag_gt",
+   "gu":"flag_gu",
+   "gw":"flag_gw",
+   "gy":"flag_gy",
+   "hk":"flag_hk",
+   "hn":"flag_hn",
+   "hr":"flag_hr",
+   "ht":"flag_ht",
+   "hu":"flag_hu",
+   "indonesia":"flag_id",
+   "ie":"flag_ie",
+   "il":"flag_il",
+   "in":"flag_in",
+   "iq":"flag_iq",
+   "ir":"flag_ir",
+   "is":"flag_is",
+   "it":"flag_it",
+   "je":"flag_je",
+   "jm":"flag_jm",
+   "jo":"flag_jo",
+   "jp":"flag_jp",
+   "ke":"flag_ke",
+   "kg":"flag_kg",
+   "kh":"flag_kh",
+   "ki":"flag_ki",
+   "km":"flag_km",
+   "kn":"flag_kn",
+   "kp":"flag_kp",
+   "kr":"flag_kr",
+   "kw":"flag_kw",
+   "ky":"flag_ky",
+   "kz":"flag_kz",
+   "la":"flag_la",
+   "lb":"flag_lb",
+   "lc":"flag_lc",
+   "li":"flag_li",
+   "lk":"flag_lk",
+   "lr":"flag_lr",
+   "ls":"flag_ls",
+   "lt":"flag_lt",
+   "lu":"flag_lu",
+   "lv":"flag_lv",
+   "ly":"flag_ly",
+   "ma":"flag_ma",
+   "mc":"flag_mc",
+   "md":"flag_md",
+   "me":"flag_me",
+   "mg":"flag_mg",
+   "mh":"flag_mh",
+   "mk":"flag_mk",
+   "ml":"flag_ml",
+   "mm":"flag_mm",
+   "mn":"flag_mn",
+   "mo":"flag_mo",
+   "mr":"flag_mr",
+   "ms":"flag_ms",
+   "mt":"flag_mt",
+   "mu":"flag_mu",
+   "mv":"flag_mv",
+   "mw":"flag_mw",
+   "mx":"flag_mx",
+   "my":"flag_my",
+   "mz":"flag_mz",
+   "na":"flag_na",
+   "nc":"flag_nc",
+   "ne":"flag_ne",
+   "nigeria":"flag_ng",
+   "ni":"flag_ni",
+   "nl":"flag_nl",
+   "no":"flag_no",
+   "np":"flag_np",
+   "nr":"flag_nr",
+   "nu":"flag_nu",
+   "nz":"flag_nz",
+   "om":"flag_om",
+   "pa":"flag_pa",
+   "pe":"flag_pe",
+   "pf":"flag_pf",
+   "pg":"flag_pg",
+   "ph":"flag_ph",
+   "pk":"flag_pk",
+   "pl":"flag_pl",
+   "pr":"flag_pr",
+   "ps":"flag_ps",
+   "pt":"flag_pt",
+   "pw":"flag_pw",
+   "py":"flag_py",
+   "qa":"flag_qa",
+   "ro":"flag_ro",
+   "rs":"flag_rs",
+   "ru":"flag_ru",
+   "rw":"flag_rw",
+   "saudiarabia":"flag_sa",
+   "saudi":"flag_sa",
+   "sb":"flag_sb",
+   "sc":"flag_sc",
+   "sd":"flag_sd",
+   "se":"flag_se",
+   "sg":"flag_sg",
+   "sh":"flag_sh",
+   "si":"flag_si",
+   "sk":"flag_sk",
+   "sl":"flag_sl",
+   "sm":"flag_sm",
+   "sn":"flag_sn",
+   "so":"flag_so",
+   "sr":"flag_sr",
+   "st":"flag_st",
+   "sv":"flag_sv",
+   "sy":"flag_sy",
+   "sz":"flag_sz",
+   "td":"flag_td",
+   "tg":"flag_tg",
+   "th":"flag_th",
+   "tj":"flag_tj",
+   "tl":"flag_tl",
+   "turkmenistan":"flag_tm",
+   "tn":"flag_tn",
+   "to":"flag_to",
+   "tr":"flag_tr",
+   "tt":"flag_tt",
+   "tuvalu":"flag_tv",
+   "tw":"flag_tw",
+   "tz":"flag_tz",
+   "ua":"flag_ua",
+   "ug":"flag_ug",
+   "us":"flag_us",
+   "uy":"flag_uy",
+   "uz":"flag_uz",
+   "va":"flag_va",
+   "vc":"flag_vc",
+   "ve":"flag_ve",
+   "vi":"flag_vi",
+   "vn":"flag_vn",
+   "vu":"flag_vu",
+   "wf":"flag_wf",
+   "waving_white_flag":"flag_white",
+   "ws":"flag_ws",
+   "xk":"flag_xk",
+   "ye":"flag_ye",
+   "za":"flag_za",
+   "zm":"flag_zm",
+   "zw":"flag_zw",
+   "clamshell_mobile_phone":"flip_phone",
+   "black_hard_shell_floppy_disk":"floppy_black",
+   "white_hard_shell_floppy_disk":"floppy_white",
+   "open_folder":"folder_open",
+   "fork_and_knife_with_plate":"fork_knife_plate",
+   "frame_with_picture":"frame_photo",
+   "frame_with_tiles":"frame_tiles",
+   "frame_with_an_x":"frame_x",
+   "anguished":"frowning",
+   "raised_hand_with_fingers_splayed":"hand_splayed",
+   "reversed_raised_hand_with_fingers_splayed":"hand_splayed_reverse",
+   "reversed_victory_hand":"hand_victory",
+   "heart_with_tip_on_the_left":"heart_tip",
+   "house_buildings":"homes",
+   "derelict_house_building":"house_abandoned",
+   "circled_information_source":"info",
+   "desert_island":"island",
+   "up_pointing_military_airplane":"jet_up",
+   "old_key":"key2",
+   "wired_keyboard":"keyboard",
+   "keyboard_and_mouse":"keyboard_mouse",
+   "musical_keyboard_with_jacks":"keyboard_with_jacks",
+   "couplekiss_mm":"kiss_mm",
+   "couplekiss_ww":"kiss_ww",
+   "satisfied":"laughing",
+   "left_hand_telephone_receiver":"left_receiver",
+   "man_in_business_suit_levitating":"levitate",
+   "weight_lifter":"lifter",
+   "light_mark":"light_check_mark",
+   "world_map":"map",
+   "sports_medal":"medal",
+   "studio_microphone":"microphone2",
+   "reversed_hand_with_middle_finger_extended":"middle_finger",
+   "lightning_mood_bubble":"mood_bubble_lightning",
+   "lightning_mood":"mood_lightning",
+   "racing_motorcycle":"motorcycle",
+   "snow_capped_mountain":"mountain_snow",
+   "one_button_mouse":"mouse_one",
+   "three_networked_computers":"network",
+   "rolled_up_newspaper":"newspaper2",
+   "note_page":"note",
+   "empty_note_page":"note_empty",
+   "note_pad":"notepad",
+   "empty_note_pad":"notepad_empty",
+   "spiral_note_pad":"notepad_spiral",
+   "oil_drum":"oil",
+   "grandma":"older_woman",
+   "optical_disc_icon":"optical_disk",
+   "lower_left_paintbrush":"paintbrush",
+   "linked_paperclips":"paperclips",
+   "national_park":"park",
+   "lower_left_ballpoint_pen":"pen_ballpoint",
+   "lower_left_fountain_pen":"pen_fountain",
+   "memo":"pencil",
+   "lower_left_pencil":"pencil3",
+   "black_pennant":"pennant_black",
+   "white_pennant":"pennant_white",
+   "no_piracy":"piracy",
+   "shit":"poop",
+   "hankey":"poop",
+   "poo":"poop",
+   "prohibited_sign":"prohibited",
+   "film_projector":"projector",
+   "racing_car":"race_car",
+   "railroad_track":"railway_track",
+   "right_speaker_with_one_sound_wave":"right_speaker_one",
+   "right_speaker_with_three_sound_waves":"right_speaker_three",
+   "skeleton":"skull",
+   "slightly_frowning_face":"slight_frown",
+   "slightly_smiling_face":"slight_smile",
+   "speaking_head_in_silhouette":"speaking_head",
+   "left_speech_bubble":"speech_left",
+   "right_speech_bubble":"speech_right",
+   "three_speech_bubbles":"speech_three",
+   "two_speech_bubbles":"speech_two",
+   "sleuth_or_spy":"spy",
+   "portable_stereo":"stereo",
+   "black_touchtone_telephone":"telephone_black",
+   "white_touchtone_telephone":"telephone_white",
+   "left_thought_bubble":"thought_left",
+   "right_thought_bubble":"thought_right",
+   "reversed_thumbs_down_sign":"thumbs_down_reverse",
+   "reversed_thumbs_up_sign":"thumbs_up_reverse",
+   "-1":"thumbsdown",
+   "+1":"thumbsup",
+   "admission_tickets":"tickets",
+   "hammer_and_wrench":"tools",
+   "diesel_locomotive":"train_diesel",
+   "triangle_with_rounded_corners":"triangle_round",
+   "turned_ok_hand_sign":"turned_ok_hand",
+   "raised_hand_with_part_between_middle_and_ring_fingers":"vulcan",
+   "left_writing_hand":"writing_hand"
+}
\ No newline at end of file
diff --git a/fixtures/emojis/index.json b/fixtures/emojis/index.json
new file mode 100644
index 0000000000000000000000000000000000000000..60ef2399e14de6b711aa4a5e0b92ce97ab1e791a
--- /dev/null
+++ b/fixtures/emojis/index.json
@@ -0,0 +1,13376 @@
+{
+  "100": {
+    "unicode": "1F4AF",
+    "unicode_alternates": [],
+    "name": "hundred points symbol",
+    "shortname": ":100:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["numbers", "perfect", "score", "100", "percent", "a", "plus", "perfect", "school", "quiz", "score", "test", "exam"],
+    "moji": "💯"
+  },
+  "1234": {
+    "unicode": "1F522",
+    "unicode_alternates": [],
+    "name": "input symbol for numbers",
+    "shortname": ":1234:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "numbers"],
+    "moji": "🔢"
+  },
+  "8ball": {
+    "unicode": "1F3B1",
+    "unicode_alternates": [],
+    "name": "billiards",
+    "shortname": ":8ball:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["pool", "billiards", "eight ball", "pool", "pocket ball", "cue"],
+    "moji": "🎱"
+  },
+  "a": {
+    "unicode": "1F170",
+    "unicode_alternates": [],
+    "name": "negative squared latin capital letter a",
+    "shortname": ":a:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "letter", "red-square"],
+    "moji": "🅰"
+  },
+  "ab": {
+    "unicode": "1F18E",
+    "unicode_alternates": [],
+    "name": "negative squared ab",
+    "shortname": ":ab:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "red-square"],
+    "moji": "🆎"
+  },
+  "abc": {
+    "unicode": "1F524",
+    "unicode_alternates": [],
+    "name": "input symbol for latin letters",
+    "shortname": ":abc:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "blue-square"],
+    "moji": "🔤"
+  },
+  "abcd": {
+    "unicode": "1F521",
+    "unicode_alternates": [],
+    "name": "input symbol for latin small letters",
+    "shortname": ":abcd:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "blue-square"],
+    "moji": "🔡"
+  },
+  "accept": {
+    "unicode": "1F251",
+    "unicode_alternates": [],
+    "name": "circled ideograph accept",
+    "shortname": ":accept:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["agree", "chinese", "good", "kanji", "ok", "yes"],
+    "moji": "🉑"
+  },
+  "aerial_tramway": {
+    "unicode": "1F6A1",
+    "unicode_alternates": [],
+    "name": "aerial tramway",
+    "shortname": ":aerial_tramway:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "aerial", "tram", "tramway", "cable", "transport"],
+    "moji": "🚡"
+  },
+  "airplane": {
+    "unicode": "2708",
+    "unicode_alternates": ["2708-FE0F"],
+    "name": "airplane",
+    "shortname": ":airplane:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flight", "transportation", "vehicle", "airplane", "plane", "airport", "travel", "airlines", "fly", "jet", "jumbo", "boeing", "airbus"],
+    "moji": "✈"
+  },
+  "airplane_arriving": {
+    "unicode": "1F6EC",
+    "unicode_alternates": [],
+    "name": "airplane arriving",
+    "shortname": ":airplane_arriving:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flight", "transportation", "vehicle", "plane", "airport", "travel", "airlines", "fly", "jet", "jumbo", "boeing", "airbus"]
+  },
+  "airplane_departure": {
+    "unicode": "1F6EB",
+    "unicode_alternates": [],
+    "name": "airplane departure",
+    "shortname": ":airplane_departure:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flight", "transportation", "vehicle", "plane", "airport", "travel", "airlines", "fly", "jet", "jumbo", "boeing", "airbus", "leaving"]
+  },
+  "airplane_northeast": {
+    "unicode": "1F6EA",
+    "unicode_alternates": [],
+    "name": "northeast-pointing airplane",
+    "shortname": ":airplane_northeast:",
+    "category": "travel_places",
+    "aliases": [":northeast_pointing_airplane:"],
+    "aliases_ascii": [],
+    "keywords": ["plane", "travel"]
+  },
+  "airplane_small": {
+    "unicode": "1F6E9",
+    "unicode_alternates": [],
+    "name": "small airplane",
+    "shortname": ":airplane_small:",
+    "category": "travel_places",
+    "aliases": [":small_airplane:"],
+    "aliases_ascii": [],
+    "keywords": ["flight", "transportation", "vehicle", "plane", "airport", "travel", "airlines", "fly", "jet", "jumbo", "boeing", "airbus"]
+  },
+  "airplane_small_up": {
+    "unicode": "1F6E8",
+    "unicode_alternates": [],
+    "name": "up-pointing small airplane",
+    "shortname": ":airplane_small_up:",
+    "category": "travel_places",
+    "aliases": [":up_pointing_small_airplane:"],
+    "aliases_ascii": [],
+    "keywords": ["plane", "travel"]
+  },
+  "airplane_up": {
+    "unicode": "1F6E7",
+    "unicode_alternates": [],
+    "name": "up-pointing airplane",
+    "shortname": ":airplane_up:",
+    "category": "travel_places",
+    "aliases": [":up_pointing_airplane:"],
+    "aliases_ascii": [],
+    "keywords": ["plane", "travel"]
+  },
+  "alarm_clock": {
+    "unicode": "23F0",
+    "unicode_alternates": [],
+    "name": "alarm clock",
+    "shortname": ":alarm_clock:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["time", "wake"],
+    "moji": "⏰"
+  },
+  "alien": {
+    "unicode": "1F47D",
+    "unicode_alternates": [],
+    "name": "extraterrestrial alien",
+    "shortname": ":alien:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["UFO", "paul", "alien", "ufo"],
+    "moji": "👽"
+  },
+  "ambulance": {
+    "unicode": "1F691",
+    "unicode_alternates": [],
+    "name": "ambulance",
+    "shortname": ":ambulance:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["911", "health", "ambulance", "emergency", "medical", "help", "assistance"],
+    "moji": "🚑"
+  },
+  "anchor": {
+    "unicode": "2693",
+    "unicode_alternates": ["2693-FE0F"],
+    "name": "anchor",
+    "shortname": ":anchor:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["ferry", "ship", "anchor", "ship", "boat", "ocean", "harbor", "marina", "shipyard", "sailor", "tattoo"],
+    "moji": "âš“"
+  },
+  "angel": {
+    "unicode": "1F47C",
+    "unicode_alternates": [],
+    "name": "baby angel",
+    "shortname": ":angel:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["baby", "angel", "halo", "cupid", "wings", "halo", "heaven", "wings", "jesus"],
+    "moji": "👼"
+  },
+  "anger": {
+    "unicode": "1F4A2",
+    "unicode_alternates": [],
+    "name": "anger symbol",
+    "shortname": ":anger:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["anger", "angry", "mad"],
+    "moji": "💢"
+  },
+  "anger_left": {
+    "unicode": "1F5EE",
+    "unicode_alternates": [],
+    "name": "left anger bubble",
+    "shortname": ":anger_left:",
+    "category": "objects_symbols",
+    "aliases": [":left_anger_bubble:"],
+    "aliases_ascii": [],
+    "keywords": ["speech", "balloon", "talk", "mood", "conversation", "communication", "comic", "angry"]
+  },
+  "anger_right": {
+    "unicode": "1F5EF",
+    "unicode_alternates": [],
+    "name": "right anger bubble",
+    "shortname": ":anger_right:",
+    "category": "objects_symbols",
+    "aliases": [":right_anger_bubble:"],
+    "aliases_ascii": [],
+    "keywords": ["speech", "balloon", "talk", "mood", "conversation", "communication", "comic", "angry"]
+  },
+  "angry": {
+    "unicode": "1F620",
+    "unicode_alternates": [],
+    "name": "angry face",
+    "shortname": ":angry:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [">:(", ">:-(", ":@"],
+    "keywords": ["angry", "livid", "mad", "vexed", "irritated", "annoyed", "face", "frustrated", "mad"],
+    "moji": "😠"
+  },
+  "anguished": {
+    "unicode": "1F627",
+    "unicode_alternates": [],
+    "name": "anguished face",
+    "shortname": ":anguished:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "nervous", "stunned", "pain", "anguish", "ouch", "misery", "distress", "grief"],
+    "moji": "😧"
+  },
+  "ant": {
+    "unicode": "1F41C",
+    "unicode_alternates": [],
+    "name": "ant",
+    "shortname": ":ant:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "insect", "ant", "queen", "insect", "team"],
+    "moji": "🐜"
+  },
+  "apple": {
+    "unicode": "1F34E",
+    "unicode_alternates": [],
+    "name": "red apple",
+    "shortname": ":apple:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fruit", "mac", "apple", "fruit", "electronics", "red", "doctor", "teacher", "school", "core"],
+    "moji": "🍎"
+  },
+  "aquarius": {
+    "unicode": "2652",
+    "unicode_alternates": ["2652-FE0F"],
+    "name": "aquarius",
+    "shortname": ":aquarius:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["aquarius", "water", "bearer", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "purple-square", "sign", "zodiac", "horoscope"],
+    "moji": "â™’"
+  },
+  "aries": {
+    "unicode": "2648",
+    "unicode_alternates": ["2648-FE0F"],
+    "name": "aries",
+    "shortname": ":aries:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["aries", "ram", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "purple-square", "sign", "zodiac", "horoscope"],
+    "moji": "♈"
+  },
+  "arrow_backward": {
+    "unicode": "25C0",
+    "unicode_alternates": ["25C0-FE0F"],
+    "name": "black left-pointing triangle",
+    "shortname": ":arrow_backward:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "â—€"
+  },
+  "arrow_double_down": {
+    "unicode": "23EC",
+    "unicode_alternates": [],
+    "name": "black down-pointing double triangle",
+    "shortname": ":arrow_double_down:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "⏬"
+  },
+  "arrow_double_up": {
+    "unicode": "23EB",
+    "unicode_alternates": [],
+    "name": "black up-pointing double triangle",
+    "shortname": ":arrow_double_up:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "⏫"
+  },
+  "arrow_down": {
+    "unicode": "2B07",
+    "unicode_alternates": ["2B07-FE0F"],
+    "name": "downwards black arrow",
+    "shortname": ":arrow_down:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "⬇"
+  },
+  "arrow_down_small": {
+    "unicode": "1F53D",
+    "unicode_alternates": [],
+    "name": "down-pointing small red triangle",
+    "shortname": ":arrow_down_small:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "🔽"
+  },
+  "arrow_forward": {
+    "unicode": "25B6",
+    "unicode_alternates": ["25B6-FE0F"],
+    "name": "black right-pointing triangle",
+    "shortname": ":arrow_forward:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "â–¶"
+  },
+  "arrow_heading_down": {
+    "unicode": "2935",
+    "unicode_alternates": ["2935-FE0F"],
+    "name": "arrow pointing rightwards then curving downwards",
+    "shortname": ":arrow_heading_down:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "⤵"
+  },
+  "arrow_heading_up": {
+    "unicode": "2934",
+    "unicode_alternates": ["2934-FE0F"],
+    "name": "arrow pointing rightwards then curving upwards",
+    "shortname": ":arrow_heading_up:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "⤴"
+  },
+  "arrow_left": {
+    "unicode": "2B05",
+    "unicode_alternates": ["2B05-FE0F"],
+    "name": "leftwards black arrow",
+    "shortname": ":arrow_left:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square", "previous"],
+    "moji": "⬅"
+  },
+  "arrow_lower_left": {
+    "unicode": "2199",
+    "unicode_alternates": ["2199-FE0F"],
+    "name": "south west arrow",
+    "shortname": ":arrow_lower_left:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "↙"
+  },
+  "arrow_lower_right": {
+    "unicode": "2198",
+    "unicode_alternates": ["2198-FE0F"],
+    "name": "south east arrow",
+    "shortname": ":arrow_lower_right:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "blue-square"],
+    "moji": "↘"
+  },
+  "arrow_right": {
+    "unicode": "27A1",
+    "unicode_alternates": ["27A1-FE0F"],
+    "name": "black rightwards arrow",
+    "shortname": ":arrow_right:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "next"],
+    "moji": "âž¡"
+  },
+  "arrow_right_hook": {
+    "unicode": "21AA",
+    "unicode_alternates": ["21AA-FE0F"],
+    "name": "rightwards arrow with hook",
+    "shortname": ":arrow_right_hook:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "↪"
+  },
+  "arrow_up": {
+    "unicode": "2B06",
+    "unicode_alternates": ["2B06-FE0F"],
+    "name": "upwards black arrow",
+    "shortname": ":arrow_up:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "⬆"
+  },
+  "arrow_up_down": {
+    "unicode": "2195",
+    "unicode_alternates": ["2195-FE0F"],
+    "name": "up down arrow",
+    "shortname": ":arrow_up_down:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "↕"
+  },
+  "arrow_up_small": {
+    "unicode": "1F53C",
+    "unicode_alternates": [],
+    "name": "up-pointing small red triangle",
+    "shortname": ":arrow_up_small:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "🔼"
+  },
+  "arrow_upper_left": {
+    "unicode": "2196",
+    "unicode_alternates": ["2196-FE0F"],
+    "name": "north west arrow",
+    "shortname": ":arrow_upper_left:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "↖"
+  },
+  "arrow_upper_right": {
+    "unicode": "2197",
+    "unicode_alternates": ["2197-FE0F"],
+    "name": "north east arrow",
+    "shortname": ":arrow_upper_right:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "↗"
+  },
+  "arrows_clockwise": {
+    "unicode": "1F503",
+    "unicode_alternates": [],
+    "name": "clockwise downwards and upwards open circle arrows",
+    "shortname": ":arrows_clockwise:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sync"],
+    "moji": "🔃"
+  },
+  "arrows_counterclockwise": {
+    "unicode": "1F504",
+    "unicode_alternates": [],
+    "name": "anticlockwise downwards and upwards open circle ar",
+    "shortname": ":arrows_counterclockwise:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "sync"],
+    "moji": "🔄"
+  },
+  "art": {
+    "unicode": "1F3A8",
+    "unicode_alternates": [],
+    "name": "artist palette",
+    "shortname": ":art:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["design", "draw", "paint", "artist", "palette", "art", "colors", "paint", "draw", "brush", "pastels", "oils"],
+    "moji": "🎨"
+  },
+  "articulated_lorry": {
+    "unicode": "1F69B",
+    "unicode_alternates": [],
+    "name": "articulated lorry",
+    "shortname": ":articulated_lorry:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cars", "transportation", "vehicle", "truck", "delivery", "semi", "lorry", "articulated"],
+    "moji": "🚛"
+  },
+  "ascending_notes": {
+    "unicode": "1F39C",
+    "unicode_alternates": [],
+    "name": "beamed ascending musical notes",
+    "shortname": ":ascending_notes:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["score", "music", "sound", "tone"]
+  },
+  "astonished": {
+    "unicode": "1F632",
+    "unicode_alternates": [],
+    "name": "astonished face",
+    "shortname": ":astonished:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "xox", "shocked", "surprise", "astonished"],
+    "moji": "😲"
+  },
+  "athletic_shoe": {
+    "unicode": "1F45F",
+    "unicode_alternates": [],
+    "name": "athletic shoe",
+    "shortname": ":athletic_shoe:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shoes", "sports"],
+    "moji": "👟"
+  },
+  "atm": {
+    "unicode": "1F3E7",
+    "unicode_alternates": [],
+    "name": "automated teller machine",
+    "shortname": ":atm:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["atm", "cash", "withdrawal", "money", "deposit", "financial", "bank", "adam", "payday", "bank", "blue-square", "cash", "money", "payment"],
+    "moji": "🏧"
+  },
+  "b": {
+    "unicode": "1F171",
+    "unicode_alternates": [],
+    "name": "negative squared latin capital letter b",
+    "shortname": ":b:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "letter", "red-square"],
+    "moji": "🅱"
+  },
+  "baby": {
+    "unicode": "1F476",
+    "unicode_alternates": [],
+    "name": "baby",
+    "shortname": ":baby:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["boy", "child", "infant"],
+    "moji": "👶"
+  },
+  "baby_bottle": {
+    "unicode": "1F37C",
+    "unicode_alternates": [],
+    "name": "baby bottle",
+    "shortname": ":baby_bottle:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["container", "food", "baby", "bottle", "milk", "mother", "nipple", "newborn", "formula"],
+    "moji": "🍼"
+  },
+  "baby_chick": {
+    "unicode": "1F424",
+    "unicode_alternates": [],
+    "name": "baby chick",
+    "shortname": ":baby_chick:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "chicken", "chick", "baby", "bird", "chicken", "young", "woman", "cute"],
+    "moji": "🐤"
+  },
+  "baby_symbol": {
+    "unicode": "1F6BC",
+    "unicode_alternates": [],
+    "name": "baby symbol",
+    "shortname": ":baby_symbol:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["child", "orange-square", "baby", "crawl", "newborn", "human", "diaper", "small", "babe"],
+    "moji": "🚼"
+  },
+  "back": {
+    "unicode": "1F519",
+    "unicode_alternates": [],
+    "name": "back with leftwards arrow above",
+    "shortname": ":back:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow"],
+    "moji": "🔙"
+  },
+  "baggage_claim": {
+    "unicode": "1F6C4",
+    "unicode_alternates": [],
+    "name": "baggage claim",
+    "shortname": ":baggage_claim:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["airport", "blue-square", "transport", "bag", "baggage", "luggage", "travel"],
+    "moji": "🛄"
+  },
+  "balloon": {
+    "unicode": "1F388",
+    "unicode_alternates": [],
+    "name": "balloon",
+    "shortname": ":balloon:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["celebration", "party", "balloon", "birthday", "celebration", "helium", "gas", "children", "float"],
+    "moji": "🎈"
+  },
+  "ballot_box": {
+    "unicode": "1F5F3",
+    "unicode_alternates": [],
+    "name": "ballot box with ballot",
+    "shortname": ":ballot_box:",
+    "category": "objects_symbols",
+    "aliases": [":ballot_box_with_ballot:"],
+    "aliases_ascii": [],
+    "keywords": ["vote"]
+  },
+  "ballot_box_check": {
+    "unicode": "1F5F9",
+    "unicode_alternates": [],
+    "name": "ballot box with bold check",
+    "shortname": ":ballot_box_check:",
+    "category": "objects_symbols",
+    "aliases": [":ballot_box_with_bold_check:"],
+    "aliases_ascii": [],
+    "keywords": ["mark", "vote"]
+  },
+  "ballot_box_with_check": {
+    "unicode": "2611",
+    "unicode_alternates": ["2611-FE0F"],
+    "name": "ballot box with check",
+    "shortname": ":ballot_box_with_check:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["agree", "ok"],
+    "moji": "☑"
+  },
+  "ballot_box_x": {
+    "unicode": "1F5F5",
+    "unicode_alternates": [],
+    "name": "ballot box with script x",
+    "shortname": ":ballot_box_x:",
+    "category": "objects_symbols",
+    "aliases": [":ballot_box_with_script_x:"],
+    "aliases_ascii": [],
+    "keywords": ["mark", "vote"]
+  },
+  "ballot_x": {
+    "unicode": "1F5F4",
+    "unicode_alternates": [],
+    "name": "ballot script x",
+    "shortname": ":ballot_x:",
+    "category": "objects_symbols",
+    "aliases": [":ballot_script_x:"],
+    "aliases_ascii": [],
+    "keywords": ["mark", "vote"]
+  },
+  "bamboo": {
+    "unicode": "1F38D",
+    "unicode_alternates": [],
+    "name": "pine decoration",
+    "shortname": ":bamboo:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "plant", "vegetable", "pine", "bamboo", "decoration", "new", "years", "spirits", "harvest", "prosperity", "longevity", "fortune", "luck", "welcome", "farming", "agriculture"],
+    "moji": "🎍"
+  },
+  "banana": {
+    "unicode": "1F34C",
+    "unicode_alternates": [],
+    "name": "banana",
+    "shortname": ":banana:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "banana", "peel", "bunch"],
+    "moji": "🍌"
+  },
+  "bangbang": {
+    "unicode": "203C",
+    "unicode_alternates": ["203C-FE0F"],
+    "name": "double exclamation mark",
+    "shortname": ":bangbang:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["exclamation", "surprise"],
+    "moji": "‼"
+  },
+  "bank": {
+    "unicode": "1F3E6",
+    "unicode_alternates": [],
+    "name": "bank",
+    "shortname": ":bank:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building"],
+    "moji": "🏦"
+  },
+  "bar_chart": {
+    "unicode": "1F4CA",
+    "unicode_alternates": [],
+    "name": "bar chart",
+    "shortname": ":bar_chart:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["graph", "presentation", "stats"],
+    "moji": "📊"
+  },
+  "barber": {
+    "unicode": "1F488",
+    "unicode_alternates": [],
+    "name": "barber pole",
+    "shortname": ":barber:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["hair", "salon", "style"],
+    "moji": "💈"
+  },
+  "baseball": {
+    "unicode": "26BE",
+    "unicode_alternates": ["26BE-FE0F"],
+    "name": "baseball",
+    "shortname": ":baseball:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["MLB", "balls", "sports"],
+    "moji": "âš¾"
+  },
+  "basketball": {
+    "unicode": "1F3C0",
+    "unicode_alternates": [],
+    "name": "basketball and hoop",
+    "shortname": ":basketball:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["NBA", "balls", "sports", "basketball", "bball", "dribble", "hoop", "net", "swish", "rip city"],
+    "moji": "🏀"
+  },
+  "bath": {
+    "unicode": "1F6C0",
+    "unicode_alternates": [],
+    "name": "bath",
+    "shortname": ":bath:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clean", "shower", "bath", "tub", "basin", "wash", "bubble", "soak", "bathroom", "soap", "water", "clean", "shampoo", "lather", "water"],
+    "moji": "🛀"
+  },
+  "bathtub": {
+    "unicode": "1F6C1",
+    "unicode_alternates": [],
+    "name": "bathtub",
+    "shortname": ":bathtub:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clean", "shower", "bath", "tub", "basin", "wash", "bubble", "soak", "bathroom", "soap", "water", "clean", "shampoo", "lather", "water"],
+    "moji": "🛁"
+  },
+  "battery": {
+    "unicode": "1F50B",
+    "unicode_alternates": [],
+    "name": "battery",
+    "shortname": ":battery:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["energy", "power", "sustain"],
+    "moji": "🔋"
+  },
+  "beach": {
+    "unicode": "1F3D6",
+    "unicode_alternates": [],
+    "name": "beach with umbrella",
+    "shortname": ":beach:",
+    "category": "travel_places",
+    "aliases": [":beach_with_umbrella:"],
+    "aliases_ascii": [],
+    "keywords": ["sand", "sun", "surf", "vacation", "relaxation", "tanning", "tan", "swimming"]
+  },
+  "bear": {
+    "unicode": "1F43B",
+    "unicode_alternates": [],
+    "name": "bear face",
+    "shortname": ":bear:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐻"
+  },
+  "bed": {
+    "unicode": "1F6CF",
+    "unicode_alternates": [],
+    "name": "bed",
+    "shortname": ":bed:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sleep", "sex", "queen", "full", "twin", "king", "mattress"]
+  },
+  "bee": {
+    "unicode": "1F41D",
+    "unicode_alternates": [],
+    "name": "honeybee",
+    "shortname": ":bee:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "insect", "bee", "queen", "buzz", "flower", "pollen", "sting", "honey", "hive", "bumble", "pollination"],
+    "moji": "🐝"
+  },
+  "beer": {
+    "unicode": "1F37A",
+    "unicode_alternates": [],
+    "name": "beer mug",
+    "shortname": ":beer:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["beverage", "drink", "drunk", "party", "pub", "relax", "beer", "hops", "mug", "barley", "malt", "yeast", "portland", "oregon", "brewery", "micro", "pint", "boot"],
+    "moji": "🍺"
+  },
+  "beers": {
+    "unicode": "1F37B",
+    "unicode_alternates": [],
+    "name": "clinking beer mugs",
+    "shortname": ":beers:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["beverage", "drink", "drunk", "party", "pub", "relax", "beer", "beers", "cheers", "mug", "toast", "celebrate", "pub", "bar", "jolly", "hops", "clink"],
+    "moji": "🍻"
+  },
+  "beetle": {
+    "unicode": "1F41E",
+    "unicode_alternates": [],
+    "name": "lady beetle",
+    "shortname": ":beetle:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["insect", "nature", "lady", "bug", "ladybug", "ladybird", "beetle", "cow", "lady cow", "insect", "endearment"],
+    "moji": "🐞"
+  },
+  "beginner": {
+    "unicode": "1F530",
+    "unicode_alternates": [],
+    "name": "japanese symbol for beginner",
+    "shortname": ":beginner:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["badge", "shield"],
+    "moji": "🔰"
+  },
+  "bell": {
+    "unicode": "1F514",
+    "unicode_alternates": [],
+    "name": "bell",
+    "shortname": ":bell:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chime", "christmas", "notification", "sound", "xmas"],
+    "moji": "🔔"
+  },
+  "bellhop": {
+    "unicode": "1F6CE",
+    "unicode_alternates": [],
+    "name": "bellhop bell",
+    "shortname": ":bellhop:",
+    "category": "travel_places",
+    "aliases": [":bellhop_bell:"],
+    "aliases_ascii": [],
+    "keywords": ["hotel", "porter", "ding"]
+  },
+  "bento": {
+    "unicode": "1F371",
+    "unicode_alternates": [],
+    "name": "bento box",
+    "shortname": ":bento:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["box", "food", "japanese", "bento", "japanese", "rice", "meal", "box", "obento", "convenient", "lunchbox"],
+    "moji": "🍱"
+  },
+  "bicyclist": {
+    "unicode": "1F6B4",
+    "unicode_alternates": [],
+    "name": "bicyclist",
+    "shortname": ":bicyclist:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bike", "exercise", "hipster", "sports", "bicyclist", "road", "bike", "pedal", "bicycle", "transportation"],
+    "moji": "🚴"
+  },
+  "bike": {
+    "unicode": "1F6B2",
+    "unicode_alternates": [],
+    "name": "bicycle",
+    "shortname": ":bike:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bicycle", "exercise", "hipster", "sports", "bike", "pedal", "bicycle", "transportation"],
+    "moji": "🚲"
+  },
+  "bikini": {
+    "unicode": "1F459",
+    "unicode_alternates": [],
+    "name": "bikini",
+    "shortname": ":bikini:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["beach", "fashion", "female", "girl", "swimming", "woman"],
+    "moji": "👙"
+  },
+  "bird": {
+    "unicode": "1F426",
+    "unicode_alternates": [],
+    "name": "bird",
+    "shortname": ":bird:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "fly", "nature", "tweet"],
+    "moji": "🐦"
+  },
+  "birthday": {
+    "unicode": "1F382",
+    "unicode_alternates": [],
+    "name": "birthday cake",
+    "shortname": ":birthday:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cake", "party", "birthday", "birth", "cake", "dessert", "wish", "celebrate"],
+    "moji": "🎂"
+  },
+  "black_circle": {
+    "unicode": "26AB",
+    "unicode_alternates": ["26AB-FE0F"],
+    "name": "medium black circle",
+    "shortname": ":black_circle:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "âš«"
+  },
+  "black_joker": {
+    "unicode": "1F0CF",
+    "unicode_alternates": [],
+    "name": "playing card black joker",
+    "shortname": ":black_joker:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cards", "game", "poker"],
+    "moji": "🃏"
+  },
+  "black_large_square": {
+    "unicode": "2B1B",
+    "unicode_alternates": ["2B1B-FE0F"],
+    "name": "black large square",
+    "shortname": ":black_large_square:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "⬛"
+  },
+  "black_medium_small_square": {
+    "unicode": "25FE",
+    "unicode_alternates": ["25FE-FE0F"],
+    "name": "black medium small square",
+    "shortname": ":black_medium_small_square:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": [],
+    "moji": "â—¾"
+  },
+  "black_medium_square": {
+    "unicode": "25FC",
+    "unicode_alternates": ["25FC-FE0F"],
+    "name": "black medium square",
+    "shortname": ":black_medium_square:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "â—¼"
+  },
+  "black_nib": {
+    "unicode": "2712",
+    "unicode_alternates": ["2712-FE0F"],
+    "name": "black nib",
+    "shortname": ":black_nib:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["pen", "stationery"],
+    "moji": "✒"
+  },
+  "black_small_square": {
+    "unicode": "25AA",
+    "unicode_alternates": ["25AA-FE0F"],
+    "name": "black small square",
+    "shortname": ":black_small_square:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": [],
+    "moji": "â–ª"
+  },
+  "black_square_button": {
+    "unicode": "1F532",
+    "unicode_alternates": [],
+    "name": "black square button",
+    "shortname": ":black_square_button:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["frame"],
+    "moji": "🔲"
+  },
+  "blossom": {
+    "unicode": "1F33C",
+    "unicode_alternates": [],
+    "name": "blossom",
+    "shortname": ":blossom:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flowers", "nature", "yellow", "blossom", "daisy", "flower"],
+    "moji": "🌼"
+  },
+  "blowfish": {
+    "unicode": "1F421",
+    "unicode_alternates": [],
+    "name": "blowfish",
+    "shortname": ":blowfish:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "nature", "ocean", "sea", "blowfish", "pufferfish", "puffer", "ballonfish", "toadfish", "fugu fish", "sushi"],
+    "moji": "🐡"
+  },
+  "blue_book": {
+    "unicode": "1F4D8",
+    "unicode_alternates": [],
+    "name": "blue book",
+    "shortname": ":blue_book:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["knowledge", "library", "read"],
+    "moji": "📘"
+  },
+  "blue_car": {
+    "unicode": "1F699",
+    "unicode_alternates": [],
+    "name": "recreational vehicle",
+    "shortname": ":blue_car:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["car", "suv", "car", "wagon", "automobile"],
+    "moji": "🚙"
+  },
+  "blue_heart": {
+    "unicode": "1F499",
+    "unicode_alternates": [],
+    "name": "blue heart",
+    "shortname": ":blue_heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines", "blue", "heart", "love", "stability", "truth", "loyalty", "trust"],
+    "moji": "💙"
+  },
+  "blush": {
+    "unicode": "1F60A",
+    "unicode_alternates": [],
+    "name": "smiling face with smiling eyes",
+    "shortname": ":blush:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["crush", "embarrassed", "face", "flushed", "happy", "shy", "smile", "smiling", "smile", "smiley"],
+    "moji": "😊"
+  },
+  "boar": {
+    "unicode": "1F417",
+    "unicode_alternates": [],
+    "name": "boar",
+    "shortname": ":boar:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐗"
+  },
+  "bomb": {
+    "unicode": "1F4A3",
+    "unicode_alternates": [],
+    "name": "bomb",
+    "shortname": ":bomb:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["boom", "explode"],
+    "moji": "💣"
+  },
+  "book": {
+    "unicode": "1F4D6",
+    "unicode_alternates": [],
+    "name": "open book",
+    "shortname": ":book:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["library", "literature"],
+    "moji": "📖"
+  },
+  "book2": {
+    "unicode": "1F56E",
+    "unicode_alternates": [],
+    "name": "book",
+    "shortname": ":book2:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["library", "literature", "novel", "reading", "story"]
+  },
+  "bookmark": {
+    "unicode": "1F516",
+    "unicode_alternates": [],
+    "name": "bookmark",
+    "shortname": ":bookmark:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["favorite"],
+    "moji": "🔖"
+  },
+  "bookmark_tabs": {
+    "unicode": "1F4D1",
+    "unicode_alternates": [],
+    "name": "bookmark tabs",
+    "shortname": ":bookmark_tabs:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["favorite"],
+    "moji": "📑"
+  },
+  "books": {
+    "unicode": "1F4DA",
+    "unicode_alternates": [],
+    "name": "books",
+    "shortname": ":books:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["library", "literature"],
+    "moji": "📚"
+  },
+  "boom": {
+    "unicode": "1F4A5",
+    "unicode_alternates": [],
+    "name": "collision symbol",
+    "shortname": ":boom:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bomb", "explode", "explosion", "boom", "bang", "collision", "fire", "emphasis", "wow", "bam"],
+    "moji": "💥"
+  },
+  "boot": {
+    "unicode": "1F462",
+    "unicode_alternates": [],
+    "name": "womans boots",
+    "shortname": ":boot:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fashion", "shoes"],
+    "moji": "👢"
+  },
+  "bouquet": {
+    "unicode": "1F490",
+    "unicode_alternates": [],
+    "name": "bouquet",
+    "shortname": ":bouquet:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flowers", "nature"],
+    "moji": "💐"
+  },
+  "bouquet2": {
+    "unicode": "1F395",
+    "unicode_alternates": [],
+    "name": "bouquet of flowers",
+    "shortname": ":bouquet2:",
+    "category": "celebration",
+    "aliases": [":bouquet_of_flowers:"],
+    "aliases_ascii": [],
+    "keywords": ["nature", "marriage", "wedding", "bride"]
+  },
+  "bow": {
+    "unicode": "1F647",
+    "unicode_alternates": [],
+    "name": "person bowing deeply",
+    "shortname": ":bow:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["boy", "male", "man", "sorry", "bow", "respect", "curtsy", "bend"],
+    "moji": "🙇"
+  },
+  "bowling": {
+    "unicode": "1F3B3",
+    "unicode_alternates": [],
+    "name": "bowling",
+    "shortname": ":bowling:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fun", "play", "sports", "bowl", "bowling", "ball", "pin", "strike", "spare", "game"],
+    "moji": "🎳"
+  },
+  "boy": {
+    "unicode": "1F466",
+    "unicode_alternates": [],
+    "name": "boy",
+    "shortname": ":boy:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["guy", "male", "man"],
+    "moji": "👦"
+  },
+  "boys_symbol": {
+    "unicode": "1F6C9",
+    "unicode_alternates": [],
+    "name": "boys symbol",
+    "shortname": ":boys_symbol:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["male", "child"]
+  },
+  "bread": {
+    "unicode": "1F35E",
+    "unicode_alternates": [],
+    "name": "bread",
+    "shortname": ":bread:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["breakfast", "food", "toast", "wheat", "bread", "loaf", "yeast"],
+    "moji": "🍞"
+  },
+  "bride_with_veil": {
+    "unicode": "1F470",
+    "unicode_alternates": [],
+    "name": "bride with veil",
+    "shortname": ":bride_with_veil:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["couple", "marriage", "wedding", "bride", "wedding", "planning", "veil", "gown", "dress", "engagement", "white"],
+    "moji": "👰"
+  },
+  "bridge_at_night": {
+    "unicode": "1F309",
+    "unicode_alternates": [],
+    "name": "bridge at night",
+    "shortname": ":bridge_at_night:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["photo", "sanfrancisco", "bridge", "night", "water", "road", "evening", "suspension", "golden", "gate"],
+    "moji": "🌉"
+  },
+  "briefcase": {
+    "unicode": "1F4BC",
+    "unicode_alternates": [],
+    "name": "briefcase",
+    "shortname": ":briefcase:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["business", "documents", "work"],
+    "moji": "💼"
+  },
+  "broken_heart": {
+    "unicode": "1F494",
+    "unicode_alternates": [],
+    "name": "broken heart",
+    "shortname": ":broken_heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["</3"],
+    "keywords": ["sad", "sorry"],
+    "moji": "💔"
+  },
+  "bug": {
+    "unicode": "1F41B",
+    "unicode_alternates": [],
+    "name": "bug",
+    "shortname": ":bug:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["insect", "nature", "bug", "insect", "virus", "error"],
+    "moji": "🐛"
+  },
+  "bulb": {
+    "unicode": "1F4A1",
+    "unicode_alternates": [],
+    "name": "electric light bulb",
+    "shortname": ":bulb:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["electricity", "light", "idea", "bulb", "light"],
+    "moji": "💡"
+  },
+  "bullettrain_front": {
+    "unicode": "1F685",
+    "unicode_alternates": [],
+    "name": "high-speed train with bullet nose",
+    "shortname": ":bullettrain_front:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "train", "bullet", "rail"],
+    "moji": "🚅"
+  },
+  "bullettrain_side": {
+    "unicode": "1F684",
+    "unicode_alternates": [],
+    "name": "high-speed train",
+    "shortname": ":bullettrain_side:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "train", "bullet", "rail"],
+    "moji": "🚄"
+  },
+  "bullhorn": {
+    "unicode": "1F56B",
+    "unicode_alternates": [],
+    "name": "bullhorn",
+    "shortname": ":bullhorn:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sound", "noise", "announcement", "megaphone"]
+  },
+  "bullhorn_waves": {
+    "unicode": "1F56C",
+    "unicode_alternates": [],
+    "name": "bullhorn with sound waves",
+    "shortname": ":bullhorn_waves:",
+    "category": "objects_symbols",
+    "aliases": [":bullhorn_with_sound_waves:"],
+    "aliases_ascii": [],
+    "keywords": ["sound", "noise", "announcement", "megaphone"]
+  },
+  "bus": {
+    "unicode": "1F68C",
+    "unicode_alternates": [],
+    "name": "bus",
+    "shortname": ":bus:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["car", "transportation", "vehicle", "bus", "school", "city", "transportation", "public"],
+    "moji": "🚌"
+  },
+  "busstop": {
+    "unicode": "1F68F",
+    "unicode_alternates": [],
+    "name": "bus stop",
+    "shortname": ":busstop:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "bus", "stop", "city", "transport", "transportation"],
+    "moji": "🚏"
+  },
+  "bust_in_silhouette": {
+    "unicode": "1F464",
+    "unicode_alternates": [],
+    "name": "bust in silhouette",
+    "shortname": ":bust_in_silhouette:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["human", "man", "person", "user", "silhouette", "person", "user", "member", "account", "guest", "icon", "avatar", "profile", "me", "myself", "i"],
+    "moji": "👤"
+  },
+  "busts_in_silhouette": {
+    "unicode": "1F465",
+    "unicode_alternates": [],
+    "name": "busts in silhouette",
+    "shortname": ":busts_in_silhouette:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["group", "human", "man", "person", "team", "user", "silhouette", "silhouettes", "people", "user", "members", "accounts", "relationship", "shadow"],
+    "moji": "👥"
+  },
+  "cactus": {
+    "unicode": "1F335",
+    "unicode_alternates": [],
+    "name": "cactus",
+    "shortname": ":cactus:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "plant", "vegetable", "cactus", "desert", "drought", "spike", "poke"],
+    "moji": "🌵"
+  },
+  "cake": {
+    "unicode": "1F370",
+    "unicode_alternates": [],
+    "name": "shortcake",
+    "shortname": ":cake:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["desert", "food", "cake", "short", "dessert", "strawberry"],
+    "moji": "🍰"
+  },
+  "calculator": {
+    "unicode": "1F5A9",
+    "unicode_alternates": [],
+    "name": "pocket calculator",
+    "shortname": ":calculator:",
+    "category": "objects_symbols",
+    "aliases": [":pocket calculator:"],
+    "aliases_ascii": [],
+    "keywords": ["add", "subtract", "multiple", "divide", "scientific"]
+  },
+  "calendar": {
+    "unicode": "1F4C6",
+    "unicode_alternates": [],
+    "name": "tear-off calendar",
+    "shortname": ":calendar:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["schedule"],
+    "moji": "📆"
+  },
+  "calendar_spiral": {
+    "unicode": "1F5D3",
+    "unicode_alternates": [],
+    "name": "spiral calendar pad",
+    "shortname": ":calendar_spiral:",
+    "category": "objects_symbols",
+    "aliases": [":spiral_calendar_pad:"],
+    "aliases_ascii": [],
+    "keywords": ["schedule", "date", "day"]
+  },
+  "calling": {
+    "unicode": "1F4F2",
+    "unicode_alternates": [],
+    "name": "mobile phone with rightwards arrow at left",
+    "shortname": ":calling:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["incoming", "iphone"],
+    "moji": "📲"
+  },
+  "camel": {
+    "unicode": "1F42B",
+    "unicode_alternates": [],
+    "name": "bactrian camel",
+    "shortname": ":camel:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "hot", "nature", "bactrian", "camel", "hump", "desert", "central asia", "heat", "hot", "water", "hump day", "wednesday", "sex"],
+    "moji": "🐫"
+  },
+  "camera": {
+    "unicode": "1F4F7",
+    "unicode_alternates": [],
+    "name": "camera",
+    "shortname": ":camera:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["gadgets", "photo"],
+    "moji": "📷"
+  },
+  "camera_with_flash": {
+    "unicode": "1F4F8",
+    "unicode_alternates": [],
+    "name": "camera with flash",
+    "shortname": ":camera_with_flash:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["photo", "picture"]
+  },
+  "camping": {
+    "unicode": "1F3D5",
+    "unicode_alternates": [],
+    "name": "camping",
+    "shortname": ":camping:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["outdoors", "nature", "wilderness", "roughing", "activity"]
+  },
+  "cancellation_x": {
+    "unicode": "1F5D9",
+    "unicode_alternates": [],
+    "name": "cancellation x",
+    "shortname": ":cancellation_x:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cancel", "stop", "delete"]
+  },
+  "cancer": {
+    "unicode": "264B",
+    "unicode_alternates": ["264B-FE0F"],
+    "name": "cancer",
+    "shortname": ":cancer:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cancer", "crab", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "sign", "zodiac", "horoscope"],
+    "moji": "♋"
+  },
+  "candle": {
+    "unicode": "1F56F",
+    "unicode_alternates": [],
+    "name": "candle",
+    "shortname": ":candle:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["light", "wax"]
+  },
+  "candy": {
+    "unicode": "1F36C",
+    "unicode_alternates": [],
+    "name": "candy",
+    "shortname": ":candy:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["desert", "snack", "candy", "sugar", "sweet", "hard"],
+    "moji": "🍬"
+  },
+  "capital_abcd": {
+    "unicode": "1F520",
+    "unicode_alternates": [],
+    "name": "input symbol for latin capital letters",
+    "shortname": ":capital_abcd:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "blue-square", "words"],
+    "moji": "🔠"
+  },
+  "capricorn": {
+    "unicode": "2651",
+    "unicode_alternates": ["2651-FE0F"],
+    "name": "capricorn",
+    "shortname": ":capricorn:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["capricorn", "sea-goat", "goat-horned", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "sign", "zodiac", "horoscope"],
+    "moji": "♑"
+  },
+  "card_box": {
+    "unicode": "1F5C3",
+    "unicode_alternates": [],
+    "name": "card file box",
+    "shortname": ":card_box:",
+    "category": "objects_symbols",
+    "aliases": [":card_file_box:"],
+    "aliases_ascii": [],
+    "keywords": ["index", "organization"]
+  },
+  "card_index": {
+    "unicode": "1F4C7",
+    "unicode_alternates": [],
+    "name": "card index",
+    "shortname": ":card_index:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["business", "stationery"],
+    "moji": "📇"
+  },
+  "carousel_horse": {
+    "unicode": "1F3A0",
+    "unicode_alternates": [],
+    "name": "carousel horse",
+    "shortname": ":carousel_horse:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["carnival", "horse", "photo", "carousel", "horse", "amusement", "park", "ride", "entertainment", "park", "fair"],
+    "moji": "🎠"
+  },
+  "cartridge": {
+    "unicode": "1F5AD",
+    "unicode_alternates": [],
+    "name": "tape cartridge",
+    "shortname": ":cartridge:",
+    "category": "objects_symbols",
+    "aliases": [":tape_cartridge:"],
+    "aliases_ascii": [],
+    "keywords": ["oldschool", "save", "technology", "disk", "storage", "information", "computer", "drive", "megabyte"]
+  },
+  "cat": {
+    "unicode": "1F431",
+    "unicode_alternates": [],
+    "name": "cat face",
+    "shortname": ":cat:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "meow"],
+    "moji": "🐱"
+  },
+  "cat2": {
+    "unicode": "1F408",
+    "unicode_alternates": [],
+    "name": "cat",
+    "shortname": ":cat2:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "meow", "pet", "cat", "kitten", "meow"],
+    "moji": "🐈"
+  },
+  "celtic_cross": {
+    "unicode": "1F548",
+    "unicode_alternates": [],
+    "name": "celtic cross",
+    "shortname": ":celtic_cross:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["religion", "symbol"]
+  },
+  "chart": {
+    "unicode": "1F4B9",
+    "unicode_alternates": [],
+    "name": "chart with upwards trend and yen sign",
+    "shortname": ":chart:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["graph", "green-square"],
+    "moji": "💹"
+  },
+  "chart_with_downwards_trend": {
+    "unicode": "1F4C9",
+    "unicode_alternates": [],
+    "name": "chart with downwards trend",
+    "shortname": ":chart_with_downwards_trend:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["graph"],
+    "moji": "📉"
+  },
+  "chart_with_upwards_trend": {
+    "unicode": "1F4C8",
+    "unicode_alternates": [],
+    "name": "chart with upwards trend",
+    "shortname": ":chart_with_upwards_trend:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["graph"],
+    "moji": "📈"
+  },
+  "checkered_flag": {
+    "unicode": "1F3C1",
+    "unicode_alternates": [],
+    "name": "chequered flag",
+    "shortname": ":checkered_flag:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["contest", "finishline", "gokart", "rase", "checkered", "chequred", "race", "flag", "finish", "complete", "end"],
+    "moji": "🏁"
+  },
+  "cherries": {
+    "unicode": "1F352",
+    "unicode_alternates": [],
+    "name": "cherries",
+    "shortname": ":cherries:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "cherry", "cherries", "tree", "fruit", "pit"],
+    "moji": "🍒"
+  },
+  "cherry_blossom": {
+    "unicode": "1F338",
+    "unicode_alternates": [],
+    "name": "cherry blossom",
+    "shortname": ":cherry_blossom:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flower", "nature", "plant", "cherry", "blossom", "tree", "flower"],
+    "moji": "🌸"
+  },
+  "chestnut": {
+    "unicode": "1F330",
+    "unicode_alternates": [],
+    "name": "chestnut",
+    "shortname": ":chestnut:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "squirrel", "chestnut", "roasted", "food", "tree"],
+    "moji": "🌰"
+  },
+  "chicken": {
+    "unicode": "1F414",
+    "unicode_alternates": [],
+    "name": "chicken",
+    "shortname": ":chicken:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cluck", "chicken", "hen", "poultry", "livestock"],
+    "moji": "🐔"
+  },
+  "children_crossing": {
+    "unicode": "1F6B8",
+    "unicode_alternates": [],
+    "name": "children crossing",
+    "shortname": ":children_crossing:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["school", "children", "kids", "caution", "crossing", "street", "crosswalk", "slow"],
+    "moji": "🚸"
+  },
+  "chipmunk": {
+    "unicode": "1F43F",
+    "unicode_alternates": [],
+    "name": "chipmunk",
+    "shortname": ":chipmunk:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"]
+  },
+  "chocolate_bar": {
+    "unicode": "1F36B",
+    "unicode_alternates": [],
+    "name": "chocolate bar",
+    "shortname": ":chocolate_bar:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["desert", "food", "snack", "chocolate", "bar", "candy", "coca", "hershey&#039;s"],
+    "moji": "🍫"
+  },
+  "christmas_tree": {
+    "unicode": "1F384",
+    "unicode_alternates": [],
+    "name": "christmas tree",
+    "shortname": ":christmas_tree:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["celebration", "december", "festival", "vacation", "xmas", "christmas", "xmas", "santa", "holiday", "winter", "december", "santa", "evergreen", "ornaments", "jesus", "gifts", "presents"],
+    "moji": "🎄"
+  },
+  "church": {
+    "unicode": "26EA",
+    "unicode_alternates": ["26EA-FE0F"],
+    "name": "church",
+    "shortname": ":church:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "christ", "religion"],
+    "moji": "⛪"
+  },
+  "cinema": {
+    "unicode": "1F3A6",
+    "unicode_alternates": [],
+    "name": "cinema",
+    "shortname": ":cinema:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "film", "movie", "record", "cinema", "movie", "theater", "motion", "picture"],
+    "moji": "🎦"
+  },
+  "circus_tent": {
+    "unicode": "1F3AA",
+    "unicode_alternates": [],
+    "name": "circus tent",
+    "shortname": ":circus_tent:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["carnival", "festival", "party", "circus", "tent", "event", "carnival", "big", "top", "canvas"],
+    "moji": "🎪"
+  },
+  "city_dusk": {
+    "unicode": "1F306",
+    "unicode_alternates": [],
+    "name": "cityscape at dusk",
+    "shortname": ":city_dusk:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["photo", "city", "scape", "sunset", "dusk", "lights", "evening", "metropolitan", "night", "dark"],
+    "moji": "🌆"
+  },
+  "city_sunset": {
+    "unicode": "1F307",
+    "unicode_alternates": [],
+    "name": "sunset over buildings",
+    "shortname": ":city_sunset:",
+    "category": "places",
+    "aliases": [":city_sunrise:"],
+    "aliases_ascii": [],
+    "keywords": ["photo", "city", "scape", "sunrise", "dawn", "light", "morning", "metropolitan", "rise", "sun"],
+    "moji": "🌇"
+  },
+  "cityscape": {
+    "unicode": "1F3D9",
+    "unicode_alternates": [],
+    "name": "cityscape",
+    "shortname": ":cityscape:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["skyscraper", "city", "view", "lights", "buiildings", "metropolis"]
+  },
+  "clap": {
+    "unicode": "1F44F",
+    "unicode_alternates": [],
+    "name": "clapping hands sign",
+    "shortname": ":clap:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["applause", "congrats", "hands", "praise", "clapping", "appreciation", "approval", "sound", "encouragement", "enthusiasm"],
+    "moji": "👏"
+  },
+  "clapper": {
+    "unicode": "1F3AC",
+    "unicode_alternates": [],
+    "name": "clapper board",
+    "shortname": ":clapper:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["film", "movie", "record", "clapper", "board", "clapboard", "movie", "film", "take"],
+    "moji": "🎬"
+  },
+  "classical_building": {
+    "unicode": "1F3DB",
+    "unicode_alternates": [],
+    "name": "classical building",
+    "shortname": ":classical_building:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["government", "architecture", "history", "iconic", "genre"]
+  },
+  "clipboard": {
+    "unicode": "1F4CB",
+    "unicode_alternates": [],
+    "name": "clipboard",
+    "shortname": ":clipboard:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents", "stationery"],
+    "moji": "📋"
+  },
+  "clock": {
+    "unicode": "1F570",
+    "unicode_alternates": [],
+    "name": "mantlepiece clock",
+    "shortname": ":clock:",
+    "category": "objects_symbols",
+    "aliases": [":mantlepiece_clock:"],
+    "aliases_ascii": [],
+    "keywords": ["time"]
+  },
+  "clock1": {
+    "unicode": "1F550",
+    "unicode_alternates": [],
+    "name": "clock face one oclock",
+    "shortname": ":clock1:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕐"
+  },
+  "clock10": {
+    "unicode": "1F559",
+    "unicode_alternates": [],
+    "name": "clock face ten oclock",
+    "shortname": ":clock10:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕙"
+  },
+  "clock1030": {
+    "unicode": "1F565",
+    "unicode_alternates": [],
+    "name": "clock face ten-thirty",
+    "shortname": ":clock1030:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕥"
+  },
+  "clock11": {
+    "unicode": "1F55A",
+    "unicode_alternates": [],
+    "name": "clock face eleven oclock",
+    "shortname": ":clock11:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕚"
+  },
+  "clock1130": {
+    "unicode": "1F566",
+    "unicode_alternates": [],
+    "name": "clock face eleven-thirty",
+    "shortname": ":clock1130:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕦"
+  },
+  "clock12": {
+    "unicode": "1F55B",
+    "unicode_alternates": [],
+    "name": "clock face twelve oclock",
+    "shortname": ":clock12:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕛"
+  },
+  "clock1230": {
+    "unicode": "1F567",
+    "unicode_alternates": [],
+    "name": "clock face twelve-thirty",
+    "shortname": ":clock1230:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"]
+  },
+  "clock130": {
+    "unicode": "1F55C",
+    "unicode_alternates": [],
+    "name": "clock face one-thirty",
+    "shortname": ":clock130:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕜"
+  },
+  "clock2": {
+    "unicode": "1F551",
+    "unicode_alternates": [],
+    "name": "clock face two oclock",
+    "shortname": ":clock2:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕑"
+  },
+  "clock230": {
+    "unicode": "1F55D",
+    "unicode_alternates": [],
+    "name": "clock face two-thirty",
+    "shortname": ":clock230:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕝"
+  },
+  "clock3": {
+    "unicode": "1F552",
+    "unicode_alternates": [],
+    "name": "clock face three oclock",
+    "shortname": ":clock3:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕒"
+  },
+  "clock330": {
+    "unicode": "1F55E",
+    "unicode_alternates": [],
+    "name": "clock face three-thirty",
+    "shortname": ":clock330:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕞"
+  },
+  "clock4": {
+    "unicode": "1F553",
+    "unicode_alternates": [],
+    "name": "clock face four oclock",
+    "shortname": ":clock4:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕓"
+  },
+  "clock430": {
+    "unicode": "1F55F",
+    "unicode_alternates": [],
+    "name": "clock face four-thirty",
+    "shortname": ":clock430:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕟"
+  },
+  "clock5": {
+    "unicode": "1F554",
+    "unicode_alternates": [],
+    "name": "clock face five oclock",
+    "shortname": ":clock5:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕔"
+  },
+  "clock530": {
+    "unicode": "1F560",
+    "unicode_alternates": [],
+    "name": "clock face five-thirty",
+    "shortname": ":clock530:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕠"
+  },
+  "clock6": {
+    "unicode": "1F555",
+    "unicode_alternates": [],
+    "name": "clock face six oclock",
+    "shortname": ":clock6:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕕"
+  },
+  "clock630": {
+    "unicode": "1F561",
+    "unicode_alternates": [],
+    "name": "clock face six-thirty",
+    "shortname": ":clock630:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕡"
+  },
+  "clock7": {
+    "unicode": "1F556",
+    "unicode_alternates": [],
+    "name": "clock face seven oclock",
+    "shortname": ":clock7:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕖"
+  },
+  "clock730": {
+    "unicode": "1F562",
+    "unicode_alternates": [],
+    "name": "clock face seven-thirty",
+    "shortname": ":clock730:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕢"
+  },
+  "clock8": {
+    "unicode": "1F557",
+    "unicode_alternates": [],
+    "name": "clock face eight oclock",
+    "shortname": ":clock8:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕗"
+  },
+  "clock830": {
+    "unicode": "1F563",
+    "unicode_alternates": [],
+    "name": "clock face eight-thirty",
+    "shortname": ":clock830:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕣"
+  },
+  "clock9": {
+    "unicode": "1F558",
+    "unicode_alternates": [],
+    "name": "clock face nine oclock",
+    "shortname": ":clock9:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕘"
+  },
+  "clock930": {
+    "unicode": "1F564",
+    "unicode_alternates": [],
+    "name": "clock face nine-thirty",
+    "shortname": ":clock930:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "time"],
+    "moji": "🕤"
+  },
+  "clockwise_arrows": {
+    "unicode": "1F5D8",
+    "unicode_alternates": [],
+    "name": "clockwise right and left semicircle arrows",
+    "shortname": ":clockwise_arrows:",
+    "category": "objects_symbols",
+    "aliases": [":clockwise_right_and_left_semicircle_arrows:"],
+    "aliases_ascii": [],
+    "keywords": ["sync"]
+  },
+  "closed_book": {
+    "unicode": "1F4D5",
+    "unicode_alternates": [],
+    "name": "closed book",
+    "shortname": ":closed_book:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["knowledge", "library", "read"],
+    "moji": "📕"
+  },
+  "closed_lock_with_key": {
+    "unicode": "1F510",
+    "unicode_alternates": [],
+    "name": "closed lock with key",
+    "shortname": ":closed_lock_with_key:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["privacy", "security"],
+    "moji": "🔐"
+  },
+  "closed_umbrella": {
+    "unicode": "1F302",
+    "unicode_alternates": [],
+    "name": "closed umbrella",
+    "shortname": ":closed_umbrella:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["drizzle", "rain", "weather", "umbrella", "closed", "rain", "moisture", "protection", "sun", "ultraviolet", "uv"],
+    "moji": "🌂"
+  },
+  "cloud": {
+    "unicode": "2601",
+    "unicode_alternates": ["2601-FE0F"],
+    "name": "cloud",
+    "shortname": ":cloud:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sky", "weather"],
+    "moji": "☁"
+  },
+  "cloud_lightning": {
+    "unicode": "1F329",
+    "unicode_alternates": [],
+    "name": "cloud with lightning",
+    "shortname": ":cloud_lightning:",
+    "category": "nature",
+    "aliases": [":cloud_with_lightning:"],
+    "aliases_ascii": [],
+    "keywords": ["weather", "thunder"]
+  },
+  "cloud_rain": {
+    "unicode": "1F327",
+    "unicode_alternates": [],
+    "name": "cloud with rain",
+    "shortname": ":cloud_rain:",
+    "category": "nature",
+    "aliases": [":cloud_with_rain:"],
+    "aliases_ascii": [],
+    "keywords": ["weather", "wet"]
+  },
+  "cloud_snow": {
+    "unicode": "1F328",
+    "unicode_alternates": [],
+    "name": "cloud with snow",
+    "shortname": ":cloud_snow:",
+    "category": "nature",
+    "aliases": [":cloud_with_snow:"],
+    "aliases_ascii": [],
+    "keywords": ["weather", "cold"]
+  },
+  "cloud_tornado": {
+    "unicode": "1F32A",
+    "unicode_alternates": [],
+    "name": "cloud with tornado",
+    "shortname": ":cloud_tornado:",
+    "category": "nature",
+    "aliases": [":cloud_with_tornado:"],
+    "aliases_ascii": [],
+    "keywords": ["weather", "destruction", "funnel"]
+  },
+  "clubs": {
+    "unicode": "2663",
+    "unicode_alternates": ["2663-FE0F"],
+    "name": "black club suit",
+    "shortname": ":clubs:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cards", "poker"],
+    "moji": "♣"
+  },
+  "cocktail": {
+    "unicode": "1F378",
+    "unicode_alternates": [],
+    "name": "cocktail glass",
+    "shortname": ":cocktail:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alcohol", "beverage", "drink", "drunk", "cocktail", "mixed", "drink", "alcohol", "glass", "martini", "bar"],
+    "moji": "🍸"
+  },
+  "coffee": {
+    "unicode": "2615",
+    "unicode_alternates": ["2615-FE0F"],
+    "name": "hot beverage",
+    "shortname": ":coffee:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["beverage", "cafe", "drink", "espresso"],
+    "moji": "☕"
+  },
+  "cold_sweat": {
+    "unicode": "1F630",
+    "unicode_alternates": [],
+    "name": "face with open mouth and cold sweat",
+    "shortname": ":cold_sweat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "nervous", "sweat", "exasperated", "frustrated"],
+    "moji": "😰"
+  },
+  "compression": {
+    "unicode": "1F5DC",
+    "unicode_alternates": [],
+    "name": "compression",
+    "shortname": ":compression:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["reduce"]
+  },
+  "computer": {
+    "unicode": "1F4BB",
+    "unicode_alternates": [],
+    "name": "personal computer",
+    "shortname": ":computer:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["laptop", "tech"],
+    "moji": "💻"
+  },
+  "computer_old": {
+    "unicode": "1F5B3",
+    "unicode_alternates": [],
+    "name": "old personal computer",
+    "shortname": ":computer_old:",
+    "category": "objects_symbols",
+    "aliases": [":old_personal_computer:"],
+    "aliases_ascii": [],
+    "keywords": ["cpu", "terminal"]
+  },
+  "confetti_ball": {
+    "unicode": "1F38A",
+    "unicode_alternates": [],
+    "name": "confetti ball",
+    "shortname": ":confetti_ball:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["festival", "party", "party", "congratulations", "confetti", "ball", "celebrate", "win", "birthday", "new years", "wedding"],
+    "moji": "🎊"
+  },
+  "confounded": {
+    "unicode": "1F616",
+    "unicode_alternates": [],
+    "name": "confounded face",
+    "shortname": ":confounded:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["confused", "face", "sick", "unwell", "confound", "amaze", "perplex", "puzzle", "mystify"],
+    "moji": "😖"
+  },
+  "confused": {
+    "unicode": "1F615",
+    "unicode_alternates": [],
+    "name": "confused face",
+    "shortname": ":confused:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [">:\\", ">:/", ":-/", ":-.", ":/", ":\\", "=/", "=\\", ":L", "=L"],
+    "keywords": ["confused", "confuse", "daze", "perplex", "puzzle", "indifference", "skeptical", "undecided", "uneasy", "hesitant"],
+    "moji": "😕"
+  },
+  "congratulations": {
+    "unicode": "3297",
+    "unicode_alternates": ["3297-FE0F"],
+    "name": "circled ideograph congratulation",
+    "shortname": ":congratulations:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "japanese", "kanji"],
+    "moji": "㊗"
+  },
+  "construction": {
+    "unicode": "1F6A7",
+    "unicode_alternates": [],
+    "name": "construction sign",
+    "shortname": ":construction:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["caution", "progress", "wip"],
+    "moji": "🚧"
+  },
+  "construction_worker": {
+    "unicode": "1F477",
+    "unicode_alternates": [],
+    "name": "construction worker",
+    "shortname": ":construction_worker:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["human", "male", "man", "wip"],
+    "moji": "👷"
+  },
+  "control_knobs": {
+    "unicode": "1F39B",
+    "unicode_alternates": [],
+    "name": "control knobs",
+    "shortname": ":control_knobs:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dial"]
+  },
+  "contruction_site": {
+    "unicode": "1F3D7",
+    "unicode_alternates": [],
+    "name": "building construction",
+    "shortname": ":contruction_site:",
+    "category": "travel_places",
+    "aliases": [":building_construction:"],
+    "aliases_ascii": [],
+    "keywords": ["site", "work"]
+  },
+  "convenience_store": {
+    "unicode": "1F3EA",
+    "unicode_alternates": [],
+    "name": "convenience store",
+    "shortname": ":convenience_store:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building"],
+    "moji": "🏪"
+  },
+  "cookie": {
+    "unicode": "1F36A",
+    "unicode_alternates": [],
+    "name": "cookie",
+    "shortname": ":cookie:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chocolate", "food", "oreo", "snack", "cookie", "dessert", "biscuit", "sweet", "chocolate"],
+    "moji": "🍪"
+  },
+  "cool": {
+    "unicode": "1F192",
+    "unicode_alternates": [],
+    "name": "squared cool",
+    "shortname": ":cool:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "words"],
+    "moji": "🆒"
+  },
+  "cop": {
+    "unicode": "1F46E",
+    "unicode_alternates": [],
+    "name": "police officer",
+    "shortname": ":cop:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrest", "enforcement", "law", "man", "police"],
+    "moji": "👮"
+  },
+  "copyright": {
+    "moji": "©",
+    "unicode": "00A9",
+    "unicode_alternates": [],
+    "name": "copyright sign",
+    "shortname": ":copyright:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["ip", "license"]
+  },
+  "corn": {
+    "unicode": "1F33D",
+    "unicode_alternates": [],
+    "name": "ear of maize",
+    "shortname": ":corn:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "plant", "vegetable", "corn", "maize", "food", "iowa", "kernel", "popcorn", "husk", "yellow", "stalk", "cob", "ear"],
+    "moji": "🌽"
+  },
+  "couch": {
+    "unicode": "1F6CB",
+    "unicode_alternates": [],
+    "name": "couch and lamp",
+    "shortname": ":couch:",
+    "category": "travel_places",
+    "aliases": [":couch_and_lamp:"],
+    "aliases_ascii": [],
+    "keywords": ["lounge", "sectional", "sofa", "loveseat", "leather", "microfiber", "sit", "relax"]
+  },
+  "couple": {
+    "unicode": "1F46B",
+    "unicode_alternates": [],
+    "name": "man and woman holding hands",
+    "shortname": ":couple:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "date", "dating", "human", "like", "love", "marriage", "people", "valentines"],
+    "moji": "👫"
+  },
+  "couple_mm": {
+    "unicode": "1F468-2764-1F468",
+    "unicode_alternates": ["1F468-200D-2764-FE0F-200D-1F468"],
+    "name": "couple (man,man)",
+    "shortname": ":couple_mm:",
+    "category": "people",
+    "aliases": [":couple_with_heart_mm:"],
+    "aliases_ascii": [],
+    "keywords": ["affection", "dating", "human", "like", "love", "marriage", "valentines"]
+  },
+  "couple_with_heart": {
+    "unicode": "1F491",
+    "unicode_alternates": [],
+    "name": "couple with heart",
+    "shortname": ":couple_with_heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "dating", "human", "like", "love", "marriage", "valentines"],
+    "moji": "💑"
+  },
+  "couple_ww": {
+    "unicode": "1F469-2764-1F469",
+    "unicode_alternates": ["1F469-200D-2764-FE0F-200D-1F469"],
+    "name": "couple (woman,woman)",
+    "shortname": ":couple_ww:",
+    "category": "people",
+    "aliases": [":couple_with_heart_ww:"],
+    "aliases_ascii": [],
+    "keywords": ["affection", "dating", "human", "like", "love", "marriage", "valentines"]
+  },
+  "couplekiss": {
+    "unicode": "1F48F",
+    "unicode_alternates": [],
+    "name": "kiss",
+    "shortname": ":couplekiss:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dating", "like", "love", "marriage", "valentines"],
+    "moji": "💏"
+  },
+  "cow": {
+    "unicode": "1F42E",
+    "unicode_alternates": [],
+    "name": "cow face",
+    "shortname": ":cow:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "beef", "ox"],
+    "moji": "🐮"
+  },
+  "cow2": {
+    "unicode": "1F404",
+    "unicode_alternates": [],
+    "name": "cow",
+    "shortname": ":cow2:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "beef", "nature", "ox", "cow", "milk", "dairy", "beef", "bessie", "moo"],
+    "moji": "🐄"
+  },
+  "crayon": {
+    "unicode": "1F58D",
+    "unicode_alternates": [],
+    "name": "lower left crayon",
+    "shortname": ":crayon:",
+    "category": "objects_symbols",
+    "aliases": [":lower_left_crayon:"],
+    "aliases_ascii": [],
+    "keywords": ["write", "draw", "color", "wax"]
+  },
+  "credit_card": {
+    "unicode": "1F4B3",
+    "unicode_alternates": [],
+    "name": "credit card",
+    "shortname": ":credit_card:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bill", "dollar", "money", "pay", "payment", "credit", "card", "loan", "purchase", "shopping", "mastercard", "visa", "american express", "wallet", "signature"],
+    "moji": "💳"
+  },
+  "crescent_moon": {
+    "unicode": "1F319",
+    "unicode_alternates": [],
+    "name": "crescent moon",
+    "shortname": ":crescent_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["night", "moon", "crescent", "waxing", "sky", "night", "cheese", "phase"],
+    "moji": "🌙"
+  },
+  "crocodile": {
+    "unicode": "1F40A",
+    "unicode_alternates": [],
+    "name": "crocodile",
+    "shortname": ":crocodile:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "crocodile", "croc", "alligator", "gator", "cranky"],
+    "moji": "🐊"
+  },
+  "cross_heavy": {
+    "unicode": "1F547",
+    "unicode_alternates": [],
+    "name": "heavy latin cross",
+    "shortname": ":cross_heavy:",
+    "category": "objects_symbols",
+    "aliases": [":heavy_latin_cross:"],
+    "aliases_ascii": [],
+    "keywords": ["religion", "symbol"]
+  },
+  "cross_white": {
+    "unicode": "1F546",
+    "unicode_alternates": [],
+    "name": "white latin cross",
+    "shortname": ":cross_white:",
+    "category": "objects_symbols",
+    "aliases": [":white_latin_cross:"],
+    "aliases_ascii": [],
+    "keywords": ["religion", "symbol"]
+  },
+  "crossbones": {
+    "unicode": "1F571",
+    "unicode_alternates": [],
+    "name": "black skull and crossbones",
+    "shortname": ":crossbones:",
+    "category": "objects_symbols",
+    "aliases": [":black_skull_and_crossbones:"],
+    "aliases_ascii": [],
+    "keywords": ["poison", "danger", "death"]
+  },
+  "crossed_flags": {
+    "unicode": "1F38C",
+    "unicode_alternates": [],
+    "name": "crossed flags",
+    "shortname": ":crossed_flags:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["japan"],
+    "moji": "🎌"
+  },
+  "crown": {
+    "unicode": "1F451",
+    "unicode_alternates": [],
+    "name": "crown",
+    "shortname": ":crown:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["king", "kod", "leader", "royalty"],
+    "moji": "👑"
+  },
+  "cruise_ship": {
+    "unicode": "1F6F3",
+    "unicode_alternates": [],
+    "name": "passenger ship",
+    "shortname": ":cruise_ship:",
+    "category": "travel_places",
+    "aliases": [":passenger_ship:"],
+    "aliases_ascii": [],
+    "keywords": ["titanic", "transportation", "boat"]
+  },
+  "cry": {
+    "unicode": "1F622",
+    "unicode_alternates": [],
+    "name": "crying face",
+    "shortname": ":cry:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":'(", ":'-(", ";(", ";-("],
+    "keywords": ["face", "sad", "sad", "cry", "tear", "weep", "tears"],
+    "moji": "😢"
+  },
+  "crying_cat_face": {
+    "unicode": "1F63F",
+    "unicode_alternates": [],
+    "name": "crying cat face",
+    "shortname": ":crying_cat_face:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cats", "sad", "tears", "weep", "cry", "cat", "sob", "tears", "sad", "melancholy", "morn", "somber", "hurt"],
+    "moji": "😿"
+  },
+  "crystal_ball": {
+    "unicode": "1F52E",
+    "unicode_alternates": [],
+    "name": "crystal ball",
+    "shortname": ":crystal_ball:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["disco", "party"],
+    "moji": "🔮"
+  },
+  "cupid": {
+    "unicode": "1F498",
+    "unicode_alternates": [],
+    "name": "heart with arrow",
+    "shortname": ":cupid:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "heart", "like", "love", "valentines"],
+    "moji": "💘"
+  },
+  "curly_loop": {
+    "unicode": "27B0",
+    "unicode_alternates": [],
+    "name": "curly loop",
+    "shortname": ":curly_loop:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["scribble"],
+    "moji": "âž°"
+  },
+  "currency_exchange": {
+    "unicode": "1F4B1",
+    "unicode_alternates": [],
+    "name": "currency exchange",
+    "shortname": ":currency_exchange:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dollar", "money", "travel"],
+    "moji": "💱"
+  },
+  "curry": {
+    "unicode": "1F35B",
+    "unicode_alternates": [],
+    "name": "curry and rice",
+    "shortname": ":curry:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "hot", "indian", "spicy", "curry", "spice", "flavor", "food", "meal"],
+    "moji": "🍛"
+  },
+  "custard": {
+    "unicode": "1F36E",
+    "unicode_alternates": [],
+    "name": "custard",
+    "shortname": ":custard:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["desert", "food", "custard", "cream", "rich", "butter", "dessert", "crème", "brûlée", "french"],
+    "moji": "🍮"
+  },
+  "customs": {
+    "unicode": "1F6C3",
+    "unicode_alternates": [],
+    "name": "customs",
+    "shortname": ":customs:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["border", "passport", "customs", "travel", "foreign", "goods", "check", "authority", "government"],
+    "moji": "🛃"
+  },
+  "cyclone": {
+    "moji": "🌀",
+    "unicode": "1F300",
+    "unicode_alternates": [],
+    "name": "cyclone",
+    "shortname": ":cyclone:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue", "cloud", "swirl", "weather", "cyclone", "hurricane", "typhoon", "storm", "ocean"]
+  },
+  "dagger": {
+    "unicode": "1F5E1",
+    "unicode_alternates": [],
+    "name": "dagger knife",
+    "shortname": ":dagger:",
+    "category": "objects_symbols",
+    "aliases": [":dagger_knife:"],
+    "aliases_ascii": [],
+    "keywords": ["blade", "knife"]
+  },
+  "dancer": {
+    "unicode": "1F483",
+    "unicode_alternates": [],
+    "name": "dancer",
+    "shortname": ":dancer:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "fun", "girl", "woman", "dance", "dancer", "dress", "fancy", "boogy", "party", "celebrate", "ballet", "tango", "cha cha", "music"],
+    "moji": "💃"
+  },
+  "dancers": {
+    "unicode": "1F46F",
+    "unicode_alternates": [],
+    "name": "woman with bunny ears",
+    "shortname": ":dancers:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bunny", "female", "girls", "women", "dancing", "dancers", "showgirl", "playboy", "costume", "bunny", "cancan"],
+    "moji": "👯"
+  },
+  "dango": {
+    "unicode": "1F361",
+    "unicode_alternates": [],
+    "name": "dango",
+    "shortname": ":dango:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "dango", "japanese", "dumpling", "mochi", "balls", "skewer"],
+    "moji": "🍡"
+  },
+  "dark_sunglasses": {
+    "unicode": "1F576",
+    "unicode_alternates": [],
+    "name": "dark sunglasses",
+    "shortname": ":dark_sunglasses:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shades", "eyes"]
+  },
+  "dart": {
+    "unicode": "1F3AF",
+    "unicode_alternates": [],
+    "name": "direct hit",
+    "shortname": ":dart:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bar", "game", "direct", "hit", "bullseye", "dart", "archery", "game", "fletching", "arrow", "sport"],
+    "moji": "🎯"
+  },
+  "dash": {
+    "unicode": "1F4A8",
+    "unicode_alternates": [],
+    "name": "dash symbol",
+    "shortname": ":dash:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["air", "fast", "shoo", "wind"],
+    "moji": "💨"
+  },
+  "date": {
+    "unicode": "1F4C5",
+    "unicode_alternates": [],
+    "name": "calendar",
+    "shortname": ":date:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["calendar", "schedule"],
+    "moji": "📅"
+  },
+  "deciduous_tree": {
+    "unicode": "1F333",
+    "unicode_alternates": [],
+    "name": "deciduous tree",
+    "shortname": ":deciduous_tree:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "plant", "deciduous", "tree", "leaves", "fall", "color"],
+    "moji": "🌳"
+  },
+  "department_store": {
+    "unicode": "1F3EC",
+    "unicode_alternates": [],
+    "name": "department store",
+    "shortname": ":department_store:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "mall", "shopping", "department", "store", "retail", "sale", "merchandise"],
+    "moji": "🏬"
+  },
+  "descending_notes": {
+    "unicode": "1F39D",
+    "unicode_alternates": [],
+    "name": "beamed descending musical notes",
+    "shortname": ":descending_notes:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["score", "music", "sound", "tone"]
+  },
+  "desert": {
+    "unicode": "1F3DC",
+    "unicode_alternates": [],
+    "name": "desert",
+    "shortname": ":desert:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["hot", "dry", "sandy", "cactus", "sunny", "barren"]
+  },
+  "desktop": {
+    "unicode": "1F5A5",
+    "unicode_alternates": [],
+    "name": "desktop computer",
+    "shortname": ":desktop:",
+    "category": "objects_symbols",
+    "aliases": [":desktop_computer:"],
+    "aliases_ascii": [],
+    "keywords": ["cpu"]
+  },
+  "desktop_window": {
+    "unicode": "1F5D4",
+    "unicode_alternates": [],
+    "name": "desktop window",
+    "shortname": ":desktop_window:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["computer"]
+  },
+  "diamond_shape_with_a_dot_inside": {
+    "unicode": "1F4A0",
+    "unicode_alternates": [],
+    "name": "diamond shape with a dot inside",
+    "shortname": ":diamond_shape_with_a_dot_inside:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["diamond", "cute", "cuteness", "kawaii", "japanese", "glyph", "adorable"],
+    "moji": "💠"
+  },
+  "diamonds": {
+    "unicode": "2666",
+    "unicode_alternates": ["2666-FE0F"],
+    "name": "black diamond suit",
+    "shortname": ":diamonds:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cards", "poker"],
+    "moji": "♦"
+  },
+  "disappointed": {
+    "unicode": "1F61E",
+    "unicode_alternates": [],
+    "name": "disappointed face",
+    "shortname": ":disappointed:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [">:[", ":-(", ":(", ":-[", ":[", "=("],
+    "keywords": ["disappointed", "disappoint", "frown", "depressed", "discouraged", "face", "sad", "upset"],
+    "moji": "😞"
+  },
+  "disappointed_relieved": {
+    "unicode": "1F625",
+    "unicode_alternates": [],
+    "name": "disappointed but relieved face",
+    "shortname": ":disappointed_relieved:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "nervous", "phew", "sweat", "disappoint", "relief"],
+    "moji": "😥"
+  },
+  "dividers": {
+    "unicode": "1F5C2",
+    "unicode_alternates": [],
+    "name": "card index dividers",
+    "shortname": ":dividers:",
+    "category": "objects_symbols",
+    "aliases": [":card_index_dividers:"],
+    "aliases_ascii": [],
+    "keywords": ["stationery", "rolodex"]
+  },
+  "dizzy": {
+    "unicode": "1F4AB",
+    "unicode_alternates": [],
+    "name": "dizzy symbol",
+    "shortname": ":dizzy:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shoot", "sparkle", "star", "dizzy", "drunk", "sick", "intoxicated", "squeans", "starburst", "star"],
+    "moji": "💫"
+  },
+  "dizzy_face": {
+    "unicode": "1F635",
+    "unicode_alternates": [],
+    "name": "dizzy face",
+    "shortname": ":dizzy_face:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["#-)", "#)", "%-)", "%)", "X)", "X-)"],
+    "keywords": ["dizzy", "drunk", "inebriated", "face", "spent", "unconscious", "xox"],
+    "moji": "😵"
+  },
+  "do_not_litter": {
+    "unicode": "1F6AF",
+    "unicode_alternates": [],
+    "name": "do not litter symbol",
+    "shortname": ":do_not_litter:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bin", "garbage", "trash", "litter", "garbage", "waste", "no", "can", "trash"],
+    "moji": "🚯"
+  },
+  "document": {
+    "unicode": "1F5CE",
+    "unicode_alternates": [],
+    "name": "document",
+    "shortname": ":document:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["page"]
+  },
+  "document_text": {
+    "unicode": "1F5B9",
+    "unicode_alternates": [],
+    "name": "document with text",
+    "shortname": ":document_text:",
+    "category": "objects_symbols",
+    "aliases": [":document_with_text:"],
+    "aliases_ascii": [],
+    "keywords": ["page"]
+  },
+  "dog": {
+    "unicode": "1F436",
+    "unicode_alternates": [],
+    "name": "dog face",
+    "shortname": ":dog:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "friend", "nature", "woof"],
+    "moji": "🐶"
+  },
+  "dog2": {
+    "unicode": "1F415",
+    "unicode_alternates": [],
+    "name": "dog",
+    "shortname": ":dog2:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "doge", "friend", "nature", "pet", "dog", "puppy", "pet", "friend", "woof", "bark", "fido"],
+    "moji": "🐕"
+  },
+  "dollar": {
+    "unicode": "1F4B5",
+    "unicode_alternates": [],
+    "name": "banknote with dollar sign",
+    "shortname": ":dollar:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bill", "currency", "money", "dollar", "united states", "canada", "australia", "banknote", "money", "currency", "paper", "cash", "bills"],
+    "moji": "💵"
+  },
+  "dolls": {
+    "unicode": "1F38E",
+    "unicode_alternates": [],
+    "name": "japanese dolls",
+    "shortname": ":dolls:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["japanese", "kimono", "toy", "dolls", "japan", "japanese", "day", "girls", "emperor", "empress", "pray", "blessing", "imperial", "family", "royal"],
+    "moji": "🎎"
+  },
+  "dolphin": {
+    "unicode": "1F42C",
+    "unicode_alternates": [],
+    "name": "dolphin",
+    "shortname": ":dolphin:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "fins", "fish", "flipper", "nature", "ocean", "sea"],
+    "moji": "🐬"
+  },
+  "door": {
+    "unicode": "1F6AA",
+    "unicode_alternates": [],
+    "name": "door",
+    "shortname": ":door:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["entry", "exit", "house", "door", "doorway", "entrance", "enter", "exit", "entry"],
+    "moji": "🚪"
+  },
+  "doughnut": {
+    "unicode": "1F369",
+    "unicode_alternates": [],
+    "name": "doughnut",
+    "shortname": ":doughnut:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["desert", "food", "snack", "sweet", "doughnut", "donut", "pastry", "fried", "dessert", "breakfast", "police", "homer", "sweet"],
+    "moji": "🍩"
+  },
+  "dove": {
+    "unicode": "1F54A",
+    "unicode_alternates": [],
+    "name": "dove of peace",
+    "shortname": ":dove:",
+    "category": "objects_symbols",
+    "aliases": [":dove_of_peace:"],
+    "aliases_ascii": [],
+    "keywords": ["symbol", "bird"]
+  },
+  "dragon": {
+    "unicode": "1F409",
+    "unicode_alternates": [],
+    "name": "dragon",
+    "shortname": ":dragon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "chinese", "green", "myth", "nature", "dragon", "fire", "legendary", "myth"],
+    "moji": "🐉"
+  },
+  "dragon_face": {
+    "unicode": "1F432",
+    "unicode_alternates": [],
+    "name": "dragon face",
+    "shortname": ":dragon_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "chinese", "green", "myth", "nature", "dragon", "head", "fire", "legendary", "myth"],
+    "moji": "🐲"
+  },
+  "dress": {
+    "unicode": "1F457",
+    "unicode_alternates": [],
+    "name": "dress",
+    "shortname": ":dress:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clothes", "fashion"],
+    "moji": "👗"
+  },
+  "dromedary_camel": {
+    "unicode": "1F42A",
+    "unicode_alternates": [],
+    "name": "dromedary camel",
+    "shortname": ":dromedary_camel:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "desert", "hot", "dromedary", "camel", "hump", "desert", "middle east", "heat", "hot", "water", "hump day", "wednesday", "sex"],
+    "moji": "🐪"
+  },
+  "droplet": {
+    "unicode": "1F4A7",
+    "unicode_alternates": [],
+    "name": "droplet",
+    "shortname": ":droplet:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["drip", "faucet", "water", "drop", "droplet", "h20", "water", "aqua", "tear", "sweat", "rain", "moisture", "wet", "moist", "spit"],
+    "moji": "💧"
+  },
+  "dvd": {
+    "unicode": "1F4C0",
+    "unicode_alternates": [],
+    "name": "dvd",
+    "shortname": ":dvd:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cd", "disc", "disk"],
+    "moji": "📀"
+  },
+  "e-mail": {
+    "unicode": "1F4E7",
+    "unicode_alternates": [],
+    "name": "e-mail symbol",
+    "shortname": ":e-mail:",
+    "category": "objects",
+    "aliases": [":email:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "inbox"],
+    "moji": "📧"
+  },
+  "ear": {
+    "unicode": "1F442",
+    "unicode_alternates": [],
+    "name": "ear",
+    "shortname": ":ear:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "hear", "listen", "sound"],
+    "moji": "👂"
+  },
+  "ear_of_rice": {
+    "unicode": "1F33E",
+    "unicode_alternates": [],
+    "name": "ear of rice",
+    "shortname": ":ear_of_rice:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "plant", "ear", "rice", "food", "plant", "seed"],
+    "moji": "🌾"
+  },
+  "earth_africa": {
+    "unicode": "1F30D",
+    "unicode_alternates": [],
+    "name": "earth globe europe-africa",
+    "shortname": ":earth_africa:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["globe", "international", "world", "earth", "globe", "space", "planet", "africa", "europe", "home"],
+    "moji": "🌍"
+  },
+  "earth_americas": {
+    "unicode": "1F30E",
+    "unicode_alternates": [],
+    "name": "earth globe americas",
+    "shortname": ":earth_americas:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["USA", "globe", "international", "world", "earth", "globe", "space", "planet", "north", "south", "america", "americas", "home"],
+    "moji": "🌎"
+  },
+  "earth_asia": {
+    "unicode": "1F30F",
+    "unicode_alternates": [],
+    "name": "earth globe asia-australia",
+    "shortname": ":earth_asia:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["east", "globe", "international", "world", "earth", "globe", "space", "planet", "asia", "australia", "home"],
+    "moji": "🌏"
+  },
+  "egg": {
+    "unicode": "1F373",
+    "unicode_alternates": [],
+    "name": "cooking",
+    "shortname": ":egg:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["breakfast", "food", "egg", "fry", "pan", "flat", "cook", "frying", "cooking", "utensil"],
+    "moji": "🍳"
+  },
+  "eggplant": {
+    "unicode": "1F346",
+    "unicode_alternates": [],
+    "name": "aubergine",
+    "shortname": ":eggplant:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["aubergine", "food", "nature", "vegetable", "eggplant", "aubergine", "fruit", "purple", "penis"],
+    "moji": "🍆"
+  },
+  "eight": {
+    "moji": "8️⃣",
+    "unicode": "0038-20E3",
+    "unicode_alternates": ["0038-FE0F-20E3"],
+    "name": "digit eight",
+    "shortname": ":eight:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["8", "blue-square", "numbers"]
+  },
+  "eight_pointed_black_star": {
+    "unicode": "2734",
+    "unicode_alternates": ["2734-FE0F"],
+    "name": "eight pointed black star",
+    "shortname": ":eight_pointed_black_star:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": [],
+    "moji": "✴"
+  },
+  "eight_spoked_asterisk": {
+    "unicode": "2733",
+    "unicode_alternates": ["2733-FE0F"],
+    "name": "eight spoked asterisk",
+    "shortname": ":eight_spoked_asterisk:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["green-square", "sparkle", "star"],
+    "moji": "✳"
+  },
+  "electric_plug": {
+    "unicode": "1F50C",
+    "unicode_alternates": [],
+    "name": "electric plug",
+    "shortname": ":electric_plug:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["charger", "power"],
+    "moji": "🔌"
+  },
+  "elephant": {
+    "unicode": "1F418",
+    "unicode_alternates": [],
+    "name": "elephant",
+    "shortname": ":elephant:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "nose", "thailand"],
+    "moji": "🐘"
+  },
+  "end": {
+    "unicode": "1F51A",
+    "unicode_alternates": [],
+    "name": "end with leftwards arrow above",
+    "shortname": ":end:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "words"],
+    "moji": "🔚"
+  },
+  "envelope": {
+    "unicode": "2709",
+    "unicode_alternates": ["2709-FE0F"],
+    "name": "envelope",
+    "shortname": ":envelope:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "letter", "mail", "postal"],
+    "moji": "✉"
+  },
+  "envelope_back": {
+    "unicode": "1F582",
+    "unicode_alternates": [],
+    "name": "back of envelope",
+    "shortname": ":envelope_back:",
+    "category": "objects_symbols",
+    "aliases": [":back_of_envelope:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "letter", "mail", "postal"]
+  },
+  "envelope_flying": {
+    "unicode": "1F585",
+    "unicode_alternates": [],
+    "name": "flying envelope",
+    "shortname": ":envelope_flying:",
+    "category": "objects_symbols",
+    "aliases": [":flying_envelope:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "letter", "mail", "postal"]
+  },
+  "envelope_stamped": {
+    "unicode": "1F583",
+    "unicode_alternates": [],
+    "name": "stamped envelope",
+    "shortname": ":envelope_stamped:",
+    "category": "objects_symbols",
+    "aliases": [":stamped_envelope:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "letter", "mail", "postal"]
+  },
+  "envelope_stamped_pen": {
+    "unicode": "1F586",
+    "unicode_alternates": [],
+    "name": "pen over stamped envelope",
+    "shortname": ":envelope_stamped_pen:",
+    "category": "objects_symbols",
+    "aliases": [":pen_over_stamped_envelope:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "letter", "mail", "postal"]
+  },
+  "envelope_with_arrow": {
+    "unicode": "1F4E9",
+    "unicode_alternates": [],
+    "name": "envelope with downwards arrow above",
+    "shortname": ":envelope_with_arrow:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["email"],
+    "moji": "📩"
+  },
+  "euro": {
+    "unicode": "1F4B6",
+    "unicode_alternates": [],
+    "name": "banknote with euro sign",
+    "shortname": ":euro:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["currency", "dollar", "money", "euro", "europe", "banknote", "money", "currency", "paper", "cash", "bills"],
+    "moji": "💶"
+  },
+  "european_castle": {
+    "unicode": "1F3F0",
+    "unicode_alternates": [],
+    "name": "european castle",
+    "shortname": ":european_castle:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "history", "royalty", "castle", "european", "residence", "royalty", "disneyland", "disney", "fort", "fortified", "moat", "tower", "princess", "prince", "lord", "king", "queen", "fortress", "nobel", "stronghold"],
+    "moji": "🏰"
+  },
+  "european_post_office": {
+    "unicode": "1F3E4",
+    "unicode_alternates": [],
+    "name": "european post office",
+    "shortname": ":european_post_office:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building"],
+    "moji": "🏤"
+  },
+  "evergreen_tree": {
+    "unicode": "1F332",
+    "unicode_alternates": [],
+    "name": "evergreen tree",
+    "shortname": ":evergreen_tree:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "plant", "evergreen", "tree", "needles", "christmas"],
+    "moji": "🌲"
+  },
+  "exclamation": {
+    "unicode": "2757",
+    "unicode_alternates": ["2757-FE0F"],
+    "name": "heavy exclamation mark symbol",
+    "shortname": ":exclamation:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["surprise"],
+    "moji": "❗"
+  },
+  "expressionless": {
+    "unicode": "1F611",
+    "unicode_alternates": [],
+    "name": "expressionless face",
+    "shortname": ":expressionless:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["-_-", "-__-", "-___-"],
+    "keywords": ["expressionless", "blank", "void", "vapid", "without expression", "face", "indifferent"],
+    "moji": "😑"
+  },
+  "eye": {
+    "unicode": "1F441",
+    "unicode_alternates": [],
+    "name": "eye",
+    "shortname": ":eye:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["look", "peek", "watch"]
+  },
+  "eyeglasses": {
+    "unicode": "1F453",
+    "unicode_alternates": [],
+    "name": "eyeglasses",
+    "shortname": ":eyeglasses:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["accessories", "eyesight", "fashion", "eyeglasses", "spectacles", "eye", "sight", "nearsightedness", "myopia", "farsightedness", "hyperopia", "frames", "vision", "see", "blurry", "contacts"],
+    "moji": "👓"
+  },
+  "eyes": {
+    "unicode": "1F440",
+    "unicode_alternates": [],
+    "name": "eyes",
+    "shortname": ":eyes:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["look", "peek", "stalk", "watch"],
+    "moji": "👀"
+  },
+  "factory": {
+    "unicode": "1F3ED",
+    "unicode_alternates": [],
+    "name": "factory",
+    "shortname": ":factory:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building"],
+    "moji": "🏭"
+  },
+  "fallen_leaf": {
+    "unicode": "1F342",
+    "unicode_alternates": [],
+    "name": "fallen leaf",
+    "shortname": ":fallen_leaf:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["leaves", "nature", "plant", "vegetable", "leaf", "fall", "color", "deciduous", "autumn"],
+    "moji": "🍂"
+  },
+  "family": {
+    "unicode": "1F46A",
+    "unicode_alternates": [],
+    "name": "family",
+    "shortname": ":family:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["child", "dad", "father", "home", "mom", "mother", "parents", "family", "mother", "father", "child", "girl", "boy", "group", "unit"],
+    "moji": "👪"
+  },
+  "family_mmb": {
+    "unicode": "1F468-1F468-1F466",
+    "unicode_alternates": ["1F468-200D-1F468-200D-1F466"],
+    "name": "family (man,man,boy)",
+    "shortname": ":family_mmb:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["child", "dad", "father", "parents", "group", "unit", "gay", "homosexual", "man", "boy"]
+  },
+  "family_mmbb": {
+    "unicode": "1F468-1F468-1F466-1F466",
+    "unicode_alternates": ["1F468-200D-1F468-200D-1F466-200D-1F466"],
+    "name": "family (man,man,boy,boy)",
+    "shortname": ":family_mmbb:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["children", "dad", "father", "parents", "group", "unit", "gay", "homosexual", "man", "boy"]
+  },
+  "family_mmg": {
+    "unicode": "1F468-1F468-1F467",
+    "unicode_alternates": ["1F468-200D-1F468-200D-1F467"],
+    "name": "family (man,man,girl)",
+    "shortname": ":family_mmg:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["child", "dad", "father", "parents", "group", "unit", "gay", "homosexual", "man", "girl"]
+  },
+  "family_mmgb": {
+    "unicode": "1F468-1F468-1F467-1F466",
+    "unicode_alternates": ["1F468-200D-1F468-200D-1F467-200D-1F466"],
+    "name": "family (man,man,girl,boy)",
+    "shortname": ":family_mmgb:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["children", "dad", "father", "parents", "group", "unit", "gay", "homosexual", "man", "girl", "boy"]
+  },
+  "family_mmgg": {
+    "unicode": "1F468-1F468-1F467-1F467",
+    "unicode_alternates": ["1F468-200D-1F468-200D-1F467-200D-1F467"],
+    "name": "family (man,man,girl,girl)",
+    "shortname": ":family_mmgg:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["children", "dad", "father", "parents", "group", "unit", "gay", "homosexual", "man", "girl"]
+  },
+  "family_mwbb": {
+    "unicode": "1F468-1F469-1F466-1F466",
+    "unicode_alternates": ["1F468-200D-1F469-200D-1F466-200D-1F466"],
+    "name": "family (man,woman,boy,boy)",
+    "shortname": ":family_mwbb:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dad", "father", "mom", "mother", "parents", "children", "boy", "group", "unit", "man", "woman"]
+  },
+  "family_mwg": {
+    "unicode": "1F468-1F469-1F467",
+    "unicode_alternates": ["1F468-200D-1F469-200D-1F467"],
+    "name": "family (man,woman,girl)",
+    "shortname": ":family_mwg:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["child", "dad", "father", "mom", "mother", "parents", "girl", "boy", "group", "unit", "man", "woman"]
+  },
+  "family_mwgb": {
+    "unicode": "1F468-1F469-1F467-1F466",
+    "unicode_alternates": ["1F468-200D-1F469-200D-1F467-200D-1F466"],
+    "name": "family (man,woman,girl,boy)",
+    "shortname": ":family_mwgb:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dad", "father", "mom", "mother", "parents", "children", "girl", "boy", "group", "unit", "man", "woman"]
+  },
+  "family_mwgg": {
+    "unicode": "1F468-1F469-1F467-1F467",
+    "unicode_alternates": ["1F468-200D-1F469-200D-1F467-200D-1F467"],
+    "name": "family (man,woman,girl,girl)",
+    "shortname": ":family_mwgg:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dad", "father", "mom", "mother", "parents", "children", "girl", "group", "unit", "man", "woman"]
+  },
+  "family_wwb": {
+    "unicode": "1F469-1F469-1F466",
+    "unicode_alternates": ["1F469-200D-1F469-200D-1F466"],
+    "name": "family (woman,woman,boy)",
+    "shortname": ":family_wwb:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mom", "mother", "parents", "child", "boy", "group", "unit", "gay", "lesbian", "homosexual", "woman"]
+  },
+  "family_wwbb": {
+    "unicode": "1F469-1F469-1F466-1F466",
+    "unicode_alternates": ["1F469-200D-1F469-200D-1F466-200D-1F466"],
+    "name": "family (woman,woman,boy,boy)",
+    "shortname": ":family_wwbb:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mom", "mother", "parents", "children", "group", "unit", "gay", "lesbian", "homosexual", "woman", "boy"]
+  },
+  "family_wwg": {
+    "unicode": "1F469-1F469-1F467",
+    "unicode_alternates": ["1F469-200D-1F469-200D-1F467"],
+    "name": "family (woman,woman,girl)",
+    "shortname": ":family_wwg:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mom", "mother", "parents", "child", "woman", "girl", "group", "unit", "gay", "lesbian", "homosexual"]
+  },
+  "family_wwgb": {
+    "unicode": "1F469-1F469-1F467-1F466",
+    "unicode_alternates": ["1F469-200D-1F469-200D-1F467-200D-1F466"],
+    "name": "family (woman,woman,girl,boy)",
+    "shortname": ":family_wwgb:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mom", "mother", "parents", "children", "group", "unit", "gay", "lesbian", "homosexual", "woman", "girl", "boy"]
+  },
+  "family_wwgg": {
+    "unicode": "1F469-1F469-1F467-1F467",
+    "unicode_alternates": ["1F469-200D-1F469-200D-1F467-200D-1F467"],
+    "name": "family (woman,woman,girl,girl)",
+    "shortname": ":family_wwgg:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mom", "mother", "parents", "children", "group", "unit", "gay", "lesbian", "homosexual", "woman", "girl"]
+  },
+  "fast_forward": {
+    "unicode": "23E9",
+    "unicode_alternates": [],
+    "name": "black right-pointing double triangle",
+    "shortname": ":fast_forward:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "⏩"
+  },
+  "fax": {
+    "unicode": "1F4E0",
+    "unicode_alternates": [],
+    "name": "fax machine",
+    "shortname": ":fax:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "technology"],
+    "moji": "📠"
+  },
+  "fearful": {
+    "unicode": "1F628",
+    "unicode_alternates": [],
+    "name": "fearful face",
+    "shortname": ":fearful:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "nervous", "oops", "scared", "terrified", "fear", "fearful", "scared", "frightened"],
+    "moji": "😨"
+  },
+  "feet": {
+    "unicode": "1F43E",
+    "unicode_alternates": [],
+    "name": "paw prints",
+    "shortname": ":feet:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cat", "dog", "footprints", "paw", "pet", "tracking", "paw", "prints", "mark", "imprints", "footsteps", "animal", "lion", "bear", "dog", "cat", "raccoon", "critter", "feet", "pawsteps"],
+    "moji": "🐾"
+  },
+  "ferris_wheel": {
+    "unicode": "1F3A1",
+    "unicode_alternates": [],
+    "name": "ferris wheel",
+    "shortname": ":ferris_wheel:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["carnival", "londoneye", "photo", "farris", "wheel", "amusement", "park", "fair", "ride", "entertainment"],
+    "moji": "🎡"
+  },
+  "file_cabinet": {
+    "unicode": "1F5C4",
+    "unicode_alternates": [],
+    "name": "file cabinet",
+    "shortname": ":file_cabinet:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["folders", "office", "documents", "storage"]
+  },
+  "file_folder": {
+    "unicode": "1F4C1",
+    "unicode_alternates": [],
+    "name": "file folder",
+    "shortname": ":file_folder:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents"],
+    "moji": "📁"
+  },
+  "film_frames": {
+    "unicode": "1F39E",
+    "unicode_alternates": [],
+    "name": "film frames",
+    "shortname": ":film_frames:",
+    "category": "activity",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["movie", "record", "8mm", "16mm", "reel", "celluloid"]
+  },
+  "finger_pointing_down": {
+    "unicode": "1F597",
+    "unicode_alternates": [],
+    "name": "white down pointing left hand index",
+    "shortname": ":finger_pointing_down:",
+    "category": "people",
+    "aliases": [":white_down_pointing_left_hand_index:"],
+    "aliases_ascii": [],
+    "keywords": ["direction", "finger", "hand"]
+  },
+  "finger_pointing_down2": {
+    "unicode": "1F59F",
+    "unicode_alternates": [],
+    "name": "sideways white down pointing index",
+    "shortname": ":finger_pointing_down2:",
+    "category": "people",
+    "aliases": [":sideways_white_down_pointing_index:"],
+    "aliases_ascii": [],
+    "keywords": ["direction", "finger", "hand"]
+  },
+  "finger_pointing_left": {
+    "unicode": "1F598",
+    "unicode_alternates": [],
+    "name": "sideways white left pointing index",
+    "shortname": ":finger_pointing_left:",
+    "category": "people",
+    "aliases": [":sideways_white_left_pointing_index:"],
+    "aliases_ascii": [],
+    "keywords": ["direction", "finger", "hand"]
+  },
+  "finger_pointing_right": {
+    "unicode": "1F599",
+    "unicode_alternates": [],
+    "name": "sideways white right pointing index",
+    "shortname": ":finger_pointing_right:",
+    "category": "people",
+    "aliases": [":sideways_white_right_pointing_index:"],
+    "aliases_ascii": [],
+    "keywords": ["direction", "finger", "hand"]
+  },
+  "finger_pointing_up": {
+    "unicode": "1F59E",
+    "unicode_alternates": [],
+    "name": "sideways white up pointing index",
+    "shortname": ":finger_pointing_up:",
+    "category": "people",
+    "aliases": [":sideways_white_up_pointing_index:"],
+    "aliases_ascii": [],
+    "keywords": ["direction", "finger", "hand"]
+  },
+  "fire": {
+    "unicode": "1F525",
+    "unicode_alternates": [],
+    "name": "fire",
+    "shortname": ":fire:",
+    "category": "emoticons",
+    "aliases": [":flame:"],
+    "aliases_ascii": [],
+    "keywords": ["cook", "hot", "flame"],
+    "moji": "🔥"
+  },
+  "fire_engine": {
+    "unicode": "1F692",
+    "unicode_alternates": [],
+    "name": "fire engine",
+    "shortname": ":fire_engine:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cars", "transportation", "vehicle", "fire", "fighter", "engine", "truck", "emergency", "medical"],
+    "moji": "🚒"
+  },
+  "fire_engine_oncoming": {
+    "unicode": "1F6F1",
+    "unicode_alternates": [],
+    "name": "oncoming fire engine",
+    "shortname": ":fire_engine_oncoming:",
+    "category": "travel_places",
+    "aliases": [":oncoming_fire_engine:"],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "fighter", "truck", "emergency"]
+  },
+  "fireworks": {
+    "unicode": "1F386",
+    "unicode_alternates": [],
+    "name": "fireworks",
+    "shortname": ":fireworks:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["carnival", "congratulations", "festival", "photo", "fireworks", "independence", "celebration", "explosion", "july", "4th", "rocket", "sky", "idea", "excitement"],
+    "moji": "🎆"
+  },
+  "first_quarter_moon": {
+    "unicode": "1F313",
+    "unicode_alternates": [],
+    "name": "first quarter moon symbol",
+    "shortname": ":first_quarter_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "quarter", "first", "sky", "night", "cheese", "phase"],
+    "moji": "🌓"
+  },
+  "first_quarter_moon_with_face": {
+    "unicode": "1F31B",
+    "unicode_alternates": [],
+    "name": "first quarter moon with face",
+    "shortname": ":first_quarter_moon_with_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "first", "quarter", "anthropomorphic", "face", "sky", "night", "cheese", "phase"],
+    "moji": "🌛"
+  },
+  "fish": {
+    "unicode": "1F41F",
+    "unicode_alternates": [],
+    "name": "fish",
+    "shortname": ":fish:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "food", "nature"],
+    "moji": "🐟"
+  },
+  "fish_cake": {
+    "unicode": "1F365",
+    "unicode_alternates": [],
+    "name": "fish cake with swirl design",
+    "shortname": ":fish_cake:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fish", "cake", "kamboko", "swirl", "ramen", "noodles", "naruto"],
+    "moji": "🍥"
+  },
+  "fishing_pole_and_fish": {
+    "unicode": "1F3A3",
+    "unicode_alternates": [],
+    "name": "fishing pole and fish",
+    "shortname": ":fishing_pole_and_fish:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "hobby", "fish", "fishing", "pole"],
+    "moji": "🎣"
+  },
+  "fist": {
+    "unicode": "270A",
+    "unicode_alternates": [],
+    "name": "raised fist",
+    "shortname": ":fist:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fingers", "grasp", "hand"],
+    "moji": "✊"
+  },
+  "five": {
+    "moji": "5️⃣",
+    "unicode": "0035-20E3",
+    "unicode_alternates": ["0035-FE0F-20E3"],
+    "name": "digit five",
+    "shortname": ":five:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "numbers", "prime"]
+  },
+  "flag_ac": {
+    "unicode": "1F1E6-1F1E8",
+    "unicode_alternates": [],
+    "name": "ascension",
+    "shortname": ":flag_ac:",
+    "category": "flags",
+    "aliases": [":ac:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ac"]
+  },
+  "flag_ad": {
+    "unicode": "1F1E6-1F1E9",
+    "unicode_alternates": [],
+    "name": "andorra",
+    "shortname": ":flag_ad:",
+    "category": "flags",
+    "aliases": [":ad:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ad"]
+  },
+  "flag_ae": {
+    "unicode": "1F1E6-1F1EA",
+    "unicode_alternates": [],
+    "name": "the united arab emirates",
+    "shortname": ":flag_ae:",
+    "category": "flags",
+    "aliases": [":ae:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ae"]
+  },
+  "flag_af": {
+    "unicode": "1F1E6-1F1EB",
+    "unicode_alternates": [],
+    "name": "afghanistan",
+    "shortname": ":flag_af:",
+    "category": "flags",
+    "aliases": [":af:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "afghanestan", "af"]
+  },
+  "flag_ag": {
+    "unicode": "1F1E6-1F1EC",
+    "unicode_alternates": [],
+    "name": "antigua and barbuda",
+    "shortname": ":flag_ag:",
+    "category": "flags",
+    "aliases": [":ag:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ag"]
+  },
+  "flag_ai": {
+    "unicode": "1F1E6-1F1EE",
+    "unicode_alternates": [],
+    "name": "anguilla",
+    "shortname": ":flag_ai:",
+    "category": "flags",
+    "aliases": [":ai:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ai"]
+  },
+  "flag_al": {
+    "unicode": "1F1E6-1F1F1",
+    "unicode_alternates": [],
+    "name": "albania",
+    "shortname": ":flag_al:",
+    "category": "flags",
+    "aliases": [":al:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "shqiperia", "al"]
+  },
+  "flag_am": {
+    "unicode": "1F1E6-1F1F2",
+    "unicode_alternates": [],
+    "name": "armenia",
+    "shortname": ":flag_am:",
+    "category": "flags",
+    "aliases": [":am:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "hayastan", "am"]
+  },
+  "flag_ao": {
+    "unicode": "1F1E6-1F1F4",
+    "unicode_alternates": [],
+    "name": "angola",
+    "shortname": ":flag_ao:",
+    "category": "flags",
+    "aliases": [":ao:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ao"]
+  },
+  "flag_ar": {
+    "unicode": "1F1E6-1F1F7",
+    "unicode_alternates": [],
+    "name": "argentina",
+    "shortname": ":flag_ar:",
+    "category": "flags",
+    "aliases": [":ar:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ar"]
+  },
+  "flag_at": {
+    "unicode": "1F1E6-1F1F9",
+    "unicode_alternates": [],
+    "name": "austria",
+    "shortname": ":flag_at:",
+    "category": "flags",
+    "aliases": [":at:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "&ouml;sterreich", "osterreich", "at"]
+  },
+  "flag_au": {
+    "unicode": "1F1E6-1F1FA",
+    "unicode_alternates": [],
+    "name": "australia",
+    "shortname": ":flag_au:",
+    "category": "flags",
+    "aliases": [":au:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "au"]
+  },
+  "flag_aw": {
+    "unicode": "1F1E6-1F1FC",
+    "unicode_alternates": [],
+    "name": "aruba",
+    "shortname": ":flag_aw:",
+    "category": "flags",
+    "aliases": [":aw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "aw"]
+  },
+  "flag_az": {
+    "unicode": "1F1E6-1F1FF",
+    "unicode_alternates": [],
+    "name": "azerbaijan",
+    "shortname": ":flag_az:",
+    "category": "flags",
+    "aliases": [":az:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "azarbaycan", "az"]
+  },
+  "flag_ba": {
+    "unicode": "1F1E7-1F1E6",
+    "unicode_alternates": [],
+    "name": "bosnia and herzegovina",
+    "shortname": ":flag_ba:",
+    "category": "flags",
+    "aliases": [":ba:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bosna i hercegovina", "ba"]
+  },
+  "flag_bb": {
+    "unicode": "1F1E7-1F1E7",
+    "unicode_alternates": [],
+    "name": "barbados",
+    "shortname": ":flag_bb:",
+    "category": "flags",
+    "aliases": [":bb:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bb"]
+  },
+  "flag_bd": {
+    "unicode": "1F1E7-1F1E9",
+    "unicode_alternates": [],
+    "name": "bangladesh",
+    "shortname": ":flag_bd:",
+    "category": "flags",
+    "aliases": [":bd:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bd"]
+  },
+  "flag_be": {
+    "unicode": "1F1E7-1F1EA",
+    "unicode_alternates": [],
+    "name": "belgium",
+    "shortname": ":flag_be:",
+    "category": "flags",
+    "aliases": [":be:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "belgique", "belgie", "be"]
+  },
+  "flag_bf": {
+    "unicode": "1F1E7-1F1EB",
+    "unicode_alternates": [],
+    "name": "burkina faso",
+    "shortname": ":flag_bf:",
+    "category": "flags",
+    "aliases": [":bf:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bf"]
+  },
+  "flag_bg": {
+    "unicode": "1F1E7-1F1EC",
+    "unicode_alternates": [],
+    "name": "bulgaria",
+    "shortname": ":flag_bg:",
+    "category": "flags",
+    "aliases": [":bg:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bg"]
+  },
+  "flag_bh": {
+    "unicode": "1F1E7-1F1ED",
+    "unicode_alternates": [],
+    "name": "bahrain",
+    "shortname": ":flag_bh:",
+    "category": "flags",
+    "aliases": [":bh:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "al bahrayn", "bh"]
+  },
+  "flag_bi": {
+    "unicode": "1F1E7-1F1EE",
+    "unicode_alternates": [],
+    "name": "burundi",
+    "shortname": ":flag_bi:",
+    "category": "flags",
+    "aliases": [":bi:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bi"]
+  },
+  "flag_bj": {
+    "unicode": "1F1E7-1F1EF",
+    "unicode_alternates": [],
+    "name": "benin",
+    "shortname": ":flag_bj:",
+    "category": "flags",
+    "aliases": [":bj:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bj"]
+  },
+  "flag_black": {
+    "unicode": "1F3F4",
+    "unicode_alternates": [],
+    "name": "waving black flag",
+    "shortname": ":flag_black:",
+    "category": "objects_symbols",
+    "aliases": [":waving_black_flag:"],
+    "aliases_ascii": [],
+    "keywords": ["symbol", "signal"]
+  },
+  "flag_bm": {
+    "unicode": "1F1E7-1F1F2",
+    "unicode_alternates": [],
+    "name": "bermuda",
+    "shortname": ":flag_bm:",
+    "category": "flags",
+    "aliases": [":bm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bm"]
+  },
+  "flag_bn": {
+    "unicode": "1F1E7-1F1F3",
+    "unicode_alternates": [],
+    "name": "brunei",
+    "shortname": ":flag_bn:",
+    "category": "flags",
+    "aliases": [":bn:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bn"]
+  },
+  "flag_bo": {
+    "unicode": "1F1E7-1F1F4",
+    "unicode_alternates": [],
+    "name": "bolivia",
+    "shortname": ":flag_bo:",
+    "category": "flags",
+    "aliases": [":bo:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bo"]
+  },
+  "flag_br": {
+    "unicode": "1F1E7-1F1F7",
+    "unicode_alternates": [],
+    "name": "brazil",
+    "shortname": ":flag_br:",
+    "category": "flags",
+    "aliases": [":br:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "brasil", "br"]
+  },
+  "flag_bs": {
+    "unicode": "1F1E7-1F1F8",
+    "unicode_alternates": [],
+    "name": "the bahamas",
+    "shortname": ":flag_bs:",
+    "category": "flags",
+    "aliases": [":bs:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bs"]
+  },
+  "flag_bt": {
+    "unicode": "1F1E7-1F1F9",
+    "unicode_alternates": [],
+    "name": "bhutan",
+    "shortname": ":flag_bt:",
+    "category": "flags",
+    "aliases": [":bt:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bt"]
+  },
+  "flag_bw": {
+    "unicode": "1F1E7-1F1FC",
+    "unicode_alternates": [],
+    "name": "botswana",
+    "shortname": ":flag_bw:",
+    "category": "flags",
+    "aliases": [":bw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bw"]
+  },
+  "flag_by": {
+    "unicode": "1F1E7-1F1FE",
+    "unicode_alternates": [],
+    "name": "belarus",
+    "shortname": ":flag_by:",
+    "category": "flags",
+    "aliases": [":by:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "byelarus", "by"]
+  },
+  "flag_bz": {
+    "unicode": "1F1E7-1F1FF",
+    "unicode_alternates": [],
+    "name": "belize",
+    "shortname": ":flag_bz:",
+    "category": "flags",
+    "aliases": [":bz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bz"]
+  },
+  "flag_ca": {
+    "unicode": "1F1E8-1F1E6",
+    "unicode_alternates": [],
+    "name": "canada",
+    "shortname": ":flag_ca:",
+    "category": "flags",
+    "aliases": [":ca:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ca"]
+  },
+  "flag_cd": {
+    "unicode": "1F1E8-1F1E9",
+    "unicode_alternates": [],
+    "name": "the democratic republic of the congo",
+    "shortname": ":flag_cd:",
+    "category": "flags",
+    "aliases": [":congo:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "r&eacute;publique d&eacute;mocratique du congo", "republique democratique du congo", "cd"]
+  },
+  "flag_cf": {
+    "unicode": "1F1E8-1F1EB",
+    "unicode_alternates": [],
+    "name": "central african republic",
+    "shortname": ":flag_cf:",
+    "category": "flags",
+    "aliases": [":cf:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "cf"]
+  },
+  "flag_cg": {
+    "unicode": "1F1E8-1F1EC",
+    "unicode_alternates": [],
+    "name": "the republic of the congo",
+    "shortname": ":flag_cg:",
+    "category": "flags",
+    "aliases": [":cg:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "cg"]
+  },
+  "flag_ch": {
+    "unicode": "1F1E8-1F1ED",
+    "unicode_alternates": [],
+    "name": "switzerland",
+    "shortname": ":flag_ch:",
+    "category": "flags",
+    "aliases": [":ch:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "swiss"]
+  },
+  "flag_ci": {
+    "unicode": "1F1E8-1F1EE",
+    "unicode_alternates": [],
+    "name": "cote d'ivoire",
+    "shortname": ":flag_ci:",
+    "category": "flags",
+    "aliases": [":ci:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ci"]
+  },
+  "flag_cl": {
+    "unicode": "1F1E8-1F1F1",
+    "unicode_alternates": [],
+    "name": "chile",
+    "shortname": ":flag_cl:",
+    "category": "flags",
+    "aliases": [":chile:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "cl"]
+  },
+  "flag_cm": {
+    "unicode": "1F1E8-1F1F2",
+    "unicode_alternates": [],
+    "name": "cameroon",
+    "shortname": ":flag_cm:",
+    "category": "flags",
+    "aliases": [":cm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "cm"]
+  },
+  "flag_cn": {
+    "unicode": "1F1E8-1F1F3",
+    "unicode_alternates": [],
+    "name": "china",
+    "shortname": ":flag_cn:",
+    "category": "flags",
+    "aliases": [":cn:"],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "prc", "zhong guo", "country", "nation", "cn"]
+  },
+  "flag_co": {
+    "unicode": "1F1E8-1F1F4",
+    "unicode_alternates": [],
+    "name": "colombia",
+    "shortname": ":flag_co:",
+    "category": "flags",
+    "aliases": [":co:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "co"]
+  },
+  "flag_cr": {
+    "unicode": "1F1E8-1F1F7",
+    "unicode_alternates": [],
+    "name": "costa rica",
+    "shortname": ":flag_cr:",
+    "category": "flags",
+    "aliases": [":cr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "cr"]
+  },
+  "flag_cu": {
+    "unicode": "1F1E8-1F1FA",
+    "unicode_alternates": [],
+    "name": "cuba",
+    "shortname": ":flag_cu:",
+    "category": "flags",
+    "aliases": [":cu:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "cu"]
+  },
+  "flag_cv": {
+    "unicode": "1F1E8-1F1FB",
+    "unicode_alternates": [],
+    "name": "cape verde",
+    "shortname": ":flag_cv:",
+    "category": "flags",
+    "aliases": [":cv:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "cabo verde", "cv"]
+  },
+  "flag_cy": {
+    "unicode": "1F1E8-1F1FE",
+    "unicode_alternates": [],
+    "name": "cyprus",
+    "shortname": ":flag_cy:",
+    "category": "flags",
+    "aliases": [":cy:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "kibris", "kypros", "cy"]
+  },
+  "flag_cz": {
+    "unicode": "1F1E8-1F1FF",
+    "unicode_alternates": [],
+    "name": "the czech republic",
+    "shortname": ":flag_cz:",
+    "category": "flags",
+    "aliases": [":cz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ceska republika", "cz"]
+  },
+  "flag_de": {
+    "unicode": "1F1E9-1F1EA",
+    "unicode_alternates": [],
+    "name": "germany",
+    "shortname": ":flag_de:",
+    "category": "flags",
+    "aliases": [":de:"],
+    "aliases_ascii": [],
+    "keywords": ["german", "nation", "deutschland", "country", "de"]
+  },
+  "flag_dj": {
+    "unicode": "1F1E9-1F1EF",
+    "unicode_alternates": [],
+    "name": "djibouti",
+    "shortname": ":flag_dj:",
+    "category": "flags",
+    "aliases": [":dj:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "dj"]
+  },
+  "flag_dk": {
+    "unicode": "1F1E9-1F1F0",
+    "unicode_alternates": [],
+    "name": "denmark",
+    "shortname": ":flag_dk:",
+    "category": "flags",
+    "aliases": [":dk:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "danmark", "dk"]
+  },
+  "flag_dm": {
+    "unicode": "1F1E9-1F1F2",
+    "unicode_alternates": [],
+    "name": "dominica",
+    "shortname": ":flag_dm:",
+    "category": "flags",
+    "aliases": [":dm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "dm"]
+  },
+  "flag_do": {
+    "unicode": "1F1E9-1F1F4",
+    "unicode_alternates": [],
+    "name": "the dominican republic",
+    "shortname": ":flag_do:",
+    "category": "flags",
+    "aliases": [":do:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "do"]
+  },
+  "flag_dz": {
+    "unicode": "1F1E9-1F1FF",
+    "unicode_alternates": [],
+    "name": "algeria",
+    "shortname": ":flag_dz:",
+    "category": "flags",
+    "aliases": [":dz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "al jaza'ir", "al jazair", "dz"]
+  },
+  "flag_ec": {
+    "unicode": "1F1EA-1F1E8",
+    "unicode_alternates": [],
+    "name": "ecuador",
+    "shortname": ":flag_ec:",
+    "category": "flags",
+    "aliases": [":ec:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ec"]
+  },
+  "flag_ee": {
+    "unicode": "1F1EA-1F1EA",
+    "unicode_alternates": [],
+    "name": "estonia",
+    "shortname": ":flag_ee:",
+    "category": "flags",
+    "aliases": [":ee:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "eesti vabariik", "ee"]
+  },
+  "flag_eg": {
+    "unicode": "1F1EA-1F1EC",
+    "unicode_alternates": [],
+    "name": "egypt",
+    "shortname": ":flag_eg:",
+    "category": "flags",
+    "aliases": [":eg:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "misr", "eg"]
+  },
+  "flag_eh": {
+    "unicode": "1F1EA-1F1ED",
+    "unicode_alternates": [],
+    "name": "western sahara",
+    "shortname": ":flag_eh:",
+    "category": "flags",
+    "aliases": [":eh:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "aṣ-Ṣaḥrā’ al-gharbīyah", "sahra", "gharbiyah", "eh"]
+  },
+  "flag_er": {
+    "unicode": "1F1EA-1F1F7",
+    "unicode_alternates": [],
+    "name": "eritrea",
+    "shortname": ":flag_er:",
+    "category": "flags",
+    "aliases": [":er:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "hagere ertra", "er"]
+  },
+  "flag_es": {
+    "unicode": "1F1EA-1F1F8",
+    "unicode_alternates": [],
+    "name": "spain",
+    "shortname": ":flag_es:",
+    "category": "flags",
+    "aliases": [":es:"],
+    "aliases_ascii": [],
+    "keywords": ["nation", "espa&ntilde;a", "country", "espana", "es"]
+  },
+  "flag_et": {
+    "unicode": "1F1EA-1F1F9",
+    "unicode_alternates": [],
+    "name": "ethiopia",
+    "shortname": ":flag_et:",
+    "category": "flags",
+    "aliases": [":et:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ityop'iya", "ityopiya", "et"]
+  },
+  "flag_fi": {
+    "unicode": "1F1EB-1F1EE",
+    "unicode_alternates": [],
+    "name": "finland",
+    "shortname": ":flag_fi:",
+    "category": "flags",
+    "aliases": [":fi:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "suomen tasavalta", "fi"]
+  },
+  "flag_fj": {
+    "unicode": "1F1EB-1F1EF",
+    "unicode_alternates": [],
+    "name": "fiji",
+    "shortname": ":flag_fj:",
+    "category": "flags",
+    "aliases": [":fj:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "fj"]
+  },
+  "flag_fk": {
+    "unicode": "1F1EB-1F1F0",
+    "unicode_alternates": [],
+    "name": "falkland islands",
+    "shortname": ":flag_fk:",
+    "category": "flags",
+    "aliases": [":fk:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "islas malvinas", "fk"]
+  },
+  "flag_fm": {
+    "unicode": "1F1EB-1F1F2",
+    "unicode_alternates": [],
+    "name": "micronesia",
+    "shortname": ":flag_fm:",
+    "category": "flags",
+    "aliases": [":fm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "fm"]
+  },
+  "flag_fo": {
+    "unicode": "1F1EB-1F1F4",
+    "unicode_alternates": [],
+    "name": "faroe islands",
+    "shortname": ":flag_fo:",
+    "category": "flags",
+    "aliases": [":fo:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "foroyar", "fo"]
+  },
+  "flag_fr": {
+    "unicode": "1F1EB-1F1F7",
+    "unicode_alternates": [],
+    "name": "france",
+    "shortname": ":flag_fr:",
+    "category": "flags",
+    "aliases": [":fr:"],
+    "aliases_ascii": [],
+    "keywords": ["french", "nation", "country", "fr"]
+  },
+  "flag_ga": {
+    "unicode": "1F1EC-1F1E6",
+    "unicode_alternates": [],
+    "name": "gabon",
+    "shortname": ":flag_ga:",
+    "category": "flags",
+    "aliases": [":ga:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ga"]
+  },
+  "flag_gb": {
+    "unicode": "1F1EC-1F1E7",
+    "unicode_alternates": [],
+    "name": "great britain",
+    "shortname": ":flag_gb:",
+    "category": "flags",
+    "aliases": [":gb:"],
+    "aliases_ascii": [],
+    "keywords": ["UK", "gb", "britsh", "nation", "united kingdom", "england", "country"]
+  },
+  "flag_gd": {
+    "unicode": "1F1EC-1F1E9",
+    "unicode_alternates": [],
+    "name": "grenada",
+    "shortname": ":flag_gd:",
+    "category": "flags",
+    "aliases": [":gd:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "gd"]
+  },
+  "flag_ge": {
+    "unicode": "1F1EC-1F1EA",
+    "unicode_alternates": [],
+    "name": "georgia",
+    "shortname": ":flag_ge:",
+    "category": "flags",
+    "aliases": [":ge:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sak'art'velo", "sakartvelo", "ge"]
+  },
+  "flag_gh": {
+    "unicode": "1F1EC-1F1ED",
+    "unicode_alternates": [],
+    "name": "ghana",
+    "shortname": ":flag_gh:",
+    "category": "flags",
+    "aliases": [":gh:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "gh"]
+  },
+  "flag_gi": {
+    "unicode": "1F1EC-1F1EE",
+    "unicode_alternates": [],
+    "name": "gibraltar",
+    "shortname": ":flag_gi:",
+    "category": "flags",
+    "aliases": [":gi:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "gi"]
+  },
+  "flag_gl": {
+    "unicode": "1F1EC-1F1F1",
+    "unicode_alternates": [],
+    "name": "greenland",
+    "shortname": ":flag_gl:",
+    "category": "flags",
+    "aliases": [":gl:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "kalaallit nunaat", "gl"]
+  },
+  "flag_gm": {
+    "unicode": "1F1EC-1F1F2",
+    "unicode_alternates": [],
+    "name": "the gambia",
+    "shortname": ":flag_gm:",
+    "category": "flags",
+    "aliases": [":gm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "gm"]
+  },
+  "flag_gn": {
+    "unicode": "1F1EC-1F1F3",
+    "unicode_alternates": [],
+    "name": "guinea",
+    "shortname": ":flag_gn:",
+    "category": "flags",
+    "aliases": [":gn:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "guinee", "gn"]
+  },
+  "flag_gq": {
+    "unicode": "1F1EC-1F1F6",
+    "unicode_alternates": [],
+    "name": "equatorial guinea",
+    "shortname": ":flag_gq:",
+    "category": "flags",
+    "aliases": [":gq:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "guinea ecuatorial", "gq"]
+  },
+  "flag_gr": {
+    "unicode": "1F1EC-1F1F7",
+    "unicode_alternates": [],
+    "name": "greece",
+    "shortname": ":flag_gr:",
+    "category": "flags",
+    "aliases": [":gr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ellas", "ellada", "gr"]
+  },
+  "flag_gt": {
+    "unicode": "1F1EC-1F1F9",
+    "unicode_alternates": [],
+    "name": "guatemala",
+    "shortname": ":flag_gt:",
+    "category": "flags",
+    "aliases": [":gt:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "gt"]
+  },
+  "flag_gu": {
+    "unicode": "1F1EC-1F1FA",
+    "unicode_alternates": [],
+    "name": "guam",
+    "shortname": ":flag_gu:",
+    "category": "flags",
+    "aliases": [":gu:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "gu"]
+  },
+  "flag_gw": {
+    "unicode": "1F1EC-1F1FC",
+    "unicode_alternates": [],
+    "name": "guinea-bissau",
+    "shortname": ":flag_gw:",
+    "category": "flags",
+    "aliases": [":gw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "guine-bissau", "guine bissau", "gw"]
+  },
+  "flag_gy": {
+    "unicode": "1F1EC-1F1FE",
+    "unicode_alternates": [],
+    "name": "guyana",
+    "shortname": ":flag_gy:",
+    "category": "flags",
+    "aliases": [":gy:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "gy"]
+  },
+  "flag_hk": {
+    "unicode": "1F1ED-1F1F0",
+    "unicode_alternates": [],
+    "name": "hong kong",
+    "shortname": ":flag_hk:",
+    "category": "flags",
+    "aliases": [":hk:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "xianggang", "hk"]
+  },
+  "flag_hn": {
+    "unicode": "1F1ED-1F1F3",
+    "unicode_alternates": [],
+    "name": "honduras",
+    "shortname": ":flag_hn:",
+    "category": "flags",
+    "aliases": [":hn:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "hn"]
+  },
+  "flag_hr": {
+    "unicode": "1F1ED-1F1F7",
+    "unicode_alternates": [],
+    "name": "croatia",
+    "shortname": ":flag_hr:",
+    "category": "flags",
+    "aliases": [":hr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "hrvatska", "hr"]
+  },
+  "flag_ht": {
+    "unicode": "1F1ED-1F1F9",
+    "unicode_alternates": [],
+    "name": "haiti",
+    "shortname": ":flag_ht:",
+    "category": "flags",
+    "aliases": [":ht:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ht"]
+  },
+  "flag_hu": {
+    "unicode": "1F1ED-1F1FA",
+    "unicode_alternates": [],
+    "name": "hungary",
+    "shortname": ":flag_hu:",
+    "category": "flags",
+    "aliases": [":hu:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "magyarorszag", "hu"]
+  },
+  "flag_id": {
+    "unicode": "1F1EE-1F1E9",
+    "unicode_alternates": [],
+    "name": "indonesia",
+    "shortname": ":flag_id:",
+    "category": "flags",
+    "aliases": [":indonesia:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "id"]
+  },
+  "flag_ie": {
+    "unicode": "1F1EE-1F1EA",
+    "unicode_alternates": [],
+    "name": "ireland",
+    "shortname": ":flag_ie:",
+    "category": "flags",
+    "aliases": [":ie:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "&eacute;ire", "eire", "ie"]
+  },
+  "flag_il": {
+    "unicode": "1F1EE-1F1F1",
+    "unicode_alternates": [],
+    "name": "israel",
+    "shortname": ":flag_il:",
+    "category": "flags",
+    "aliases": [":il:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "yisra'el", "yisrael", "il"]
+  },
+  "flag_in": {
+    "unicode": "1F1EE-1F1F3",
+    "unicode_alternates": [],
+    "name": "india",
+    "shortname": ":flag_in:",
+    "category": "flags",
+    "aliases": [":in:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "bharat", "in"]
+  },
+  "flag_iq": {
+    "unicode": "1F1EE-1F1F6",
+    "unicode_alternates": [],
+    "name": "iraq",
+    "shortname": ":flag_iq:",
+    "category": "flags",
+    "aliases": [":iq:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "iq"]
+  },
+  "flag_ir": {
+    "unicode": "1F1EE-1F1F7",
+    "unicode_alternates": [],
+    "name": "iran",
+    "shortname": ":flag_ir:",
+    "category": "flags",
+    "aliases": [":ir:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ir"]
+  },
+  "flag_is": {
+    "unicode": "1F1EE-1F1F8",
+    "unicode_alternates": [],
+    "name": "iceland",
+    "shortname": ":flag_is:",
+    "category": "flags",
+    "aliases": [":is:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "lyoveldio island", "is"]
+  },
+  "flag_it": {
+    "unicode": "1F1EE-1F1F9",
+    "unicode_alternates": [],
+    "name": "italy",
+    "shortname": ":flag_it:",
+    "category": "flags",
+    "aliases": [":it:"],
+    "aliases_ascii": [],
+    "keywords": ["italia", "country", "nation", "it"]
+  },
+  "flag_je": {
+    "unicode": "1F1EF-1F1EA",
+    "unicode_alternates": [],
+    "name": "jersey",
+    "shortname": ":flag_je:",
+    "category": "flags",
+    "aliases": [":je:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "je"]
+  },
+  "flag_jm": {
+    "unicode": "1F1EF-1F1F2",
+    "unicode_alternates": [],
+    "name": "jamaica",
+    "shortname": ":flag_jm:",
+    "category": "flags",
+    "aliases": [":jm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "jm"]
+  },
+  "flag_jo": {
+    "unicode": "1F1EF-1F1F4",
+    "unicode_alternates": [],
+    "name": "jordan",
+    "shortname": ":flag_jo:",
+    "category": "flags",
+    "aliases": [":jo:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "al urdun", "jo"]
+  },
+  "flag_jp": {
+    "unicode": "1F1EF-1F1F5",
+    "unicode_alternates": [],
+    "name": "japan",
+    "shortname": ":flag_jp:",
+    "category": "flags",
+    "aliases": [":jp:"],
+    "aliases_ascii": [],
+    "keywords": ["nation", "nippon", "country", "jp"]
+  },
+  "flag_ke": {
+    "unicode": "1F1F0-1F1EA",
+    "unicode_alternates": [],
+    "name": "kenya",
+    "shortname": ":flag_ke:",
+    "category": "flags",
+    "aliases": [":ke:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ke"]
+  },
+  "flag_kg": {
+    "unicode": "1F1F0-1F1EC",
+    "unicode_alternates": [],
+    "name": "kyrgyzstan",
+    "shortname": ":flag_kg:",
+    "category": "flags",
+    "aliases": [":kg:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "kyrgyz respublikasy", "kg"]
+  },
+  "flag_kh": {
+    "unicode": "1F1F0-1F1ED",
+    "unicode_alternates": [],
+    "name": "cambodia",
+    "shortname": ":flag_kh:",
+    "category": "flags",
+    "aliases": [":kh:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "kampuchea", "kh"]
+  },
+  "flag_ki": {
+    "unicode": "1F1F0-1F1EE",
+    "unicode_alternates": [],
+    "name": "kiribati",
+    "shortname": ":flag_ki:",
+    "category": "flags",
+    "aliases": [":ki:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "kiribati", "kiribas", "ki"]
+  },
+  "flag_km": {
+    "unicode": "1F1F0-1F1F2",
+    "unicode_alternates": [],
+    "name": "the comoros",
+    "shortname": ":flag_km:",
+    "category": "flags",
+    "aliases": [":km:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "km"]
+  },
+  "flag_kn": {
+    "unicode": "1F1F0-1F1F3",
+    "unicode_alternates": [],
+    "name": "saint kitts and nevis",
+    "shortname": ":flag_kn:",
+    "category": "flags",
+    "aliases": [":kn:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "kn"]
+  },
+  "flag_kp": {
+    "unicode": "1F1F0-1F1F5",
+    "unicode_alternates": [],
+    "name": "north korea",
+    "shortname": ":flag_kp:",
+    "category": "flags",
+    "aliases": [":kp:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "kp"]
+  },
+  "flag_kr": {
+    "unicode": "1F1F0-1F1F7",
+    "unicode_alternates": [],
+    "name": "korea",
+    "shortname": ":flag_kr:",
+    "category": "flags",
+    "aliases": [":kr:"],
+    "aliases_ascii": [],
+    "keywords": ["nation", "country", "south korea", "kr"]
+  },
+  "flag_kw": {
+    "unicode": "1F1F0-1F1FC",
+    "unicode_alternates": [],
+    "name": "kuwait",
+    "shortname": ":flag_kw:",
+    "category": "flags",
+    "aliases": [":kw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "al kuwayt", "kw"]
+  },
+  "flag_ky": {
+    "unicode": "1F1F0-1F1FE",
+    "unicode_alternates": [],
+    "name": "cayman islands",
+    "shortname": ":flag_ky:",
+    "category": "flags",
+    "aliases": [":ky:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ky"]
+  },
+  "flag_kz": {
+    "unicode": "1F1F0-1F1FF",
+    "unicode_alternates": [],
+    "name": "kazakhstan",
+    "shortname": ":flag_kz:",
+    "category": "flags",
+    "aliases": [":kz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "qazaqstan", "kz"]
+  },
+  "flag_la": {
+    "unicode": "1F1F1-1F1E6",
+    "unicode_alternates": [],
+    "name": "laos",
+    "shortname": ":flag_la:",
+    "category": "flags",
+    "aliases": [":la:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "la"]
+  },
+  "flag_lb": {
+    "unicode": "1F1F1-1F1E7",
+    "unicode_alternates": [],
+    "name": "lebanon",
+    "shortname": ":flag_lb:",
+    "category": "flags",
+    "aliases": [":lb:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "lubnan", "lb"]
+  },
+  "flag_lc": {
+    "unicode": "1F1F1-1F1E8",
+    "unicode_alternates": [],
+    "name": "saint lucia",
+    "shortname": ":flag_lc:",
+    "category": "flags",
+    "aliases": [":lc:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "lc"]
+  },
+  "flag_li": {
+    "unicode": "1F1F1-1F1EE",
+    "unicode_alternates": [],
+    "name": "liechtenstein",
+    "shortname": ":flag_li:",
+    "category": "flags",
+    "aliases": [":li:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "li"]
+  },
+  "flag_lk": {
+    "unicode": "1F1F1-1F1F0",
+    "unicode_alternates": [],
+    "name": "sri lanka",
+    "shortname": ":flag_lk:",
+    "category": "flags",
+    "aliases": [":lk:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "lk"]
+  },
+  "flag_lr": {
+    "unicode": "1F1F1-1F1F7",
+    "unicode_alternates": [],
+    "name": "liberia",
+    "shortname": ":flag_lr:",
+    "category": "flags",
+    "aliases": [":lr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "lr"]
+  },
+  "flag_ls": {
+    "unicode": "1F1F1-1F1F8",
+    "unicode_alternates": [],
+    "name": "lesotho",
+    "shortname": ":flag_ls:",
+    "category": "flags",
+    "aliases": [":ls:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ls"]
+  },
+  "flag_lt": {
+    "unicode": "1F1F1-1F1F9",
+    "unicode_alternates": [],
+    "name": "lithuania",
+    "shortname": ":flag_lt:",
+    "category": "flags",
+    "aliases": [":lt:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "lietuva", "lt"]
+  },
+  "flag_lu": {
+    "unicode": "1F1F1-1F1FA",
+    "unicode_alternates": [],
+    "name": "luxembourg",
+    "shortname": ":flag_lu:",
+    "category": "flags",
+    "aliases": [":lu:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "luxembourg", "letzebuerg", "lu"]
+  },
+  "flag_lv": {
+    "unicode": "1F1F1-1F1FB",
+    "unicode_alternates": [],
+    "name": "latvia",
+    "shortname": ":flag_lv:",
+    "category": "flags",
+    "aliases": [":lv:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "latvija", "lv"]
+  },
+  "flag_ly": {
+    "unicode": "1F1F1-1F1FE",
+    "unicode_alternates": [],
+    "name": "libya",
+    "shortname": ":flag_ly:",
+    "category": "flags",
+    "aliases": [":ly:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "libiyah", "ly"]
+  },
+  "flag_ma": {
+    "unicode": "1F1F2-1F1E6",
+    "unicode_alternates": [],
+    "name": "morocco",
+    "shortname": ":flag_ma:",
+    "category": "flags",
+    "aliases": [":ma:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "al maghrib", "ma"]
+  },
+  "flag_mc": {
+    "unicode": "1F1F2-1F1E8",
+    "unicode_alternates": [],
+    "name": "monaco",
+    "shortname": ":flag_mc:",
+    "category": "flags",
+    "aliases": [":mc:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mc"]
+  },
+  "flag_md": {
+    "unicode": "1F1F2-1F1E9",
+    "unicode_alternates": [],
+    "name": "moldova",
+    "shortname": ":flag_md:",
+    "category": "flags",
+    "aliases": [":md:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "md"]
+  },
+  "flag_me": {
+    "unicode": "1F1F2-1F1EA",
+    "unicode_alternates": [],
+    "name": "montenegro",
+    "shortname": ":flag_me:",
+    "category": "flags",
+    "aliases": [":me:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "crna gora", "me"]
+  },
+  "flag_mg": {
+    "unicode": "1F1F2-1F1EC",
+    "unicode_alternates": [],
+    "name": "madagascar",
+    "shortname": ":flag_mg:",
+    "category": "flags",
+    "aliases": [":mg:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mg"]
+  },
+  "flag_mh": {
+    "unicode": "1F1F2-1F1ED",
+    "unicode_alternates": [],
+    "name": "the marshall islands",
+    "shortname": ":flag_mh:",
+    "category": "flags",
+    "aliases": [":mh:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mh"]
+  },
+  "flag_mk": {
+    "unicode": "1F1F2-1F1F0",
+    "unicode_alternates": [],
+    "name": "macedonia",
+    "shortname": ":flag_mk:",
+    "category": "flags",
+    "aliases": [":mk:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mk"]
+  },
+  "flag_ml": {
+    "unicode": "1F1F2-1F1F1",
+    "unicode_alternates": [],
+    "name": "mali",
+    "shortname": ":flag_ml:",
+    "category": "flags",
+    "aliases": [":ml:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ml"]
+  },
+  "flag_mm": {
+    "unicode": "1F1F2-1F1F2",
+    "unicode_alternates": [],
+    "name": "myanmar",
+    "shortname": ":flag_mm:",
+    "category": "flags",
+    "aliases": [":mm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "myanma naingngandaw", "mm"]
+  },
+  "flag_mn": {
+    "unicode": "1F1F2-1F1F3",
+    "unicode_alternates": [],
+    "name": "mongolia",
+    "shortname": ":flag_mn:",
+    "category": "flags",
+    "aliases": [":mn:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mongol uls", "mn"]
+  },
+  "flag_mo": {
+    "unicode": "1F1F2-1F1F4",
+    "unicode_alternates": [],
+    "name": "macau",
+    "shortname": ":flag_mo:",
+    "category": "flags",
+    "aliases": [":mo:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "aomen", "mo"]
+  },
+  "flag_mr": {
+    "unicode": "1F1F2-1F1F7",
+    "unicode_alternates": [],
+    "name": "mauritania",
+    "shortname": ":flag_mr:",
+    "category": "flags",
+    "aliases": [":mr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "muritaniyah", "mr"]
+  },
+  "flag_ms": {
+    "unicode": "1F1F2-1F1F8",
+    "unicode_alternates": [],
+    "name": "montserrat",
+    "shortname": ":flag_ms:",
+    "category": "flags",
+    "aliases": [":ms:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ms"]
+  },
+  "flag_mt": {
+    "unicode": "1F1F2-1F1F9",
+    "unicode_alternates": [],
+    "name": "malta",
+    "shortname": ":flag_mt:",
+    "category": "flags",
+    "aliases": [":mt:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mt"]
+  },
+  "flag_mu": {
+    "unicode": "1F1F2-1F1FA",
+    "unicode_alternates": [],
+    "name": "mauritius",
+    "shortname": ":flag_mu:",
+    "category": "flags",
+    "aliases": [":mu:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mu"]
+  },
+  "flag_mv": {
+    "unicode": "1F1F2-1F1FB",
+    "unicode_alternates": [],
+    "name": "maldives",
+    "shortname": ":flag_mv:",
+    "category": "flags",
+    "aliases": [":mv:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "dhivehi raajje", "mv"]
+  },
+  "flag_mw": {
+    "unicode": "1F1F2-1F1FC",
+    "unicode_alternates": [],
+    "name": "malawi",
+    "shortname": ":flag_mw:",
+    "category": "flags",
+    "aliases": [":mw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mw"]
+  },
+  "flag_mx": {
+    "unicode": "1F1F2-1F1FD",
+    "unicode_alternates": [],
+    "name": "mexico",
+    "shortname": ":flag_mx:",
+    "category": "flags",
+    "aliases": [":mx:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mx"]
+  },
+  "flag_my": {
+    "unicode": "1F1F2-1F1FE",
+    "unicode_alternates": [],
+    "name": "malaysia",
+    "shortname": ":flag_my:",
+    "category": "flags",
+    "aliases": [":my:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "my"]
+  },
+  "flag_mz": {
+    "unicode": "1F1F2-1F1FF",
+    "unicode_alternates": [],
+    "name": "mozambique",
+    "shortname": ":flag_mz:",
+    "category": "flags",
+    "aliases": [":mz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "mocambique", "mz"]
+  },
+  "flag_na": {
+    "unicode": "1F1F3-1F1E6",
+    "unicode_alternates": [],
+    "name": "namibia",
+    "shortname": ":flag_na:",
+    "category": "flags",
+    "aliases": [":na:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "na"]
+  },
+  "flag_nc": {
+    "unicode": "1F1F3-1F1E8",
+    "unicode_alternates": [],
+    "name": "new caledonia",
+    "shortname": ":flag_nc:",
+    "category": "flags",
+    "aliases": [":nc:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "nouvelle", "cal&eacute;donie", "caledonie", "nc"]
+  },
+  "flag_ne": {
+    "unicode": "1F1F3-1F1EA",
+    "unicode_alternates": [],
+    "name": "niger",
+    "shortname": ":flag_ne:",
+    "category": "flags",
+    "aliases": [":ne:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ne"]
+  },
+  "flag_ng": {
+    "unicode": "1F1F3-1F1EC",
+    "unicode_alternates": [],
+    "name": "nigeria",
+    "shortname": ":flag_ng:",
+    "category": "flags",
+    "aliases": [":nigeria:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ng"]
+  },
+  "flag_ni": {
+    "unicode": "1F1F3-1F1EE",
+    "unicode_alternates": [],
+    "name": "nicaragua",
+    "shortname": ":flag_ni:",
+    "category": "flags",
+    "aliases": [":ni:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ni"]
+  },
+  "flag_nl": {
+    "unicode": "1F1F3-1F1F1",
+    "unicode_alternates": [],
+    "name": "the netherlands",
+    "shortname": ":flag_nl:",
+    "category": "flags",
+    "aliases": [":nl:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "nederland", "holland", "nl"]
+  },
+  "flag_no": {
+    "unicode": "1F1F3-1F1F4",
+    "unicode_alternates": [],
+    "name": "norway",
+    "shortname": ":flag_no:",
+    "category": "flags",
+    "aliases": [":no:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "norge", "no"]
+  },
+  "flag_np": {
+    "unicode": "1F1F3-1F1F5",
+    "unicode_alternates": [],
+    "name": "nepal",
+    "shortname": ":flag_np:",
+    "category": "flags",
+    "aliases": [":np:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "np"]
+  },
+  "flag_nr": {
+    "unicode": "1F1F3-1F1F7",
+    "unicode_alternates": [],
+    "name": "nauru",
+    "shortname": ":flag_nr:",
+    "category": "flags",
+    "aliases": [":nr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "nr"]
+  },
+  "flag_nu": {
+    "unicode": "1F1F3-1F1FA",
+    "unicode_alternates": [],
+    "name": "niue",
+    "shortname": ":flag_nu:",
+    "category": "flags",
+    "aliases": [":nu:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "nu"]
+  },
+  "flag_nz": {
+    "unicode": "1F1F3-1F1FF",
+    "unicode_alternates": [],
+    "name": "new zealand",
+    "shortname": ":flag_nz:",
+    "category": "flags",
+    "aliases": [":nz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "aotearoa", "nz"]
+  },
+  "flag_om": {
+    "unicode": "1F1F4-1F1F2",
+    "unicode_alternates": [],
+    "name": "oman",
+    "shortname": ":flag_om:",
+    "category": "flags",
+    "aliases": [":om:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "saltanat uman", "om"]
+  },
+  "flag_pa": {
+    "unicode": "1F1F5-1F1E6",
+    "unicode_alternates": [],
+    "name": "panama",
+    "shortname": ":flag_pa:",
+    "category": "flags",
+    "aliases": [":pa:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "pa"]
+  },
+  "flag_pe": {
+    "unicode": "1F1F5-1F1EA",
+    "unicode_alternates": [],
+    "name": "peru",
+    "shortname": ":flag_pe:",
+    "category": "flags",
+    "aliases": [":pe:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "pe"]
+  },
+  "flag_pf": {
+    "unicode": "1F1F5-1F1EB",
+    "unicode_alternates": [],
+    "name": "french polynesia",
+    "shortname": ":flag_pf:",
+    "category": "flags",
+    "aliases": [":pf:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "polyn&eacute;sie fran&ccedil;aise", "polynesie francaise", "pf"]
+  },
+  "flag_pg": {
+    "unicode": "1F1F5-1F1EC",
+    "unicode_alternates": [],
+    "name": "papua new guinea",
+    "shortname": ":flag_pg:",
+    "category": "flags",
+    "aliases": [":pg:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "papua niu gini", "pg"]
+  },
+  "flag_ph": {
+    "unicode": "1F1F5-1F1ED",
+    "unicode_alternates": [],
+    "name": "the philippines",
+    "shortname": ":flag_ph:",
+    "category": "flags",
+    "aliases": [":ph:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "pilipinas", "ph"]
+  },
+  "flag_pk": {
+    "unicode": "1F1F5-1F1F0",
+    "unicode_alternates": [],
+    "name": "pakistan",
+    "shortname": ":flag_pk:",
+    "category": "flags",
+    "aliases": [":pk:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "pk"]
+  },
+  "flag_pl": {
+    "unicode": "1F1F5-1F1F1",
+    "unicode_alternates": [],
+    "name": "poland",
+    "shortname": ":flag_pl:",
+    "category": "flags",
+    "aliases": [":pl:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "polska", "pl"]
+  },
+  "flag_pr": {
+    "unicode": "1F1F5-1F1F7",
+    "unicode_alternates": [],
+    "name": "puerto rico",
+    "shortname": ":flag_pr:",
+    "category": "flags",
+    "aliases": [":pr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "pr"]
+  },
+  "flag_ps": {
+    "unicode": "1F1F5-1F1F8",
+    "unicode_alternates": [],
+    "name": "palestinian authority",
+    "shortname": ":flag_ps:",
+    "category": "flags",
+    "aliases": [":ps:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ps"]
+  },
+  "flag_pt": {
+    "unicode": "1F1F5-1F1F9",
+    "unicode_alternates": [],
+    "name": "portugal",
+    "shortname": ":flag_pt:",
+    "category": "flags",
+    "aliases": [":pt:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "pt"]
+  },
+  "flag_pw": {
+    "unicode": "1F1F5-1F1FC",
+    "unicode_alternates": [],
+    "name": "palau",
+    "shortname": ":flag_pw:",
+    "category": "flags",
+    "aliases": [":pw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "belau", "pw"]
+  },
+  "flag_py": {
+    "unicode": "1F1F5-1F1FE",
+    "unicode_alternates": [],
+    "name": "paraguay",
+    "shortname": ":flag_py:",
+    "category": "flags",
+    "aliases": [":py:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "py"]
+  },
+  "flag_qa": {
+    "unicode": "1F1F6-1F1E6",
+    "unicode_alternates": [],
+    "name": "qatar",
+    "shortname": ":flag_qa:",
+    "category": "flags",
+    "aliases": [":qa:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "dawlat qatar", "qa"]
+  },
+  "flag_ro": {
+    "unicode": "1F1F7-1F1F4",
+    "unicode_alternates": [],
+    "name": "romania",
+    "shortname": ":flag_ro:",
+    "category": "flags",
+    "aliases": [":ro:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ro"]
+  },
+  "flag_rs": {
+    "unicode": "1F1F7-1F1F8",
+    "unicode_alternates": [],
+    "name": "serbia",
+    "shortname": ":flag_rs:",
+    "category": "flags",
+    "aliases": [":rs:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "srbija", "rs"]
+  },
+  "flag_ru": {
+    "unicode": "1F1F7-1F1FA",
+    "unicode_alternates": [],
+    "name": "russia",
+    "shortname": ":flag_ru:",
+    "category": "flags",
+    "aliases": [":ru:"],
+    "aliases_ascii": [],
+    "keywords": ["nation", "russian", "country", "ru"]
+  },
+  "flag_rw": {
+    "unicode": "1F1F7-1F1FC",
+    "unicode_alternates": [],
+    "name": "rwanda",
+    "shortname": ":flag_rw:",
+    "category": "flags",
+    "aliases": [":rw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "rw"]
+  },
+  "flag_sa": {
+    "unicode": "1F1F8-1F1E6",
+    "unicode_alternates": [],
+    "name": "saudi arabia",
+    "shortname": ":flag_sa:",
+    "category": "flags",
+    "aliases": [":saudiarabia:", ":saudi:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "al arabiyah as suudiyah", "sa"]
+  },
+  "flag_sb": {
+    "unicode": "1F1F8-1F1E7",
+    "unicode_alternates": [],
+    "name": "the solomon islands",
+    "shortname": ":flag_sb:",
+    "category": "flags",
+    "aliases": [":sb:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sb"]
+  },
+  "flag_sc": {
+    "unicode": "1F1F8-1F1E8",
+    "unicode_alternates": [],
+    "name": "the seychelles",
+    "shortname": ":flag_sc:",
+    "category": "flags",
+    "aliases": [":sc:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "seychelles", "sc"]
+  },
+  "flag_sd": {
+    "unicode": "1F1F8-1F1E9",
+    "unicode_alternates": [],
+    "name": "sudan",
+    "shortname": ":flag_sd:",
+    "category": "flags",
+    "aliases": [":sd:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "as-sudan", "sd"]
+  },
+  "flag_se": {
+    "unicode": "1F1F8-1F1EA",
+    "unicode_alternates": [],
+    "name": "sweden",
+    "shortname": ":flag_se:",
+    "category": "flags",
+    "aliases": [":se:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sverige", "se"]
+  },
+  "flag_sg": {
+    "unicode": "1F1F8-1F1EC",
+    "unicode_alternates": [],
+    "name": "singapore",
+    "shortname": ":flag_sg:",
+    "category": "flags",
+    "aliases": [":sg:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sg"]
+  },
+  "flag_sh": {
+    "unicode": "1F1F8-1F1ED",
+    "unicode_alternates": [],
+    "name": "saint helena",
+    "shortname": ":flag_sh:",
+    "category": "flags",
+    "aliases": [":sh:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sh"]
+  },
+  "flag_si": {
+    "unicode": "1F1F8-1F1EE",
+    "unicode_alternates": [],
+    "name": "slovenia",
+    "shortname": ":flag_si:",
+    "category": "flags",
+    "aliases": [":si:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "slovenija", "si"]
+  },
+  "flag_sk": {
+    "unicode": "1F1F8-1F1F0",
+    "unicode_alternates": [],
+    "name": "slovakia",
+    "shortname": ":flag_sk:",
+    "category": "flags",
+    "aliases": [":sk:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sk"]
+  },
+  "flag_sl": {
+    "unicode": "1F1F8-1F1F1",
+    "unicode_alternates": [],
+    "name": "sierra leone",
+    "shortname": ":flag_sl:",
+    "category": "flags",
+    "aliases": [":sl:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sl"]
+  },
+  "flag_sm": {
+    "unicode": "1F1F8-1F1F2",
+    "unicode_alternates": [],
+    "name": "san marino",
+    "shortname": ":flag_sm:",
+    "category": "flags",
+    "aliases": [":sm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sm"]
+  },
+  "flag_sn": {
+    "unicode": "1F1F8-1F1F3",
+    "unicode_alternates": [],
+    "name": "senegal",
+    "shortname": ":flag_sn:",
+    "category": "flags",
+    "aliases": [":sn:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sn"]
+  },
+  "flag_so": {
+    "unicode": "1F1F8-1F1F4",
+    "unicode_alternates": [],
+    "name": "somalia",
+    "shortname": ":flag_so:",
+    "category": "flags",
+    "aliases": [":so:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "so"]
+  },
+  "flag_sr": {
+    "unicode": "1F1F8-1F1F7",
+    "unicode_alternates": [],
+    "name": "suriname",
+    "shortname": ":flag_sr:",
+    "category": "flags",
+    "aliases": [":sr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sr"]
+  },
+  "flag_st": {
+    "unicode": "1F1F8-1F1F9",
+    "unicode_alternates": [],
+    "name": "sao tome and principe",
+    "shortname": ":flag_st:",
+    "category": "flags",
+    "aliases": [":st:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sao tome e principe", "st"]
+  },
+  "flag_sv": {
+    "unicode": "1F1F8-1F1FB",
+    "unicode_alternates": [],
+    "name": "el salvador",
+    "shortname": ":flag_sv:",
+    "category": "flags",
+    "aliases": [":sv:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sv"]
+  },
+  "flag_sy": {
+    "unicode": "1F1F8-1F1FE",
+    "unicode_alternates": [],
+    "name": "syria",
+    "shortname": ":flag_sy:",
+    "category": "flags",
+    "aliases": [":sy:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sy"]
+  },
+  "flag_sz": {
+    "unicode": "1F1F8-1F1FF",
+    "unicode_alternates": [],
+    "name": "swaziland",
+    "shortname": ":flag_sz:",
+    "category": "flags",
+    "aliases": [":sz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "sz"]
+  },
+  "flag_td": {
+    "unicode": "1F1F9-1F1E9",
+    "unicode_alternates": [],
+    "name": "chad",
+    "shortname": ":flag_td:",
+    "category": "flags",
+    "aliases": [":td:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "tchad", "td"]
+  },
+  "flag_tg": {
+    "unicode": "1F1F9-1F1EC",
+    "unicode_alternates": [],
+    "name": "togo",
+    "shortname": ":flag_tg:",
+    "category": "flags",
+    "aliases": [":tg:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "republique togolaise", "tg"]
+  },
+  "flag_th": {
+    "unicode": "1F1F9-1F1ED",
+    "unicode_alternates": [],
+    "name": "thailand",
+    "shortname": ":flag_th:",
+    "category": "flags",
+    "aliases": [":th:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "prathet thai", "th"]
+  },
+  "flag_tj": {
+    "unicode": "1F1F9-1F1EF",
+    "unicode_alternates": [],
+    "name": "tajikistan",
+    "shortname": ":flag_tj:",
+    "category": "flags",
+    "aliases": [":tj:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "jumhurii tojikiston", "tj"]
+  },
+  "flag_tl": {
+    "unicode": "1F1F9-1F1F1",
+    "unicode_alternates": [],
+    "name": "east timor",
+    "shortname": ":flag_tl:",
+    "category": "flags",
+    "aliases": [":tl:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "tl"]
+  },
+  "flag_tm": {
+    "unicode": "1F1F9-1F1F2",
+    "unicode_alternates": [],
+    "name": "turkmenistan",
+    "shortname": ":flag_tm:",
+    "category": "flags",
+    "aliases": [":turkmenistan:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "tm"]
+  },
+  "flag_tn": {
+    "unicode": "1F1F9-1F1F3",
+    "unicode_alternates": [],
+    "name": "tunisia",
+    "shortname": ":flag_tn:",
+    "category": "flags",
+    "aliases": [":tn:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "tunis", "tn"]
+  },
+  "flag_to": {
+    "unicode": "1F1F9-1F1F4",
+    "unicode_alternates": [],
+    "name": "tonga",
+    "shortname": ":flag_to:",
+    "category": "flags",
+    "aliases": [":to:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "to"]
+  },
+  "flag_tr": {
+    "unicode": "1F1F9-1F1F7",
+    "unicode_alternates": [],
+    "name": "turkey",
+    "shortname": ":flag_tr:",
+    "category": "flags",
+    "aliases": [":tr:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "turkiye"]
+  },
+  "flag_tt": {
+    "unicode": "1F1F9-1F1F9",
+    "unicode_alternates": [],
+    "name": "trinidad and tobago",
+    "shortname": ":flag_tt:",
+    "category": "flags",
+    "aliases": [":tt:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "tt"]
+  },
+  "flag_tv": {
+    "unicode": "1F1F9-1F1FB",
+    "unicode_alternates": [],
+    "name": "tuvalu",
+    "shortname": ":flag_tv:",
+    "category": "flags",
+    "aliases": [":tuvalu:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "tv"]
+  },
+  "flag_tw": {
+    "unicode": "1F1F9-1F1FC",
+    "unicode_alternates": [],
+    "name": "the republic of china",
+    "shortname": ":flag_tw:",
+    "category": "flags",
+    "aliases": [":tw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "taiwan", "tw"]
+  },
+  "flag_tz": {
+    "unicode": "1F1F9-1F1FF",
+    "unicode_alternates": [],
+    "name": "tanzania",
+    "shortname": ":flag_tz:",
+    "category": "flags",
+    "aliases": [":tz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "tz"]
+  },
+  "flag_ua": {
+    "unicode": "1F1FA-1F1E6",
+    "unicode_alternates": [],
+    "name": "ukraine",
+    "shortname": ":flag_ua:",
+    "category": "flags",
+    "aliases": [":ua:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ukrayina", "ua"]
+  },
+  "flag_ug": {
+    "unicode": "1F1FA-1F1EC",
+    "unicode_alternates": [],
+    "name": "uganda",
+    "shortname": ":flag_ug:",
+    "category": "flags",
+    "aliases": [":ug:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ug"]
+  },
+  "flag_us": {
+    "unicode": "1F1FA-1F1F8",
+    "unicode_alternates": [],
+    "name": "united states",
+    "shortname": ":flag_us:",
+    "category": "flags",
+    "aliases": [":us:"],
+    "aliases_ascii": [],
+    "keywords": ["american", "country", "nation", "usa", "united states of america", "america", "old glory", "us"]
+  },
+  "flag_uy": {
+    "unicode": "1F1FA-1F1FE",
+    "unicode_alternates": [],
+    "name": "uruguay",
+    "shortname": ":flag_uy:",
+    "category": "flags",
+    "aliases": [":uy:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "uy"]
+  },
+  "flag_uz": {
+    "unicode": "1F1FA-1F1FF",
+    "unicode_alternates": [],
+    "name": "uzbekistan",
+    "shortname": ":flag_uz:",
+    "category": "flags",
+    "aliases": [":uz:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "uzbekiston respublikasi", "uz"]
+  },
+  "flag_va": {
+    "unicode": "1F1FB-1F1E6",
+    "unicode_alternates": [],
+    "name": "the vatican city",
+    "shortname": ":flag_va:",
+    "category": "flags",
+    "aliases": [":va:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "va"]
+  },
+  "flag_vc": {
+    "unicode": "1F1FB-1F1E8",
+    "unicode_alternates": [],
+    "name": "saint vincent and the grenadines",
+    "shortname": ":flag_vc:",
+    "category": "flags",
+    "aliases": [":vc:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "vc"]
+  },
+  "flag_ve": {
+    "unicode": "1F1FB-1F1EA",
+    "unicode_alternates": [],
+    "name": "venezuela",
+    "shortname": ":flag_ve:",
+    "category": "flags",
+    "aliases": [":ve:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "ve"]
+  },
+  "flag_vi": {
+    "unicode": "1F1FB-1F1EE",
+    "unicode_alternates": [],
+    "name": "u.s. virgin islands",
+    "shortname": ":flag_vi:",
+    "category": "flags",
+    "aliases": [":vi:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "vi"]
+  },
+  "flag_vn": {
+    "unicode": "1F1FB-1F1F3",
+    "unicode_alternates": [],
+    "name": "vietnam",
+    "shortname": ":flag_vn:",
+    "category": "flags",
+    "aliases": [":vn:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "viet nam", "vn"]
+  },
+  "flag_vu": {
+    "unicode": "1F1FB-1F1FA",
+    "unicode_alternates": [],
+    "name": "vanuatu",
+    "shortname": ":flag_vu:",
+    "category": "flags",
+    "aliases": [":vu:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "vu"]
+  },
+  "flag_wf": {
+    "unicode": "1F1FC-1F1EB",
+    "unicode_alternates": [],
+    "name": "wallis and futuna",
+    "shortname": ":flag_wf:",
+    "category": "flags",
+    "aliases": [":wf:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "wf"]
+  },
+  "flag_white": {
+    "unicode": "1F3F3",
+    "unicode_alternates": [],
+    "name": "waving white flag",
+    "shortname": ":flag_white:",
+    "category": "objects_symbols",
+    "aliases": [":waving_white_flag:"],
+    "aliases_ascii": [],
+    "keywords": ["symbol", "signal"]
+  },
+  "flag_ws": {
+    "unicode": "1F1FC-1F1F8",
+    "unicode_alternates": [],
+    "name": "samoa",
+    "shortname": ":flag_ws:",
+    "category": "flags",
+    "aliases": [":ws:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "american samoa", "ws"]
+  },
+  "flag_xk": {
+    "unicode": "1F1FD-1F1F0",
+    "unicode_alternates": [],
+    "name": "kosovo",
+    "shortname": ":flag_xk:",
+    "category": "flags",
+    "aliases": [":xk:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "xk"]
+  },
+  "flag_ye": {
+    "unicode": "1F1FE-1F1EA",
+    "unicode_alternates": [],
+    "name": "yemen",
+    "shortname": ":flag_ye:",
+    "category": "flags",
+    "aliases": [":ye:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "al yaman", "ye"]
+  },
+  "flag_za": {
+    "unicode": "1F1FF-1F1E6",
+    "unicode_alternates": [],
+    "name": "south africa",
+    "shortname": ":flag_za:",
+    "category": "flags",
+    "aliases": [":za:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation"]
+  },
+  "flag_zm": {
+    "unicode": "1F1FF-1F1F2",
+    "unicode_alternates": [],
+    "name": "zambia",
+    "shortname": ":flag_zm:",
+    "category": "flags",
+    "aliases": [":zm:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "zm"]
+  },
+  "flag_zw": {
+    "unicode": "1F1FF-1F1FC",
+    "unicode_alternates": [],
+    "name": "zimbabwe",
+    "shortname": ":flag_zw:",
+    "category": "flags",
+    "aliases": [":zw:"],
+    "aliases_ascii": [],
+    "keywords": ["country", "nation", "zw"]
+  },
+  "flags": {
+    "unicode": "1F38F",
+    "unicode_alternates": [],
+    "name": "carp streamer",
+    "shortname": ":flags:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["banner", "carp", "fish", "japanese", "koinobori", "children", "kids", "boys", "celebration", "happiness", "carp", "streamers", "japanese", "holiday", "flags"],
+    "moji": "🎏"
+  },
+  "flashlight": {
+    "unicode": "1F526",
+    "unicode_alternates": [],
+    "name": "electric torch",
+    "shortname": ":flashlight:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dark"],
+    "moji": "🔦"
+  },
+  "flip_phone": {
+    "unicode": "1F581",
+    "unicode_alternates": [],
+    "name": "clamshell mobile phone",
+    "shortname": ":flip_phone:",
+    "category": "objects_symbols",
+    "aliases": [":clamshell_mobile_phone:"],
+    "aliases_ascii": [],
+    "keywords": ["cellphone"]
+  },
+  "floppy_black": {
+    "unicode": "1F5AA",
+    "unicode_alternates": [],
+    "name": "black hard shell floppy disk",
+    "shortname": ":floppy_black:",
+    "category": "objects_symbols",
+    "aliases": [":black_hard_shell_floppy_disk:"],
+    "aliases_ascii": [],
+    "keywords": ["oldschool", "save", "technology", "storage", "information", "computer", "drive", "megabyte"]
+  },
+  "floppy_disk": {
+    "unicode": "1F4BE",
+    "unicode_alternates": [],
+    "name": "floppy disk",
+    "shortname": ":floppy_disk:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["oldschool", "save", "technology", "floppy", "disk", "storage", "information", "computer", "drive", "megabyte"],
+    "moji": "💾"
+  },
+  "floppy_white": {
+    "unicode": "1F5AB",
+    "unicode_alternates": [],
+    "name": "white hard shell floppy disk",
+    "shortname": ":floppy_white:",
+    "category": "objects_symbols",
+    "aliases": [":white_hard_shell_floppy_disk:"],
+    "aliases_ascii": [],
+    "keywords": ["oldschool", "save", "technology", "storage", "information", "computer", "drive", "megabyte"]
+  },
+  "flower_playing_cards": {
+    "unicode": "1F3B4",
+    "unicode_alternates": [],
+    "name": "flower playing cards",
+    "shortname": ":flower_playing_cards:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["playing", "card", "flower", "game", "august", "moon", "special"],
+    "moji": "🎴"
+  },
+  "flushed": {
+    "unicode": "1F633",
+    "unicode_alternates": [],
+    "name": "flushed face",
+    "shortname": ":flushed:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":$", "=$"],
+    "keywords": ["blush", "face", "flattered", "flush", "blush", "red", "pink", "cheeks", "shy"],
+    "moji": "😳"
+  },
+  "fog": {
+    "unicode": "1F32B",
+    "unicode_alternates": [],
+    "name": "fog",
+    "shortname": ":fog:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["weather", "damp", "cloud", "hazy"]
+  },
+  "foggy": {
+    "unicode": "1F301",
+    "unicode_alternates": [],
+    "name": "foggy",
+    "shortname": ":foggy:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mountain", "photo", "bridge", "weather", "fog", "foggy"],
+    "moji": "🌁"
+  },
+  "folder": {
+    "unicode": "1F5C0",
+    "unicode_alternates": [],
+    "name": "folder",
+    "shortname": ":folder:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents"]
+  },
+  "folder_open": {
+    "unicode": "1F5C1",
+    "unicode_alternates": [],
+    "name": "open folder",
+    "shortname": ":folder_open:",
+    "category": "objects_symbols",
+    "aliases": [":open_folder:"],
+    "aliases_ascii": [],
+    "keywords": ["documents", "load"]
+  },
+  "football": {
+    "unicode": "1F3C8",
+    "unicode_alternates": [],
+    "name": "american football",
+    "shortname": ":football:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["NFL", "balls", "sports", "football", "ball", "sport", "america", "american"],
+    "moji": "🏈"
+  },
+  "footprints": {
+    "unicode": "1F463",
+    "unicode_alternates": [],
+    "name": "footprints",
+    "shortname": ":footprints:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["feet"],
+    "moji": "👣"
+  },
+  "fork_and_knife": {
+    "unicode": "1F374",
+    "unicode_alternates": [],
+    "name": "fork and knife",
+    "shortname": ":fork_and_knife:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cutlery", "kitchen", "fork", "knife", "restaurant", "meal", "food", "eat"],
+    "moji": "🍴"
+  },
+  "fork_knife_plate": {
+    "unicode": "1F37D",
+    "unicode_alternates": [],
+    "name": "fork and knife with plate",
+    "shortname": ":fork_knife_plate:",
+    "category": "travel_places",
+    "aliases": [":fork_and_knife_with_plate:"],
+    "aliases_ascii": [],
+    "keywords": ["meal", "food", "breakfast", "lunch", "dinner", "utensils", "setting"]
+  },
+  "fountain": {
+    "unicode": "26F2",
+    "unicode_alternates": ["26F2-FE0F"],
+    "name": "fountain",
+    "shortname": ":fountain:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["photo"],
+    "moji": "⛲"
+  },
+  "four": {
+    "moji": "4️⃣",
+    "unicode": "0034-20E3",
+    "unicode_alternates": ["0034-FE0F-20E3"],
+    "name": "digit four",
+    "shortname": ":four:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["4", "blue-square", "numbers"]
+  },
+  "four_leaf_clover": {
+    "unicode": "1F340",
+    "unicode_alternates": [],
+    "name": "four leaf clover",
+    "shortname": ":four_leaf_clover:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["lucky", "nature", "plant", "vegetable", "clover", "four", "leaf", "luck", "irish", "saint", "patrick", "green"],
+    "moji": "🍀"
+  },
+  "frame_photo": {
+    "unicode": "1F5BC",
+    "unicode_alternates": [],
+    "name": "frame with picture",
+    "shortname": ":frame_photo:",
+    "category": "objects_symbols",
+    "aliases": [":frame_with_picture:"],
+    "aliases_ascii": [],
+    "keywords": ["photo"]
+  },
+  "frame_tiles": {
+    "unicode": "1F5BD",
+    "unicode_alternates": [],
+    "name": "frame with tiles",
+    "shortname": ":frame_tiles:",
+    "category": "objects_symbols",
+    "aliases": [":frame_with_tiles:"],
+    "aliases_ascii": [],
+    "keywords": ["photo", "painting"]
+  },
+  "frame_x": {
+    "unicode": "1F5BE",
+    "unicode_alternates": [],
+    "name": "frame with an x",
+    "shortname": ":frame_x:",
+    "category": "objects_symbols",
+    "aliases": [":frame_with_an_x:"],
+    "aliases_ascii": [],
+    "keywords": ["photo", "painting"]
+  },
+  "free": {
+    "unicode": "1F193",
+    "unicode_alternates": [],
+    "name": "squared free",
+    "shortname": ":free:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "words"],
+    "moji": "🆓"
+  },
+  "fried_shrimp": {
+    "unicode": "1F364",
+    "unicode_alternates": [],
+    "name": "fried shrimp",
+    "shortname": ":fried_shrimp:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "food", "shrimp", "fried", "seafood", "small", "fish"],
+    "moji": "🍤"
+  },
+  "fries": {
+    "unicode": "1F35F",
+    "unicode_alternates": [],
+    "name": "french fries",
+    "shortname": ":fries:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chips", "food", "fries", "french", "potato", "fry", "russet", "idaho"],
+    "moji": "🍟"
+  },
+  "frog": {
+    "unicode": "1F438",
+    "unicode_alternates": [],
+    "name": "frog face",
+    "shortname": ":frog:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐸"
+  },
+  "frowning": {
+    "unicode": "1F626",
+    "unicode_alternates": [],
+    "name": "frowning face with open mouth",
+    "shortname": ":frowning:",
+    "category": "emoticons",
+    "aliases": [":anguished:"],
+    "aliases_ascii": [],
+    "keywords": ["aw", "face", "frown", "sad", "pout", "sulk", "glower"],
+    "moji": "😦"
+  },
+  "fuelpump": {
+    "unicode": "26FD",
+    "unicode_alternates": ["26FD-FE0F"],
+    "name": "fuel pump",
+    "shortname": ":fuelpump:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["gas station", "petroleum"],
+    "moji": "⛽"
+  },
+  "full_moon": {
+    "unicode": "1F315",
+    "unicode_alternates": [],
+    "name": "full moon symbol",
+    "shortname": ":full_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "yellow", "moon", "full", "sky", "night", "cheese", "phase", "monster", "spooky", "werewolves", "twilight"],
+    "moji": "🌕"
+  },
+  "full_moon_with_face": {
+    "unicode": "1F31D",
+    "unicode_alternates": [],
+    "name": "full moon with face",
+    "shortname": ":full_moon_with_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["night", "moon", "full", "anthropomorphic", "face", "sky", "night", "cheese", "phase", "spooky", "werewolves", "monsters"],
+    "moji": "🌝"
+  },
+  "game_die": {
+    "unicode": "1F3B2",
+    "unicode_alternates": [],
+    "name": "game die",
+    "shortname": ":game_die:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dice", "game", "die", "dice", "craps", "gamble", "play"],
+    "moji": "🎲"
+  },
+  "gem": {
+    "unicode": "1F48E",
+    "unicode_alternates": [],
+    "name": "gem stone",
+    "shortname": ":gem:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue", "ruby"],
+    "moji": "💎"
+  },
+  "gemini": {
+    "unicode": "264A",
+    "unicode_alternates": ["264A-FE0F"],
+    "name": "gemini",
+    "shortname": ":gemini:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["gemini", "twins", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "sign", "zodiac", "horoscope"],
+    "moji": "♊"
+  },
+  "ghost": {
+    "unicode": "1F47B",
+    "unicode_alternates": [],
+    "name": "ghost",
+    "shortname": ":ghost:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["halloween"],
+    "moji": "👻"
+  },
+  "gift": {
+    "unicode": "1F381",
+    "unicode_alternates": [],
+    "name": "wrapped present",
+    "shortname": ":gift:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["birthday", "christmas", "present", "xmas", "gift", "present", "wrap", "package", "birthday", "wedding"],
+    "moji": "🎁"
+  },
+  "gift_heart": {
+    "unicode": "1F49D",
+    "unicode_alternates": [],
+    "name": "heart with ribbon",
+    "shortname": ":gift_heart:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["love", "valentines"],
+    "moji": "💝"
+  },
+  "girl": {
+    "unicode": "1F467",
+    "unicode_alternates": [],
+    "name": "girl",
+    "shortname": ":girl:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "woman"],
+    "moji": "👧"
+  },
+  "girls_symbol": {
+    "unicode": "1F6CA",
+    "unicode_alternates": [],
+    "name": "girls symbol",
+    "shortname": ":girls_symbol:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "child"]
+  },
+  "globe_with_meridians": {
+    "unicode": "1F310",
+    "unicode_alternates": [],
+    "name": "globe with meridians",
+    "shortname": ":globe_with_meridians:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["earth", "international", "world", "earth", "meridian", "globe", "space", "planet", "home"],
+    "moji": "🌐"
+  },
+  "goat": {
+    "unicode": "1F410",
+    "unicode_alternates": [],
+    "name": "goat",
+    "shortname": ":goat:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "goat", "sheep", "kid", "billy", "livestock"],
+    "moji": "🐐"
+  },
+  "golf": {
+    "unicode": "26F3",
+    "unicode_alternates": ["26F3-FE0F"],
+    "name": "flag in hole",
+    "shortname": ":golf:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["business", "sports"],
+    "moji": "⛳"
+  },
+  "golfer": {
+    "unicode": "1F3CC",
+    "unicode_alternates": [],
+    "name": "golfer",
+    "shortname": ":golfer:",
+    "category": "activity",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sport", "par", "birdie", "eagle", "mulligan"]
+  },
+  "grapes": {
+    "unicode": "1F347",
+    "unicode_alternates": [],
+    "name": "grapes",
+    "shortname": ":grapes:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "grapes", "wine", "vinegar", "fruit", "cluster", "vine"],
+    "moji": "🍇"
+  },
+  "green_apple": {
+    "unicode": "1F34F",
+    "unicode_alternates": [],
+    "name": "green apple",
+    "shortname": ":green_apple:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fruit", "nature", "apple", "fruit", "green", "pie", "granny", "smith", "core"],
+    "moji": "🍏"
+  },
+  "green_book": {
+    "unicode": "1F4D7",
+    "unicode_alternates": [],
+    "name": "green book",
+    "shortname": ":green_book:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["knowledge", "library", "read"],
+    "moji": "📗"
+  },
+  "green_heart": {
+    "unicode": "1F49A",
+    "unicode_alternates": [],
+    "name": "green heart",
+    "shortname": ":green_heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines", "green", "heart", "love", "nature", "rebirth", "reborn", "jealous", "clingy", "envious", "possessive"],
+    "moji": "💚"
+  },
+  "grey_exclamation": {
+    "unicode": "2755",
+    "unicode_alternates": [],
+    "name": "white exclamation mark ornament",
+    "shortname": ":grey_exclamation:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["surprise"],
+    "moji": "❕"
+  },
+  "grey_question": {
+    "unicode": "2754",
+    "unicode_alternates": [],
+    "name": "white question mark ornament",
+    "shortname": ":grey_question:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["doubts"],
+    "moji": "❔"
+  },
+  "grimacing": {
+    "unicode": "1F62C",
+    "unicode_alternates": [],
+    "name": "grimacing face",
+    "shortname": ":grimacing:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "grimace", "teeth", "grimace", "disapprove", "pain"],
+    "moji": "😬"
+  },
+  "grin": {
+    "unicode": "1F601",
+    "unicode_alternates": [],
+    "name": "grinning face with smiling eyes",
+    "shortname": ":grin:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "happy", "joy", "smile", "grin", "grinning", "smiling", "smile", "smiley"],
+    "moji": "😁"
+  },
+  "grinning": {
+    "unicode": "1F600",
+    "unicode_alternates": [],
+    "name": "grinning face",
+    "shortname": ":grinning:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "happy", "joy", "smile", "grin", "grinning", "smiling", "smile", "smiley"],
+    "moji": "🕧"
+  },
+  "guardsman": {
+    "unicode": "1F482",
+    "unicode_alternates": [],
+    "name": "guardsman",
+    "shortname": ":guardsman:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["british", "gb", "male", "man", "uk", "guardsman", "guard", "bearskin", "hat", "british", "queen", "ceremonial", "military"],
+    "moji": "💂"
+  },
+  "guitar": {
+    "unicode": "1F3B8",
+    "unicode_alternates": [],
+    "name": "guitar",
+    "shortname": ":guitar:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["instrument", "music", "guitar", "string", "music", "instrument", "jam", "rock", "acoustic", "electric"],
+    "moji": "🎸"
+  },
+  "gun": {
+    "unicode": "1F52B",
+    "unicode_alternates": [],
+    "name": "pistol",
+    "shortname": ":gun:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["violence", "weapon"],
+    "moji": "🔫"
+  },
+  "haircut": {
+    "unicode": "1F487",
+    "unicode_alternates": [],
+    "name": "haircut",
+    "shortname": ":haircut:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "woman"],
+    "moji": "💇"
+  },
+  "hamburger": {
+    "unicode": "1F354",
+    "unicode_alternates": [],
+    "name": "hamburger",
+    "shortname": ":hamburger:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "meat", "hamburger", "burger", "meat", "cow", "beef"],
+    "moji": "🍔"
+  },
+  "hammer": {
+    "unicode": "1F528",
+    "unicode_alternates": [],
+    "name": "hammer",
+    "shortname": ":hammer:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["done", "judge", "law", "ruling", "tools", "verdict"],
+    "moji": "🔨"
+  },
+  "hamster": {
+    "unicode": "1F439",
+    "unicode_alternates": [],
+    "name": "hamster face",
+    "shortname": ":hamster:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐹"
+  },
+  "hand_splayed": {
+    "unicode": "1F590",
+    "unicode_alternates": [],
+    "name": "raised hand with fingers splayed",
+    "shortname": ":hand_splayed:",
+    "category": "people",
+    "aliases": [":raised_hand_with_fingers_splayed:"],
+    "aliases_ascii": [],
+    "keywords": ["hi", "five", "stop", "halt"]
+  },
+  "hand_splayed_reverse": {
+    "unicode": "1F591",
+    "unicode_alternates": [],
+    "name": "reversed raised hand with fingers splayed",
+    "shortname": ":hand_splayed_reverse:",
+    "category": "people",
+    "aliases": [":reversed_raised_hand_with_fingers_splayed:"],
+    "aliases_ascii": [],
+    "keywords": ["hi", "five", "stop", "halt"]
+  },
+  "hand_victory": {
+    "unicode": "1F594",
+    "unicode_alternates": [],
+    "name": "reversed victory hand",
+    "shortname": ":hand_victory:",
+    "category": "people",
+    "aliases": [":reversed_victory_hand:"],
+    "aliases_ascii": [],
+    "keywords": ["fu"]
+  },
+  "handbag": {
+    "unicode": "1F45C",
+    "unicode_alternates": [],
+    "name": "handbag",
+    "shortname": ":handbag:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["accessories", "accessory", "bag", "fashion"],
+    "moji": "👜"
+  },
+  "hard_disk": {
+    "unicode": "1F5B4",
+    "unicode_alternates": [],
+    "name": "hard disk",
+    "shortname": ":hard_disk:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["save", "technology", "storage", "information", "computer", "drive", "megabyte", "gigabyte", "hd"]
+  },
+  "hash": {
+    "moji": "#⃣",
+    "unicode": "0023-20E3",
+    "unicode_alternates": ["0023-FE0F-20E3"],
+    "name": "number sign",
+    "shortname": ":hash:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["symbol"]
+  },
+  "hatched_chick": {
+    "unicode": "1F425",
+    "unicode_alternates": [],
+    "name": "front-facing baby chick",
+    "shortname": ":hatched_chick:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["baby", "chicken", "chick", "baby", "bird", "chicken", "young", "woman", "cute"],
+    "moji": "🐥"
+  },
+  "hatching_chick": {
+    "unicode": "1F423",
+    "unicode_alternates": [],
+    "name": "hatching chick",
+    "shortname": ":hatching_chick:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["born", "chicken", "egg", "chick", "egg", "baby", "bird", "chicken", "young", "woman", "cute"],
+    "moji": "🐣"
+  },
+  "headphones": {
+    "unicode": "1F3A7",
+    "unicode_alternates": [],
+    "name": "headphone",
+    "shortname": ":headphones:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["gadgets", "music", "score", "headphone", "sound", "music", "ears", "beats", "buds", "audio", "listen"],
+    "moji": "🎧"
+  },
+  "hear_no_evil": {
+    "unicode": "1F649",
+    "unicode_alternates": [],
+    "name": "hear-no-evil monkey",
+    "shortname": ":hear_no_evil:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "monkey", "monkey", "ears", "hear", "sound", "kikazaru"],
+    "moji": "🙉"
+  },
+  "heart": {
+    "moji": "❤",
+    "unicode": "2764",
+    "unicode_alternates": ["2764-FE0F"],
+    "name": "heavy black heart",
+    "shortname": ":heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["<3"],
+    "keywords": ["like", "love", "red", "pink", "black", "heart", "love", "passion", "romance", "intense", "desire", "death", "evil", "cold", "valentines"]
+  },
+  "heart_decoration": {
+    "unicode": "1F49F",
+    "unicode_alternates": [],
+    "name": "heart decoration",
+    "shortname": ":heart_decoration:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["like", "love", "purple-square"],
+    "moji": "💟"
+  },
+  "heart_eyes": {
+    "unicode": "1F60D",
+    "unicode_alternates": [],
+    "name": "smiling face with heart-shaped eyes",
+    "shortname": ":heart_eyes:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "crush", "face", "infatuation", "like", "love", "valentines", "smiling", "heart", "lovestruck", "love", "flirt", "smile", "heart-shaped"],
+    "moji": "😍"
+  },
+  "heart_eyes_cat": {
+    "unicode": "1F63B",
+    "unicode_alternates": [],
+    "name": "smiling cat face with heart-shaped eyes",
+    "shortname": ":heart_eyes_cat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "animal", "cats", "like", "love", "valentines", "lovestruck", "love", "heart"],
+    "moji": "😻"
+  },
+  "heart_tip": {
+    "unicode": "1F394",
+    "unicode_alternates": [],
+    "name": "heart with tip on the left",
+    "shortname": ":heart_tip:",
+    "category": "celebration",
+    "aliases": [":heart_with_tip_on_the_left:"],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines"]
+  },
+  "heartbeat": {
+    "unicode": "1F493",
+    "unicode_alternates": [],
+    "name": "beating heart",
+    "shortname": ":heartbeat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines"],
+    "moji": "💓"
+  },
+  "heartpulse": {
+    "unicode": "1F497",
+    "unicode_alternates": [],
+    "name": "growing heart",
+    "shortname": ":heartpulse:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines"],
+    "moji": "💗"
+  },
+  "hearts": {
+    "unicode": "2665",
+    "unicode_alternates": ["2665-FE0F"],
+    "name": "black heart suit",
+    "shortname": ":hearts:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cards", "poker"],
+    "moji": "♥"
+  },
+  "heavy_check_mark": {
+    "unicode": "2714",
+    "unicode_alternates": ["2714-FE0F"],
+    "name": "heavy check mark",
+    "shortname": ":heavy_check_mark:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nike", "ok"],
+    "moji": "✔"
+  },
+  "heavy_division_sign": {
+    "unicode": "2797",
+    "unicode_alternates": [],
+    "name": "heavy division sign",
+    "shortname": ":heavy_division_sign:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["calculation", "divide", "math"],
+    "moji": "âž—"
+  },
+  "heavy_dollar_sign": {
+    "unicode": "1F4B2",
+    "unicode_alternates": [],
+    "name": "heavy dollar sign",
+    "shortname": ":heavy_dollar_sign:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["currency", "money", "payment", "dollar", "currency", "money", "cash", "sale", "purchase", "value"],
+    "moji": "💲"
+  },
+  "heavy_minus_sign": {
+    "unicode": "2796",
+    "unicode_alternates": [],
+    "name": "heavy minus sign",
+    "shortname": ":heavy_minus_sign:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["calculation", "math"],
+    "moji": "âž–"
+  },
+  "heavy_multiplication_x": {
+    "unicode": "2716",
+    "unicode_alternates": ["2716-FE0F"],
+    "name": "heavy multiplication x",
+    "shortname": ":heavy_multiplication_x:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["calculation", "math"],
+    "moji": "✖"
+  },
+  "heavy_plus_sign": {
+    "unicode": "2795",
+    "unicode_alternates": [],
+    "name": "heavy plus sign",
+    "shortname": ":heavy_plus_sign:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["calculation", "math"],
+    "moji": "âž•"
+  },
+  "helicopter": {
+    "unicode": "1F681",
+    "unicode_alternates": [],
+    "name": "helicopter",
+    "shortname": ":helicopter:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "helicopter", "helo", "gyro", "gyrocopter"],
+    "moji": "🚁"
+  },
+  "herb": {
+    "unicode": "1F33F",
+    "unicode_alternates": [],
+    "name": "herb",
+    "shortname": ":herb:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["grass", "lawn", "medicine", "plant", "vegetable", "weed", "herb", "spice", "plant", "cook", "cooking"],
+    "moji": "🌿"
+  },
+  "hibiscus": {
+    "unicode": "1F33A",
+    "unicode_alternates": [],
+    "name": "hibiscus",
+    "shortname": ":hibiscus:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flowers", "plant", "vegetable", "hibiscus", "flower", "warm"],
+    "moji": "🌺"
+  },
+  "high_brightness": {
+    "unicode": "1F506",
+    "unicode_alternates": [],
+    "name": "high brightness symbol",
+    "shortname": ":high_brightness:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["light", "summer", "sun"],
+    "moji": "🔆"
+  },
+  "high_heel": {
+    "unicode": "1F460",
+    "unicode_alternates": [],
+    "name": "high-heeled shoe",
+    "shortname": ":high_heel:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fashion", "female", "shoes"],
+    "moji": "👠"
+  },
+  "hole": {
+    "unicode": "1F573",
+    "unicode_alternates": [],
+    "name": "hole",
+    "shortname": ":hole:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["pit", "well"]
+  },
+  "homes": {
+    "unicode": "1F3D8",
+    "unicode_alternates": [],
+    "name": "house buildings",
+    "shortname": ":homes:",
+    "category": "travel_places",
+    "aliases": [":house_buildings:"],
+    "aliases_ascii": [],
+    "keywords": ["home", "residence", "dwelling", "mansion", "bungalow", "ranch", "craftsman"]
+  },
+  "honey_pot": {
+    "unicode": "1F36F",
+    "unicode_alternates": [],
+    "name": "honey pot",
+    "shortname": ":honey_pot:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bees", "sweet", "honey", "pot", "bees", "pooh", "bear"],
+    "moji": "🍯"
+  },
+  "horse": {
+    "unicode": "1F434",
+    "unicode_alternates": [],
+    "name": "horse face",
+    "shortname": ":horse:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "brown"],
+    "moji": "🐴"
+  },
+  "horse_racing": {
+    "unicode": "1F3C7",
+    "unicode_alternates": [],
+    "name": "horse racing",
+    "shortname": ":horse_racing:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "betting", "competition", "horse", "race", "racing", "jockey", "triple crown"],
+    "moji": "🏇"
+  },
+  "hospital": {
+    "unicode": "1F3E5",
+    "unicode_alternates": [],
+    "name": "hospital",
+    "shortname": ":hospital:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "doctor", "health", "surgery"],
+    "moji": "🏥"
+  },
+  "hot_pepper": {
+    "unicode": "1F336",
+    "unicode_alternates": [],
+    "name": "hot pepper",
+    "shortname": ":hot_pepper:",
+    "category": "food_drink",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "nature", "spicy", "chili", "cayenne", "habanero", "jalapeno"]
+  },
+  "hotel": {
+    "unicode": "1F3E8",
+    "unicode_alternates": [],
+    "name": "hotel",
+    "shortname": ":hotel:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["accomodation", "building", "checkin", "whotel", "hotel", "motel", "holiday inn", "hospital"],
+    "moji": "🏨"
+  },
+  "hotsprings": {
+    "unicode": "2668",
+    "unicode_alternates": ["2668-FE0F"],
+    "name": "hot springs",
+    "shortname": ":hotsprings:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bath", "relax", "warm"],
+    "moji": "♨"
+  },
+  "hourglass": {
+    "unicode": "231B",
+    "unicode_alternates": ["231B-FE0F"],
+    "name": "hourglass",
+    "shortname": ":hourglass:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clock", "oldschool", "time"],
+    "moji": "⌛"
+  },
+  "hourglass_flowing_sand": {
+    "unicode": "23F3",
+    "unicode_alternates": [],
+    "name": "hourglass with flowing sand",
+    "shortname": ":hourglass_flowing_sand:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["countdown", "oldschool", "time"],
+    "moji": "⏳"
+  },
+  "house": {
+    "unicode": "1F3E0",
+    "unicode_alternates": [],
+    "name": "house building",
+    "shortname": ":house:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "home", "house", "home", "residence", "dwelling", "mansion", "bungalow", "ranch", "craftsman"],
+    "moji": "🏠"
+  },
+  "house_abandoned": {
+    "unicode": "1F3DA",
+    "unicode_alternates": [],
+    "name": "derelict house building",
+    "shortname": ":house_abandoned:",
+    "category": "travel_places",
+    "aliases": [":derelict_house_building:"],
+    "aliases_ascii": [],
+    "keywords": ["home", "residence", "dwelling", "mansion", "bungalow", "ranch", "craftsman", "boarded", "abandoned", "vacant", "run down", "shoddy"]
+  },
+  "house_with_garden": {
+    "unicode": "1F3E1",
+    "unicode_alternates": [],
+    "name": "house with garden",
+    "shortname": ":house_with_garden:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["home", "nature", "plant"],
+    "moji": "🏡"
+  },
+  "hushed": {
+    "unicode": "1F62F",
+    "unicode_alternates": [],
+    "name": "hushed face",
+    "shortname": ":hushed:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "woo", "quiet", "hush", "whisper", "silent"],
+    "moji": "😯"
+  },
+  "ice_cream": {
+    "unicode": "1F368",
+    "unicode_alternates": [],
+    "name": "ice cream",
+    "shortname": ":ice_cream:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["desert", "food", "hot", "icecream", "ice", "cream", "dairy", "dessert", "cold", "soft", "serve", "cone", "waffle"],
+    "moji": "🍨"
+  },
+  "icecream": {
+    "unicode": "1F366",
+    "unicode_alternates": [],
+    "name": "soft ice cream",
+    "shortname": ":icecream:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["desert", "food", "hot", "icecream", "ice", "cream", "dairy", "dessert", "cold", "soft", "serve", "cone", "yogurt"],
+    "moji": "🍦"
+  },
+  "ideograph_advantage": {
+    "unicode": "1F250",
+    "unicode_alternates": [],
+    "name": "circled ideograph advantage",
+    "shortname": ":ideograph_advantage:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "get", "kanji", "obtain"],
+    "moji": "🉐"
+  },
+  "imp": {
+    "unicode": "1F47F",
+    "unicode_alternates": [],
+    "name": "imp",
+    "shortname": ":imp:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["angry", "devil", "evil", "horns", "cute", "devil"],
+    "moji": "👿"
+  },
+  "inbox_tray": {
+    "unicode": "1F4E5",
+    "unicode_alternates": [],
+    "name": "inbox tray",
+    "shortname": ":inbox_tray:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents", "email"],
+    "moji": "📥"
+  },
+  "incoming_envelope": {
+    "unicode": "1F4E8",
+    "unicode_alternates": [],
+    "name": "incoming envelope",
+    "shortname": ":incoming_envelope:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["email", "inbox"],
+    "moji": "📨"
+  },
+  "info": {
+    "unicode": "1F6C8",
+    "unicode_alternates": [],
+    "name": "circled information source",
+    "shortname": ":info:",
+    "category": "objects_symbols",
+    "aliases": [":circled_information_source:"],
+    "aliases_ascii": [],
+    "keywords": ["icon"]
+  },
+  "information_desk_person": {
+    "unicode": "1F481",
+    "unicode_alternates": [],
+    "name": "information desk person",
+    "shortname": ":information_desk_person:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "human", "woman", "information", "help", "question", "answer", "sassy", "unimpressed", "attitude", "snarky"],
+    "moji": "💁"
+  },
+  "information_source": {
+    "unicode": "2139",
+    "unicode_alternates": ["2139-FE0F"],
+    "name": "information source",
+    "shortname": ":information_source:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "blue-square", "letter"],
+    "moji": "ℹ"
+  },
+  "innocent": {
+    "unicode": "1F607",
+    "unicode_alternates": [],
+    "name": "smiling face with halo",
+    "shortname": ":innocent:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["O:-)", "0:-3", "0:3", "0:-)", "0:)", "0;^)", "O:-)", "O:)", "O;-)", "O=)", "0;-)", "O:-3", "O:3"],
+    "keywords": ["angel", "face", "halo", "halo", "angel", "innocent", "ring", "circle", "heaven"],
+    "moji": "😇"
+  },
+  "interrobang": {
+    "unicode": "2049",
+    "unicode_alternates": ["2049-FE0F"],
+    "name": "exclamation question mark",
+    "shortname": ":interrobang:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["punctuation", "surprise", "wat"],
+    "moji": "⁉"
+  },
+  "iphone": {
+    "unicode": "1F4F1",
+    "unicode_alternates": [],
+    "name": "mobile phone",
+    "shortname": ":iphone:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["apple", "dial", "gadgets", "technology"],
+    "moji": "📱"
+  },
+  "island": {
+    "unicode": "1F3DD",
+    "unicode_alternates": [],
+    "name": "desert island",
+    "shortname": ":island:",
+    "category": "travel_places",
+    "aliases": [":desert_island:"],
+    "aliases_ascii": [],
+    "keywords": ["land", "solitude", "alone"]
+  },
+  "izakaya_lantern": {
+    "unicode": "1F3EE",
+    "unicode_alternates": [],
+    "name": "izakaya lantern",
+    "shortname": ":izakaya_lantern:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["light", "izakaya", "lantern", "stay", "drink", "alcohol", "bar", "sake", "restaurant"],
+    "moji": "🏮"
+  },
+  "jack_o_lantern": {
+    "unicode": "1F383",
+    "unicode_alternates": [],
+    "name": "jack-o-lantern",
+    "shortname": ":jack_o_lantern:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["halloween", "jack-o-lantern", "pumpkin", "halloween", "holiday", "carve", "autumn", "fall", "october", "saints", "costume", "spooky", "horror", "scary", "scared", "dead"],
+    "moji": "🎃"
+  },
+  "japan": {
+    "unicode": "1F5FE",
+    "unicode_alternates": [],
+    "name": "silhouette of japan",
+    "shortname": ":japan:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nation"],
+    "moji": "🗾"
+  },
+  "japanese_castle": {
+    "unicode": "1F3EF",
+    "unicode_alternates": [],
+    "name": "japanese castle",
+    "shortname": ":japanese_castle:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "photo", "castle", "japanese", "residence", "royalty", "fort", "fortified", "fortress"],
+    "moji": "🏯"
+  },
+  "japanese_goblin": {
+    "unicode": "1F47A",
+    "unicode_alternates": [],
+    "name": "japanese goblin",
+    "shortname": ":japanese_goblin:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["evil", "mask", "red", "japanese", "tengu", "supernatural", "avian", "demon", "goblin", "mask", "theater", "nose", "frown", "mustache", "anger", "frustration"],
+    "moji": "👺"
+  },
+  "japanese_ogre": {
+    "unicode": "1F479",
+    "unicode_alternates": [],
+    "name": "japanese ogre",
+    "shortname": ":japanese_ogre:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["monster", "japanese", "oni", "demon", "troll", "ogre", "folklore", "monster", "devil", "mask", "theater", "horns", "teeth"],
+    "moji": "👹"
+  },
+  "jeans": {
+    "unicode": "1F456",
+    "unicode_alternates": [],
+    "name": "jeans",
+    "shortname": ":jeans:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fashion", "shopping", "jeans", "pants", "blue", "denim", "levi&#039;s", "levi", "designer", "work", "skinny"],
+    "moji": "👖"
+  },
+  "jet_up": {
+    "unicode": "1F6E6",
+    "unicode_alternates": [],
+    "name": "up-pointing military airplane",
+    "shortname": ":jet_up:",
+    "category": "travel_places",
+    "aliases": [":up_pointing_military_airplane:"],
+    "aliases_ascii": [],
+    "keywords": ["jet"]
+  },
+  "joy": {
+    "unicode": "1F602",
+    "unicode_alternates": [],
+    "name": "face with tears of joy",
+    "shortname": ":joy:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":')", ":'-)"],
+    "keywords": ["cry", "face", "haha", "happy", "tears", "tears", "cry", "joy", "happy", "weep"],
+    "moji": "😂"
+  },
+  "joy_cat": {
+    "unicode": "1F639",
+    "unicode_alternates": [],
+    "name": "cat face with tears of joy",
+    "shortname": ":joy_cat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cats", "haha", "happy", "tears", "happy", "tears", "cry", "joy"],
+    "moji": "😹"
+  },
+  "joystick": {
+    "unicode": "1F579",
+    "unicode_alternates": [],
+    "name": "joystick",
+    "shortname": ":joystick:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["games", "atari", "controller"]
+  },
+  "key": {
+    "unicode": "1F511",
+    "unicode_alternates": [],
+    "name": "key",
+    "shortname": ":key:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["door", "lock", "password"],
+    "moji": "🔑"
+  },
+  "key2": {
+    "unicode": "1F5DD",
+    "unicode_alternates": [],
+    "name": "old key",
+    "shortname": ":key2:",
+    "category": "objects_symbols",
+    "aliases": [":old_key:"],
+    "aliases_ascii": [],
+    "keywords": ["door", "lock", "password", "skeleton"]
+  },
+  "keyboard": {
+    "unicode": "1F5AE",
+    "unicode_alternates": [],
+    "name": "wired keyboard",
+    "shortname": ":keyboard:",
+    "category": "objects_symbols",
+    "aliases": [":wired_keyboard:"],
+    "aliases_ascii": [],
+    "keywords": ["typing", "keys", "input", "device"]
+  },
+  "keyboard_mouse": {
+    "unicode": "1F5A6",
+    "unicode_alternates": [],
+    "name": "keyboard and mouse",
+    "shortname": ":keyboard_mouse:",
+    "category": "objects_symbols",
+    "aliases": [":keyboard_and_mouse:"],
+    "aliases_ascii": [],
+    "keywords": ["computer", "input", "desktop"]
+  },
+  "keyboard_with_jacks": {
+    "unicode": "1F398",
+    "unicode_alternates": [],
+    "name": "musical keyboard with jacks",
+    "shortname": ":keyboard_with_jacks:",
+    "category": "objects_symbols",
+    "aliases": [":musical_keyboard_with_jacks:"],
+    "aliases_ascii": [],
+    "keywords": ["music", "instrument", "midi"]
+  },
+  "keycap_ten": {
+    "unicode": "1F51F",
+    "unicode_alternates": [],
+    "name": "keycap ten",
+    "shortname": ":keycap_ten:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["10", "blue-square", "numbers"],
+    "moji": "🔟"
+  },
+  "kimono": {
+    "unicode": "1F458",
+    "unicode_alternates": [],
+    "name": "kimono",
+    "shortname": ":kimono:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["dress", "fashion", "female", "japanese", "women"],
+    "moji": "👘"
+  },
+  "kiss": {
+    "unicode": "1F48B",
+    "unicode_alternates": [],
+    "name": "kiss mark",
+    "shortname": ":kiss:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "face", "like", "lips", "love", "valentines"],
+    "moji": "💋"
+  },
+  "kiss_mm": {
+    "unicode": "1F468-2764-1F48B-1F468",
+    "unicode_alternates": ["1F468-200D-2764-FE0F-200D-1F48B-200D-1F468"],
+    "name": "kiss (man,man)",
+    "shortname": ":kiss_mm:",
+    "category": "people",
+    "aliases": [":couplekiss_mm:"],
+    "aliases_ascii": [],
+    "keywords": ["dating", "like", "love", "marriage", "valentines", "couple"]
+  },
+  "kiss_ww": {
+    "unicode": "1F469-2764-1F48B-1F469",
+    "unicode_alternates": ["1F469-200D-2764-FE0F-200D-1F48B-200D-1F469"],
+    "name": "kiss (woman,woman)",
+    "shortname": ":kiss_ww:",
+    "category": "people",
+    "aliases": [":couplekiss_ww:"],
+    "aliases_ascii": [],
+    "keywords": ["dating", "like", "love", "marriage", "valentines", "couple"]
+  },
+  "kissing": {
+    "unicode": "1F617",
+    "unicode_alternates": [],
+    "name": "kissing face",
+    "shortname": ":kissing:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["3", "face", "infatuation", "like", "love", "valentines", "kissing", "kiss", "pucker", "lips", "smooch"],
+    "moji": "😗"
+  },
+  "kissing_cat": {
+    "unicode": "1F63D",
+    "unicode_alternates": [],
+    "name": "kissing cat face with closed eyes",
+    "shortname": ":kissing_cat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cats", "passion", "kiss", "puckered", "heart", "love"],
+    "moji": "😽"
+  },
+  "kissing_closed_eyes": {
+    "unicode": "1F61A",
+    "unicode_alternates": [],
+    "name": "kissing face with closed eyes",
+    "shortname": ":kissing_closed_eyes:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "face", "infatuation", "like", "love", "valentines", "kissing", "kiss", "passion", "puckered", "heart", "love", "smooch"],
+    "moji": "😚"
+  },
+  "kissing_heart": {
+    "unicode": "1F618",
+    "unicode_alternates": [],
+    "name": "face throwing a kiss",
+    "shortname": ":kissing_heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":*", ":-*", "=*", ":^*"],
+    "keywords": ["affection", "face", "infatuation", "kiss", "blowing kiss", "heart", "love", "lips", "like", "love", "valentines"],
+    "moji": "😘"
+  },
+  "kissing_smiling_eyes": {
+    "unicode": "1F619",
+    "unicode_alternates": [],
+    "name": "kissing face with smiling eyes",
+    "shortname": ":kissing_smiling_eyes:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "face", "infatuation", "valentines", "kissing", "kiss", "smile", "pucker", "lips", "smooch"],
+    "moji": "😙"
+  },
+  "knife": {
+    "unicode": "1F52A",
+    "unicode_alternates": [],
+    "name": "hocho",
+    "shortname": ":knife:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": [],
+    "moji": "🔪"
+  },
+  "koala": {
+    "unicode": "1F428",
+    "unicode_alternates": [],
+    "name": "koala",
+    "shortname": ":koala:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐨"
+  },
+  "koko": {
+    "unicode": "1F201",
+    "unicode_alternates": [],
+    "name": "squared katakana koko",
+    "shortname": ":koko:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "destination", "here", "japanese", "katakana"],
+    "moji": "🈁"
+  },
+  "label": {
+    "unicode": "1F3F7",
+    "unicode_alternates": [],
+    "name": "label",
+    "shortname": ":label:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["tag"]
+  },
+  "large_blue_circle": {
+    "unicode": "1F535",
+    "unicode_alternates": [],
+    "name": "large blue circle",
+    "shortname": ":large_blue_circle:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": [],
+    "moji": "🔵"
+  },
+  "large_blue_diamond": {
+    "unicode": "1F537",
+    "unicode_alternates": [],
+    "name": "large blue diamond",
+    "shortname": ":large_blue_diamond:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "🔷"
+  },
+  "large_orange_diamond": {
+    "unicode": "1F536",
+    "unicode_alternates": [],
+    "name": "large orange diamond",
+    "shortname": ":large_orange_diamond:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "🔶"
+  },
+  "last_quarter_moon": {
+    "unicode": "1F317",
+    "unicode_alternates": [],
+    "name": "last quarter moon symbol",
+    "shortname": ":last_quarter_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "last", "quarter", "sky", "night", "cheese", "phase"],
+    "moji": "🌗"
+  },
+  "last_quarter_moon_with_face": {
+    "unicode": "1F31C",
+    "unicode_alternates": [],
+    "name": "last quarter moon with face",
+    "shortname": ":last_quarter_moon_with_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "last", "quarter", "anthropomorphic", "face", "sky", "night", "cheese", "phase"],
+    "moji": "🌜"
+  },
+  "laughing": {
+    "unicode": "1F606",
+    "unicode_alternates": [],
+    "name": "smiling face with open mouth and tightly-closed ey",
+    "shortname": ":laughing:",
+    "category": "emoticons",
+    "aliases": [":satisfied:"],
+    "aliases_ascii": [">:)", ">;)", ">:-)", ">=)"],
+    "keywords": ["happy", "joy", "lol", "smiling", "laughing", "laugh"],
+    "moji": "😆"
+  },
+  "leaves": {
+    "unicode": "1F343",
+    "unicode_alternates": [],
+    "name": "leaf fluttering in wind",
+    "shortname": ":leaves:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["grass", "lawn", "nature", "plant", "tree", "vegetable", "leaves", "leaf", "wind", "float", "fluttering"],
+    "moji": "🍃"
+  },
+  "ledger": {
+    "unicode": "1F4D2",
+    "unicode_alternates": [],
+    "name": "ledger",
+    "shortname": ":ledger:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["notes", "paper"],
+    "moji": "📒"
+  },
+  "left_luggage": {
+    "unicode": "1F6C5",
+    "unicode_alternates": [],
+    "name": "left luggage",
+    "shortname": ":left_luggage:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "travel", "bag", "baggage", "luggage", "travel"],
+    "moji": "🛅"
+  },
+  "left_receiver": {
+    "unicode": "1F57B",
+    "unicode_alternates": [],
+    "name": "left hand telephone receiver",
+    "shortname": ":left_receiver:",
+    "category": "objects_symbols",
+    "aliases": [":left_hand_telephone_receiver:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "dial", "technology"]
+  },
+  "left_right_arrow": {
+    "unicode": "2194",
+    "unicode_alternates": ["2194-FE0F"],
+    "name": "left right arrow",
+    "shortname": ":left_right_arrow:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "↔"
+  },
+  "leftwards_arrow_with_hook": {
+    "unicode": "21A9",
+    "unicode_alternates": ["21A9-FE0F"],
+    "name": "leftwards arrow with hook",
+    "shortname": ":leftwards_arrow_with_hook:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": [],
+    "moji": "↩"
+  },
+  "lemon": {
+    "unicode": "1F34B",
+    "unicode_alternates": [],
+    "name": "lemon",
+    "shortname": ":lemon:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fruit", "nature", "lemon", "yellow", "citrus"],
+    "moji": "🍋"
+  },
+  "leo": {
+    "unicode": "264C",
+    "unicode_alternates": ["264C-FE0F"],
+    "name": "leo",
+    "shortname": ":leo:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["leo", "lion", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "purple-square", "sign", "zodiac", "horoscope"],
+    "moji": "♌"
+  },
+  "leopard": {
+    "unicode": "1F406",
+    "unicode_alternates": [],
+    "name": "leopard",
+    "shortname": ":leopard:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "leopard", "cat", "spot", "spotted", "sexy"],
+    "moji": "🐆"
+  },
+  "level_slider": {
+    "unicode": "1F39A",
+    "unicode_alternates": [],
+    "name": "level slider",
+    "shortname": ":level_slider:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["controls"]
+  },
+  "levitate": {
+    "unicode": "1F574",
+    "unicode_alternates": [],
+    "name": "man in business suit levitating",
+    "shortname": ":levitate:",
+    "category": "people",
+    "aliases": [":man_in_business_suit_levitating:"],
+    "aliases_ascii": [],
+    "keywords": ["hover", "exclamation"]
+  },
+  "libra": {
+    "unicode": "264E",
+    "unicode_alternates": ["264E-FE0F"],
+    "name": "libra",
+    "shortname": ":libra:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["libra", "scales", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "purple-square", "sign", "zodiac", "horoscope"],
+    "moji": "♎"
+  },
+  "lifter": {
+    "unicode": "1F3CB",
+    "unicode_alternates": [],
+    "name": "weight lifter",
+    "shortname": ":lifter:",
+    "category": "activity",
+    "aliases": [":weight_lifter:"],
+    "aliases_ascii": [],
+    "keywords": ["bench", "press", "squats", "deadlift"]
+  },
+  "light_check_mark": {
+    "unicode": "1F5F8",
+    "unicode_alternates": [],
+    "name": "light check mark",
+    "shortname": ":light_check_mark:",
+    "category": "objects_symbols",
+    "aliases": [":light_mark:"],
+    "aliases_ascii": [],
+    "keywords": ["vote"]
+  },
+  "light_rail": {
+    "unicode": "1F688",
+    "unicode_alternates": [],
+    "name": "light rail",
+    "shortname": ":light_rail:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "train", "rail", "light"],
+    "moji": "🚈"
+  },
+  "link": {
+    "unicode": "1F517",
+    "unicode_alternates": [],
+    "name": "link symbol",
+    "shortname": ":link:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["rings", "url"],
+    "moji": "🔗"
+  },
+  "lips": {
+    "unicode": "1F444",
+    "unicode_alternates": [],
+    "name": "mouth",
+    "shortname": ":lips:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["kiss", "mouth"],
+    "moji": "👄"
+  },
+  "lips2": {
+    "unicode": "1F5E2",
+    "unicode_alternates": [],
+    "name": "lips",
+    "shortname": ":lips2:",
+    "category": "people",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["kiss", "mouth"]
+  },
+  "lipstick": {
+    "unicode": "1F484",
+    "unicode_alternates": [],
+    "name": "lipstick",
+    "shortname": ":lipstick:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fashion", "female", "girl"],
+    "moji": "💄"
+  },
+  "lock": {
+    "unicode": "1F512",
+    "unicode_alternates": [],
+    "name": "lock",
+    "shortname": ":lock:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["password", "security"],
+    "moji": "🔒"
+  },
+  "lock_with_ink_pen": {
+    "unicode": "1F50F",
+    "unicode_alternates": [],
+    "name": "lock with ink pen",
+    "shortname": ":lock_with_ink_pen:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["secret", "security"],
+    "moji": "🔏"
+  },
+  "lollipop": {
+    "unicode": "1F36D",
+    "unicode_alternates": [],
+    "name": "lollipop",
+    "shortname": ":lollipop:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["candy", "food", "snack", "sweet", "lollipop", "stick", "lick", "sweet", "sugar", "candy"],
+    "moji": "🍭"
+  },
+  "loop": {
+    "unicode": "27BF",
+    "unicode_alternates": [],
+    "name": "double curly loop",
+    "shortname": ":loop:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["curly"],
+    "moji": "âž¿"
+  },
+  "loud_sound": {
+    "unicode": "1F50A",
+    "unicode_alternates": [],
+    "name": "speaker with three sound waves",
+    "shortname": ":loud_sound:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": [],
+    "moji": "🔊"
+  },
+  "loudspeaker": {
+    "unicode": "1F4E2",
+    "unicode_alternates": [],
+    "name": "public address loudspeaker",
+    "shortname": ":loudspeaker:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sound", "volume"],
+    "moji": "📢"
+  },
+  "love_hotel": {
+    "unicode": "1F3E9",
+    "unicode_alternates": [],
+    "name": "love hotel",
+    "shortname": ":love_hotel:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "dating", "like", "love", "hotel", "love", "sex", "romance", "leisure", "adultery", "prostitution", "hospital", "birth", "happy"],
+    "moji": "🏩"
+  },
+  "love_letter": {
+    "unicode": "1F48C",
+    "unicode_alternates": [],
+    "name": "love letter",
+    "shortname": ":love_letter:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "email", "envelope", "like", "valentines", "love", "letter", "kiss", "heart"],
+    "moji": "💌"
+  },
+  "low_brightness": {
+    "unicode": "1F505",
+    "unicode_alternates": [],
+    "name": "low brightness symbol",
+    "shortname": ":low_brightness:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["summer", "sun"],
+    "moji": "🔅"
+  },
+  "m": {
+    "unicode": "24C2",
+    "unicode_alternates": ["24C2-FE0F"],
+    "name": "circled latin capital letter m",
+    "shortname": ":m:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "blue-circle", "letter"],
+    "moji": "â“‚"
+  },
+  "mag": {
+    "unicode": "1F50D",
+    "unicode_alternates": [],
+    "name": "left-pointing magnifying glass",
+    "shortname": ":mag:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["search", "zoom", "detective", "investigator", "detail", "details"],
+    "moji": "🔍"
+  },
+  "mag_right": {
+    "unicode": "1F50E",
+    "unicode_alternates": [],
+    "name": "right-pointing magnifying glass",
+    "shortname": ":mag_right:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["search", "zoom", "detective", "investigator", "detail", "details"],
+    "moji": "🔎"
+  },
+  "mahjong": {
+    "unicode": "1F004",
+    "unicode_alternates": ["1F004-FE0F"],
+    "name": "mahjong tile red dragon",
+    "shortname": ":mahjong:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "game", "kanji"],
+    "moji": "🀄"
+  },
+  "mailbox": {
+    "unicode": "1F4EB",
+    "unicode_alternates": [],
+    "name": "closed mailbox with raised flag",
+    "shortname": ":mailbox:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "email", "inbox"],
+    "moji": "📫"
+  },
+  "mailbox_closed": {
+    "unicode": "1F4EA",
+    "unicode_alternates": [],
+    "name": "closed mailbox with lowered flag",
+    "shortname": ":mailbox_closed:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "email", "inbox"],
+    "moji": "📪"
+  },
+  "mailbox_with_mail": {
+    "unicode": "1F4EC",
+    "unicode_alternates": [],
+    "name": "open mailbox with raised flag",
+    "shortname": ":mailbox_with_mail:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "email", "inbox"],
+    "moji": "📬"
+  },
+  "mailbox_with_no_mail": {
+    "unicode": "1F4ED",
+    "unicode_alternates": [],
+    "name": "open mailbox with lowered flag",
+    "shortname": ":mailbox_with_no_mail:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["email", "inbox"],
+    "moji": "📭"
+  },
+  "man": {
+    "unicode": "1F468",
+    "unicode_alternates": [],
+    "name": "man",
+    "shortname": ":man:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["classy", "dad", "father", "guy", "mustashe"],
+    "moji": "👨"
+  },
+  "man_with_gua_pi_mao": {
+    "unicode": "1F472",
+    "unicode_alternates": [],
+    "name": "man with gua pi mao",
+    "shortname": ":man_with_gua_pi_mao:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["boy", "male", "skullcap", "chinese", "asian", "qing"],
+    "moji": "👲"
+  },
+  "man_with_turban": {
+    "unicode": "1F473",
+    "unicode_alternates": [],
+    "name": "man with turban",
+    "shortname": ":man_with_turban:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["male", "turban", "headdress", "headwear", "pagri", "india", "indian", "mummy", "wisdom", "peace"],
+    "moji": "👳"
+  },
+  "mans_shoe": {
+    "unicode": "1F45E",
+    "unicode_alternates": [],
+    "name": "mans shoe",
+    "shortname": ":mans_shoe:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fashion", "male"],
+    "moji": "👞"
+  },
+  "map": {
+    "unicode": "1F5FA",
+    "unicode_alternates": [],
+    "name": "world map",
+    "shortname": ":map:",
+    "category": "travel_places",
+    "aliases": [":world_map:"],
+    "aliases_ascii": [],
+    "keywords": ["atlas", "earth", "cartography"]
+  },
+  "maple_leaf": {
+    "unicode": "1F341",
+    "unicode_alternates": [],
+    "name": "maple leaf",
+    "shortname": ":maple_leaf:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["canada", "nature", "plant", "vegetable", "maple", "leaf", "syrup", "canada", "tree"],
+    "moji": "🍁"
+  },
+  "mask": {
+    "unicode": "1F637",
+    "unicode_alternates": [],
+    "name": "face with medical mask",
+    "shortname": ":mask:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "ill", "sick", "sick", "virus", "flu", "medical", "mask"],
+    "moji": "😷"
+  },
+  "massage": {
+    "unicode": "1F486",
+    "unicode_alternates": [],
+    "name": "face massage",
+    "shortname": ":massage:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "woman"],
+    "moji": "💆"
+  },
+  "meat_on_bone": {
+    "unicode": "1F356",
+    "unicode_alternates": [],
+    "name": "meat on bone",
+    "shortname": ":meat_on_bone:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "good", "meat", "bone", "animal", "cooked"],
+    "moji": "🍖"
+  },
+  "medal": {
+    "unicode": "1F3C5",
+    "unicode_alternates": [],
+    "name": "sports medal",
+    "shortname": ":medal:",
+    "category": "activity",
+    "aliases": [":sports_medal:"],
+    "aliases_ascii": [],
+    "keywords": ["award", "ceremony", "contest", "ftw", "place", "win", "first", "show", "reward", "achievement"]
+  },
+  "mega": {
+    "unicode": "1F4E3",
+    "unicode_alternates": [],
+    "name": "cheering megaphone",
+    "shortname": ":mega:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sound", "speaker", "volume"],
+    "moji": "📣"
+  },
+  "melon": {
+    "unicode": "1F348",
+    "unicode_alternates": [],
+    "name": "melon",
+    "shortname": ":melon:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "nature", "melon", "cantaloupe", "honeydew"],
+    "moji": "🍈"
+  },
+  "mens": {
+    "unicode": "1F6B9",
+    "unicode_alternates": [],
+    "name": "mens symbol",
+    "shortname": ":mens:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["restroom", "toilet", "wc", "men", "bathroom", "restroom", "sign", "boy", "male", "avatar"],
+    "moji": "🚹"
+  },
+  "metro": {
+    "unicode": "1F687",
+    "unicode_alternates": [],
+    "name": "metro",
+    "shortname": ":metro:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "mrt", "transportation", "tube", "underground", "metro", "subway", "underground", "train"],
+    "moji": "🚇"
+  },
+  "microphone": {
+    "unicode": "1F3A4",
+    "unicode_alternates": [],
+    "name": "microphone",
+    "shortname": ":microphone:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["PA", "music", "sound", "microphone", "mic", "audio", "sound", "voice", "karaoke"],
+    "moji": "🎤"
+  },
+  "microphone2": {
+    "unicode": "1F399",
+    "unicode_alternates": [],
+    "name": "studio microphone",
+    "shortname": ":microphone2:",
+    "category": "objects_symbols",
+    "aliases": [":studio_microphone:"],
+    "aliases_ascii": [],
+    "keywords": ["mic", "audio", "recording"]
+  },
+  "microscope": {
+    "unicode": "1F52C",
+    "unicode_alternates": [],
+    "name": "microscope",
+    "shortname": ":microscope:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["experiment", "laboratory", "zoomin"],
+    "moji": "🔬"
+  },
+  "middle_finger": {
+    "unicode": "1F595",
+    "unicode_alternates": [],
+    "name": "reversed hand with middle finger extended",
+    "shortname": ":middle_finger:",
+    "category": "people",
+    "aliases": [":reversed_hand_with_middle_finger_extended:"],
+    "aliases_ascii": [],
+    "keywords": ["fu"]
+  },
+  "military_medal": {
+    "unicode": "1F396",
+    "unicode_alternates": [],
+    "name": "military medal",
+    "shortname": ":military_medal:",
+    "category": "celebration",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["honor", "acknowledgment", "purple heart", "heroism", "veteran"]
+  },
+  "milky_way": {
+    "unicode": "1F30C",
+    "unicode_alternates": [],
+    "name": "milky way",
+    "shortname": ":milky_way:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["photo", "space", "milky", "galaxy", "star", "stars", "planets", "space", "sky"],
+    "moji": "🌌"
+  },
+  "minibus": {
+    "unicode": "1F690",
+    "unicode_alternates": [],
+    "name": "minibus",
+    "shortname": ":minibus:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["car", "transportation", "vehicle", "bus", "city", "transport", "transportation"],
+    "moji": "🚐"
+  },
+  "minidisc": {
+    "unicode": "1F4BD",
+    "unicode_alternates": [],
+    "name": "minidisc",
+    "shortname": ":minidisc:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["data", "disc", "disk", "record", "technology"],
+    "moji": "💽"
+  },
+  "mobile_phone_off": {
+    "unicode": "1F4F4",
+    "unicode_alternates": [],
+    "name": "mobile phone off",
+    "shortname": ":mobile_phone_off:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mute"],
+    "moji": "📴"
+  },
+  "money_with_wings": {
+    "unicode": "1F4B8",
+    "unicode_alternates": [],
+    "name": "money with wings",
+    "shortname": ":money_with_wings:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bills", "dollar", "payment", "money", "wings", "easy", "spend", "work", "lost", "blown", "burned", "gift", "cash", "dollar"],
+    "moji": "💸"
+  },
+  "moneybag": {
+    "unicode": "1F4B0",
+    "unicode_alternates": [],
+    "name": "money bag",
+    "shortname": ":moneybag:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["coins", "dollar", "payment"],
+    "moji": "💰"
+  },
+  "monkey": {
+    "unicode": "1F412",
+    "unicode_alternates": [],
+    "name": "monkey",
+    "shortname": ":monkey:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "monkey", "primate", "banana", "silly"],
+    "moji": "🐒"
+  },
+  "monkey_face": {
+    "unicode": "1F435",
+    "unicode_alternates": [],
+    "name": "monkey face",
+    "shortname": ":monkey_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐵"
+  },
+  "monorail": {
+    "unicode": "1F69D",
+    "unicode_alternates": [],
+    "name": "monorail",
+    "shortname": ":monorail:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "train", "mono", "rail", "transport"],
+    "moji": "🚝"
+  },
+  "mood_bubble": {
+    "unicode": "1F5F0",
+    "unicode_alternates": [],
+    "name": "mood bubble",
+    "shortname": ":mood_bubble:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["balloon", "conversation", "communication", "comic", "feeling"]
+  },
+  "mood_bubble_lightning": {
+    "unicode": "1F5F1",
+    "unicode_alternates": [],
+    "name": "lightning mood bubble",
+    "shortname": ":mood_bubble_lightning:",
+    "category": "objects_symbols",
+    "aliases": [":lightning_mood_bubble:"],
+    "aliases_ascii": [],
+    "keywords": ["balloon", "conversation", "communication", "comic", "feeling"]
+  },
+  "mood_lightning": {
+    "unicode": "1F5F2",
+    "unicode_alternates": [],
+    "name": "lightning mood",
+    "shortname": ":mood_lightning:",
+    "category": "objects_symbols",
+    "aliases": [":lightning_mood:"],
+    "aliases_ascii": [],
+    "keywords": ["zap", "electric", "current"]
+  },
+  "mortar_board": {
+    "unicode": "1F393",
+    "unicode_alternates": [],
+    "name": "graduation cap",
+    "shortname": ":mortar_board:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cap", "college", "degree", "graduation", "hat", "school", "university", "graduation", "cap", "mortarboard", "academic", "education", "ceremony", "square", "tassel"],
+    "moji": "🎓"
+  },
+  "motorboat": {
+    "unicode": "1F6E5",
+    "unicode_alternates": [],
+    "name": "motorboat",
+    "shortname": ":motorboat:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "boat", "speedboat", "powerboat"]
+  },
+  "motorcycle": {
+    "unicode": "1F3CD",
+    "unicode_alternates": [],
+    "name": "racing motorcycle",
+    "shortname": ":motorcycle:",
+    "category": "activity",
+    "aliases": [":racing_motorcycle:"],
+    "aliases_ascii": [],
+    "keywords": ["bike", "speed"]
+  },
+  "motorway": {
+    "unicode": "1F6E3",
+    "unicode_alternates": [],
+    "name": "motorway",
+    "shortname": ":motorway:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["road", "highway", "freeway", "traffic", "travel"]
+  },
+  "mount_fuji": {
+    "unicode": "1F5FB",
+    "unicode_alternates": [],
+    "name": "mount fuji",
+    "shortname": ":mount_fuji:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["japan", "mountain", "nature", "photo"],
+    "moji": "🗻"
+  },
+  "mountain_bicyclist": {
+    "unicode": "1F6B5",
+    "unicode_alternates": [],
+    "name": "mountain bicyclist",
+    "shortname": ":mountain_bicyclist:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["human", "sports", "transportation", "bicyclist", "mountain", "bike", "pedal", "bicycle", "transportation"],
+    "moji": "🚵"
+  },
+  "mountain_cableway": {
+    "unicode": "1F6A0",
+    "unicode_alternates": [],
+    "name": "mountain cableway",
+    "shortname": ":mountain_cableway:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "mountain", "cable", "rail", "train", "railway"],
+    "moji": "🚠"
+  },
+  "mountain_railway": {
+    "unicode": "1F69E",
+    "unicode_alternates": [],
+    "name": "mountain railway",
+    "shortname": ":mountain_railway:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "mountain", "railway", "rail", "train", "transport"],
+    "moji": "🚞"
+  },
+  "mountain_snow": {
+    "unicode": "1F3D4",
+    "unicode_alternates": [],
+    "name": "snow capped mountain",
+    "shortname": ":mountain_snow:",
+    "category": "travel_places",
+    "aliases": [":snow_capped_mountain:"],
+    "aliases_ascii": [],
+    "keywords": ["cold", "elevation", "hiking", "peak"]
+  },
+  "mouse": {
+    "unicode": "1F42D",
+    "unicode_alternates": [],
+    "name": "mouse face",
+    "shortname": ":mouse:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐭"
+  },
+  "mouse2": {
+    "unicode": "1F401",
+    "unicode_alternates": [],
+    "name": "mouse",
+    "shortname": ":mouse2:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "mouse", "mice", "rodent"],
+    "moji": "🐁"
+  },
+  "mouse_one": {
+    "unicode": "1F5AF",
+    "unicode_alternates": [],
+    "name": "one button mouse",
+    "shortname": ":mouse_one:",
+    "category": "objects_symbols",
+    "aliases": [":one_button_mouse:"],
+    "aliases_ascii": [],
+    "keywords": ["computer", "input", "device"]
+  },
+  "movie_camera": {
+    "unicode": "1F3A5",
+    "unicode_alternates": [],
+    "name": "movie camera",
+    "shortname": ":movie_camera:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["film", "record", "movie", "camera", "camcorder", "video", "motion", "picture"],
+    "moji": "🎥"
+  },
+  "moyai": {
+    "unicode": "1F5FF",
+    "unicode_alternates": [],
+    "name": "moyai",
+    "shortname": ":moyai:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["island", "stone"],
+    "moji": "🗿"
+  },
+  "muscle": {
+    "unicode": "1F4AA",
+    "unicode_alternates": [],
+    "name": "flexed biceps",
+    "shortname": ":muscle:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arm", "flex", "hand", "strong", "muscle", "bicep"],
+    "moji": "💪"
+  },
+  "mushroom": {
+    "unicode": "1F344",
+    "unicode_alternates": [],
+    "name": "mushroom",
+    "shortname": ":mushroom:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["plant", "vegetable", "mushroom", "fungi", "food", "fungus"],
+    "moji": "🍄"
+  },
+  "musical_keyboard": {
+    "unicode": "1F3B9",
+    "unicode_alternates": [],
+    "name": "musical keyboard",
+    "shortname": ":musical_keyboard:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["instrument", "piano", "music", "keyboard", "piano", "organ", "instrument", "electric"],
+    "moji": "🎹"
+  },
+  "musical_note": {
+    "unicode": "1F3B5",
+    "unicode_alternates": [],
+    "name": "musical note",
+    "shortname": ":musical_note:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["score", "musical", "music", "note", "music", "sound"],
+    "moji": "🎵"
+  },
+  "musical_score": {
+    "unicode": "1F3BC",
+    "unicode_alternates": [],
+    "name": "musical score",
+    "shortname": ":musical_score:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["clef", "treble", "music", "musical", "score", "clef", "g-clef", "stave", "staff"],
+    "moji": "🎼"
+  },
+  "mute": {
+    "unicode": "1F507",
+    "unicode_alternates": [],
+    "name": "speaker with cancellation stroke",
+    "shortname": ":mute:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sound", "volume"],
+    "moji": "🔇"
+  },
+  "nail_care": {
+    "unicode": "1F485",
+    "unicode_alternates": [],
+    "name": "nail polish",
+    "shortname": ":nail_care:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["beauty", "manicure"],
+    "moji": "💅"
+  },
+  "name_badge": {
+    "unicode": "1F4DB",
+    "unicode_alternates": [],
+    "name": "name badge",
+    "shortname": ":name_badge:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fire", "forbid"],
+    "moji": "📛"
+  },
+  "necktie": {
+    "unicode": "1F454",
+    "unicode_alternates": [],
+    "name": "necktie",
+    "shortname": ":necktie:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cloth", "fashion", "formal", "shirt", "suitup"],
+    "moji": "👔"
+  },
+  "negative_squared_cross_mark": {
+    "unicode": "274E",
+    "unicode_alternates": [],
+    "name": "negative squared cross mark",
+    "shortname": ":negative_squared_cross_mark:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["deny", "green-square", "no", "x"],
+    "moji": "❎"
+  },
+  "network": {
+    "unicode": "1F5A7",
+    "unicode_alternates": [],
+    "name": "three networked computers",
+    "shortname": ":network:",
+    "category": "objects_symbols",
+    "aliases": [":three_networked_computers:"],
+    "aliases_ascii": [],
+    "keywords": ["lan", "wan", "network", "technology"]
+  },
+  "neutral_face": {
+    "unicode": "1F610",
+    "unicode_alternates": [],
+    "name": "neutral face",
+    "shortname": ":neutral_face:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "indifference", "neutral", "objective", "impartial", "blank"],
+    "moji": "😐"
+  },
+  "new": {
+    "unicode": "1F195",
+    "unicode_alternates": [],
+    "name": "squared new",
+    "shortname": ":new:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "🆕"
+  },
+  "new_moon": {
+    "unicode": "1F311",
+    "unicode_alternates": [],
+    "name": "new moon symbol",
+    "shortname": ":new_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "new", "sky", "night", "cheese", "phase"],
+    "moji": "🌑"
+  },
+  "new_moon_with_face": {
+    "unicode": "1F31A",
+    "unicode_alternates": [],
+    "name": "new moon with face",
+    "shortname": ":new_moon_with_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "new", "anthropomorphic", "face", "sky", "night", "cheese", "phase"],
+    "moji": "🌚"
+  },
+  "newspaper": {
+    "unicode": "1F4F0",
+    "unicode_alternates": [],
+    "name": "newspaper",
+    "shortname": ":newspaper:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["headline", "press"],
+    "moji": "📰"
+  },
+  "newspaper2": {
+    "unicode": "1F5DE",
+    "unicode_alternates": [],
+    "name": "rolled-up newspaper",
+    "shortname": ":newspaper2:",
+    "category": "objects_symbols",
+    "aliases": [":rolled_up_newspaper:"],
+    "aliases_ascii": [],
+    "keywords": ["headline", "press"]
+  },
+  "night_with_stars": {
+    "unicode": "1F303",
+    "unicode_alternates": [],
+    "name": "night with stars",
+    "shortname": ":night_with_stars:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["night", "star", "cloudless", "evening", "planets", "space", "sky"],
+    "moji": "🌃"
+  },
+  "nine": {
+    "moji": "9️⃣",
+    "unicode": "0039-20E3",
+    "unicode_alternates": ["0039-FE0F-20E3"],
+    "name": "digit nine",
+    "shortname": ":nine:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["9", "blue-square", "numbers"]
+  },
+  "no_bell": {
+    "unicode": "1F515",
+    "unicode_alternates": [],
+    "name": "bell with cancellation stroke",
+    "shortname": ":no_bell:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mute", "sound", "volume"],
+    "moji": "🔕"
+  },
+  "no_bicycles": {
+    "unicode": "1F6B3",
+    "unicode_alternates": [],
+    "name": "no bicycles",
+    "shortname": ":no_bicycles:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cyclist", "prohibited", "bicycle", "bike pedal", "no"],
+    "moji": "🚳"
+  },
+  "no_entry": {
+    "unicode": "26D4",
+    "unicode_alternates": ["26D4-FE0F"],
+    "name": "no entry",
+    "shortname": ":no_entry:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bad", "denied", "limit", "privacy", "security", "stop"],
+    "moji": "â›”"
+  },
+  "no_entry_sign": {
+    "unicode": "1F6AB",
+    "unicode_alternates": [],
+    "name": "no entry sign",
+    "shortname": ":no_entry_sign:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["denied", "disallow", "forbid", "limit", "stop", "no", "stop", "entry"],
+    "moji": "🚫"
+  },
+  "no_good": {
+    "unicode": "1F645",
+    "unicode_alternates": [],
+    "name": "face with no good gesture",
+    "shortname": ":no_good:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "woman", "no", "stop", "nope", "don&#039;t", "not"],
+    "moji": "🙅"
+  },
+  "no_mobile_phones": {
+    "unicode": "1F4F5",
+    "unicode_alternates": [],
+    "name": "no mobile phones",
+    "shortname": ":no_mobile_phones:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["iphone", "mute"],
+    "moji": "📵"
+  },
+  "no_mouth": {
+    "unicode": "1F636",
+    "unicode_alternates": [],
+    "name": "face without mouth",
+    "shortname": ":no_mouth:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":-X", ":X", ":-#", ":#", "=X", "=x", ":x", ":-x", "=#"],
+    "keywords": ["face", "hellokitty", "mouth", "silent", "vapid"],
+    "moji": "😶"
+  },
+  "no_pedestrians": {
+    "unicode": "1F6B7",
+    "unicode_alternates": [],
+    "name": "no pedestrians",
+    "shortname": ":no_pedestrians:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["crossing", "rules", "walking", "no", "walk", "pedestrian", "stroll", "stride", "foot", "feet"],
+    "moji": "🚷"
+  },
+  "no_smoking": {
+    "unicode": "1F6AD",
+    "unicode_alternates": [],
+    "name": "no smoking symbol",
+    "shortname": ":no_smoking:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cigarette", "no", "smoking", "cigarette", "smoke", "cancer", "lungs", "inhale", "tar", "nicotine"],
+    "moji": "🚭"
+  },
+  "non-potable_water": {
+    "unicode": "1F6B1",
+    "unicode_alternates": [],
+    "name": "non-potable water symbol",
+    "shortname": ":non-potable_water:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["drink", "faucet", "tap", "non-potable", "water", "not drinkable", "dirty", "gross", "aqua", "h20"],
+    "moji": "🚱"
+  },
+  "nose": {
+    "unicode": "1F443",
+    "unicode_alternates": [],
+    "name": "nose",
+    "shortname": ":nose:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["smell", "sniff"],
+    "moji": "👃"
+  },
+  "note": {
+    "unicode": "1F5C9",
+    "unicode_alternates": [],
+    "name": "note page",
+    "shortname": ":note:",
+    "category": "objects_symbols",
+    "aliases": [":note_page:"],
+    "aliases_ascii": [],
+    "keywords": ["stationery", "post-it"]
+  },
+  "note_empty": {
+    "unicode": "1F5C6",
+    "unicode_alternates": [],
+    "name": "empty note page",
+    "shortname": ":note_empty:",
+    "category": "objects_symbols",
+    "aliases": [":empty_note_page:"],
+    "aliases_ascii": [],
+    "keywords": ["stationery", "post-it"]
+  },
+  "notebook": {
+    "unicode": "1F4D3",
+    "unicode_alternates": [],
+    "name": "notebook",
+    "shortname": ":notebook:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["notes", "paper", "record", "stationery"],
+    "moji": "📓"
+  },
+  "notebook_with_decorative_cover": {
+    "unicode": "1F4D4",
+    "unicode_alternates": [],
+    "name": "notebook with decorative cover",
+    "shortname": ":notebook_with_decorative_cover:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["classroom", "notes", "paper", "record"],
+    "moji": "📔"
+  },
+  "notepad": {
+    "unicode": "1F5CA",
+    "unicode_alternates": [],
+    "name": "note pad",
+    "shortname": ":notepad:",
+    "category": "objects_symbols",
+    "aliases": [":note_pad:"],
+    "aliases_ascii": [],
+    "keywords": ["stationery", "post-it"]
+  },
+  "notepad_empty": {
+    "unicode": "1F5C7",
+    "unicode_alternates": [],
+    "name": "empty note pad",
+    "shortname": ":notepad_empty:",
+    "category": "objects_symbols",
+    "aliases": [":empty_note_pad:"],
+    "aliases_ascii": [],
+    "keywords": ["stationery", "post-it"]
+  },
+  "notepad_spiral": {
+    "unicode": "1F5D2",
+    "unicode_alternates": [],
+    "name": "spiral note pad",
+    "shortname": ":notepad_spiral:",
+    "category": "objects_symbols",
+    "aliases": [":spiral_note_pad:"],
+    "aliases_ascii": [],
+    "keywords": ["stationery"]
+  },
+  "notes": {
+    "unicode": "1F3B6",
+    "unicode_alternates": [],
+    "name": "multiple musical notes",
+    "shortname": ":notes:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["music", "score", "musical", "music", "notes", "music", "sound", "melody"],
+    "moji": "🎶"
+  },
+  "nut_and_bolt": {
+    "unicode": "1F529",
+    "unicode_alternates": [],
+    "name": "nut and bolt",
+    "shortname": ":nut_and_bolt:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["handy", "tools"],
+    "moji": "🔩"
+  },
+  "o": {
+    "unicode": "2B55",
+    "unicode_alternates": ["2B55-FE0F"],
+    "name": "heavy large circle",
+    "shortname": ":o:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["circle", "round"],
+    "moji": "â­•"
+  },
+  "o2": {
+    "unicode": "1F17E",
+    "unicode_alternates": [],
+    "name": "negative squared latin capital letter o",
+    "shortname": ":o2:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "letter", "red-square"],
+    "moji": "🅾"
+  },
+  "ocean": {
+    "unicode": "1F30A",
+    "unicode_alternates": [],
+    "name": "water wave",
+    "shortname": ":ocean:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sea", "water", "wave", "ocean", "wave", "surf", "beach", "tide"],
+    "moji": "🌊"
+  },
+  "octopus": {
+    "unicode": "1F419",
+    "unicode_alternates": [],
+    "name": "octopus",
+    "shortname": ":octopus:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "creature", "ocean", "sea"],
+    "moji": "🐙"
+  },
+  "oden": {
+    "unicode": "1F362",
+    "unicode_alternates": [],
+    "name": "oden",
+    "shortname": ":oden:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "japanese", "oden", "seafood", "casserole", "stew"],
+    "moji": "🍢"
+  },
+  "office": {
+    "unicode": "1F3E2",
+    "unicode_alternates": [],
+    "name": "office building",
+    "shortname": ":office:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "bureau", "work"],
+    "moji": "🏢"
+  },
+  "oil": {
+    "unicode": "1F6E2",
+    "unicode_alternates": [],
+    "name": "oil drum",
+    "shortname": ":oil:",
+    "category": "objects_symbols",
+    "aliases": [":oil_drum:"],
+    "aliases_ascii": [],
+    "keywords": ["petroleum"]
+  },
+  "ok": {
+    "unicode": "1F197",
+    "unicode_alternates": [],
+    "name": "squared ok",
+    "shortname": ":ok:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["agree", "blue-square", "good", "yes"],
+    "moji": "🆗"
+  },
+  "ok_hand": {
+    "unicode": "1F44C",
+    "unicode_alternates": [],
+    "name": "ok hand sign",
+    "shortname": ":ok_hand:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fingers", "limbs", "perfect", "okay", "ok", "smoke", "smoking", "marijuana", "joint", "pot", "420"],
+    "moji": "👌"
+  },
+  "ok_woman": {
+    "unicode": "1F646",
+    "unicode_alternates": [],
+    "name": "face with ok gesture",
+    "shortname": ":ok_woman:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["*\\0/*", "\\0/", "*\\O/*", "\\O/"],
+    "keywords": ["female", "girl", "human", "pink", "women", "yes", "ok", "okay", "accept"],
+    "moji": "🙆"
+  },
+  "older_man": {
+    "unicode": "1F474",
+    "unicode_alternates": [],
+    "name": "older man",
+    "shortname": ":older_man:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["human", "male", "men"],
+    "moji": "👴"
+  },
+  "older_woman": {
+    "unicode": "1F475",
+    "unicode_alternates": [],
+    "name": "older woman",
+    "shortname": ":older_woman:",
+    "category": "emoticons",
+    "aliases": [":grandma:"],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "women", "grandma", "grandmother"],
+    "moji": "👵"
+  },
+  "om_symbol": {
+    "unicode": "1F549",
+    "unicode_alternates": [],
+    "name": "om symbol",
+    "shortname": ":om_symbol:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["hinduism", "sound", "spiritual", "icon", "dharmic", "buddhism", "jainism", "meditate"]
+  },
+  "on": {
+    "unicode": "1F51B",
+    "unicode_alternates": [],
+    "name": "on with exclamation mark with left right arrow abo",
+    "shortname": ":on:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "words"],
+    "moji": "🔛"
+  },
+  "oncoming_automobile": {
+    "unicode": "1F698",
+    "unicode_alternates": [],
+    "name": "oncoming automobile",
+    "shortname": ":oncoming_automobile:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["car", "transportation", "vehicle", "sedan", "car", "automobile"],
+    "moji": "🚘"
+  },
+  "oncoming_bus": {
+    "unicode": "1F68D",
+    "unicode_alternates": [],
+    "name": "oncoming bus",
+    "shortname": ":oncoming_bus:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "bus", "school", "city", "transportation", "public"],
+    "moji": "🚍"
+  },
+  "oncoming_police_car": {
+    "unicode": "1F694",
+    "unicode_alternates": [],
+    "name": "oncoming police car",
+    "shortname": ":oncoming_police_car:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["enforcement", "law", "vehicle", "police", "car", "emergency", "ticket", "citation", "crime", "help", "officer"],
+    "moji": "🚔"
+  },
+  "oncoming_taxi": {
+    "unicode": "1F696",
+    "unicode_alternates": [],
+    "name": "oncoming taxi",
+    "shortname": ":oncoming_taxi:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cars", "uber", "vehicle", "taxi", "car", "automobile", "city", "transport", "service"],
+    "moji": "🚖"
+  },
+  "one": {
+    "moji": "1️⃣",
+    "unicode": "0031-20E3",
+    "unicode_alternates": ["0031-FE0F-20E3"],
+    "name": "digit one",
+    "shortname": ":one:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["1", "blue-square", "numbers"]
+  },
+  "open_file_folder": {
+    "unicode": "1F4C2",
+    "unicode_alternates": [],
+    "name": "open file folder",
+    "shortname": ":open_file_folder:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents", "load"],
+    "moji": "📂"
+  },
+  "open_hands": {
+    "unicode": "1F450",
+    "unicode_alternates": [],
+    "name": "open hands sign",
+    "shortname": ":open_hands:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["butterfly", "fingers"],
+    "moji": "👐"
+  },
+  "open_mouth": {
+    "unicode": "1F62E",
+    "unicode_alternates": [],
+    "name": "face with open mouth",
+    "shortname": ":open_mouth:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":-O", ":O", ":-o", ":o", "O_O", ">:O"],
+    "keywords": ["face", "impressed", "mouth", "open", "jaw", "gapping", "surprise", "wow"],
+    "moji": "😮"
+  },
+  "ophiuchus": {
+    "unicode": "26CE",
+    "unicode_alternates": [],
+    "name": "ophiuchus",
+    "shortname": ":ophiuchus:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["ophiuchus", "serpent", "snake", "astrology", "greek", "constellation", "stars", "zodiac", "purple-square", "sign", "horoscope"],
+    "moji": "⛎"
+  },
+  "optical_disk": {
+    "unicode": "1F5B8",
+    "unicode_alternates": [],
+    "name": "optical disc icon",
+    "shortname": ":optical_disk:",
+    "category": "objects_symbols",
+    "aliases": [":optical_disc_icon:"],
+    "aliases_ascii": [],
+    "keywords": ["cd", "dvd", "disc", "disk", "technology"]
+  },
+  "orange_book": {
+    "unicode": "1F4D9",
+    "unicode_alternates": [],
+    "name": "orange book",
+    "shortname": ":orange_book:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["knowledge", "library", "read"],
+    "moji": "📙"
+  },
+  "outbox_tray": {
+    "unicode": "1F4E4",
+    "unicode_alternates": [],
+    "name": "outbox tray",
+    "shortname": ":outbox_tray:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["email", "inbox"],
+    "moji": "📤"
+  },
+  "ox": {
+    "unicode": "1F402",
+    "unicode_alternates": [],
+    "name": "ox",
+    "shortname": ":ox:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "beef", "cow"],
+    "moji": "🐂"
+  },
+  "package": {
+    "unicode": "1F4E6",
+    "unicode_alternates": [],
+    "name": "package",
+    "shortname": ":package:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["gift", "mail"],
+    "moji": "📦"
+  },
+  "page": {
+    "unicode": "1F5CF",
+    "unicode_alternates": [],
+    "name": "page",
+    "shortname": ":page:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["document"]
+  },
+  "page_facing_up": {
+    "unicode": "1F4C4",
+    "unicode_alternates": [],
+    "name": "page facing up",
+    "shortname": ":page_facing_up:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents"],
+    "moji": "📄"
+  },
+  "page_with_curl": {
+    "unicode": "1F4C3",
+    "unicode_alternates": [],
+    "name": "page with curl",
+    "shortname": ":page_with_curl:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents"],
+    "moji": "📃"
+  },
+  "pager": {
+    "unicode": "1F4DF",
+    "unicode_alternates": [],
+    "name": "pager",
+    "shortname": ":pager:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bbcall", "oldschool"],
+    "moji": "📟"
+  },
+  "pages": {
+    "unicode": "1F5D0",
+    "unicode_alternates": [],
+    "name": "pages",
+    "shortname": ":pages:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents"]
+  },
+  "paintbrush": {
+    "unicode": "1F58C",
+    "unicode_alternates": [],
+    "name": "lower left paintbrush",
+    "shortname": ":paintbrush:",
+    "category": "objects_symbols",
+    "aliases": [":lower_left_paintbrush:"],
+    "aliases_ascii": [],
+    "keywords": ["brush", "art", "painting"]
+  },
+  "palm_tree": {
+    "unicode": "1F334",
+    "unicode_alternates": [],
+    "name": "palm tree",
+    "shortname": ":palm_tree:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "plant", "vegetable", "palm", "tree", "coconuts", "fronds", "warm", "tropical"],
+    "moji": "🌴"
+  },
+  "panda_face": {
+    "unicode": "1F43C",
+    "unicode_alternates": [],
+    "name": "panda face",
+    "shortname": ":panda_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "panda", "bear", "face", "cub", "cute", "endearment", "friendship", "love", "bamboo", "china", "black", "white"],
+    "moji": "🐼"
+  },
+  "paperclip": {
+    "unicode": "1F4CE",
+    "unicode_alternates": [],
+    "name": "paperclip",
+    "shortname": ":paperclip:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents", "stationery"],
+    "moji": "📎"
+  },
+  "paperclips": {
+    "unicode": "1F587",
+    "unicode_alternates": [],
+    "name": "linked paperclips",
+    "shortname": ":paperclips:",
+    "category": "objects_symbols",
+    "aliases": [":linked_paperclips:"],
+    "aliases_ascii": [],
+    "keywords": ["documents", "stationery"]
+  },
+  "park": {
+    "unicode": "1F3DE",
+    "unicode_alternates": [],
+    "name": "national park",
+    "shortname": ":park:",
+    "category": "travel_places",
+    "aliases": [":national_park:"],
+    "aliases_ascii": [],
+    "keywords": ["woods", "nature", "wildlife", "forest", "wilderness", "national"]
+  },
+  "parking": {
+    "unicode": "1F17F",
+    "unicode_alternates": ["1F17F-FE0F"],
+    "name": "negative squared latin capital letter p",
+    "shortname": ":parking:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "blue-square", "cars", "letter"],
+    "moji": "🅿"
+  },
+  "part_alternation_mark": {
+    "unicode": "303D",
+    "unicode_alternates": ["303D-FE0F"],
+    "name": "part alternation mark",
+    "shortname": ":part_alternation_mark:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["graph", "sing", "song", "vocal", "music", "karaoke", "cue", "letter", "m", "japanese"],
+    "moji": "〽"
+  },
+  "partly_sunny": {
+    "unicode": "26C5",
+    "unicode_alternates": ["26C5-FE0F"],
+    "name": "sun behind cloud",
+    "shortname": ":partly_sunny:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cloud", "morning", "nature", "weather"],
+    "moji": "â›…"
+  },
+  "passport_control": {
+    "unicode": "1F6C2",
+    "unicode_alternates": [],
+    "name": "passport control",
+    "shortname": ":passport_control:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "custom", "passport", "official", "travel", "control", "foreign", "identification"],
+    "moji": "🛂"
+  },
+  "peach": {
+    "unicode": "1F351",
+    "unicode_alternates": [],
+    "name": "peach",
+    "shortname": ":peach:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "nature", "peach", "fruit", "juicy", "pit"],
+    "moji": "🍑"
+  },
+  "pear": {
+    "unicode": "1F350",
+    "unicode_alternates": [],
+    "name": "pear",
+    "shortname": ":pear:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fruit", "nature", "pear", "fruit", "shape"],
+    "moji": "🍐"
+  },
+  "pen_ballpoint": {
+    "unicode": "1F58A",
+    "unicode_alternates": [],
+    "name": "lower left ballpoint pen",
+    "shortname": ":pen_ballpoint:",
+    "category": "objects_symbols",
+    "aliases": [":lower_left_ballpoint_pen:"],
+    "aliases_ascii": [],
+    "keywords": ["write", "bic", "ink"]
+  },
+  "pen_fountain": {
+    "unicode": "1F58B",
+    "unicode_alternates": [],
+    "name": "lower left fountain pen",
+    "shortname": ":pen_fountain:",
+    "category": "objects_symbols",
+    "aliases": [":lower_left_fountain_pen:"],
+    "aliases_ascii": [],
+    "keywords": ["write", "calligraphy", "ink"]
+  },
+  "pencil": {
+    "unicode": "1F4DD",
+    "unicode_alternates": [],
+    "name": "memo",
+    "shortname": ":pencil:",
+    "category": "objects",
+    "aliases": [":memo:"],
+    "aliases_ascii": [],
+    "keywords": ["documents", "paper", "station", "write"],
+    "moji": "📝"
+  },
+  "pencil2": {
+    "unicode": "270F",
+    "unicode_alternates": ["270F-FE0F"],
+    "name": "pencil",
+    "shortname": ":pencil2:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["paper", "stationery", "write"],
+    "moji": "✏"
+  },
+  "pencil3": {
+    "unicode": "1F589",
+    "unicode_alternates": [],
+    "name": "lower left pencil",
+    "shortname": ":pencil3:",
+    "category": "objects_symbols",
+    "aliases": [":lower_left_pencil:"],
+    "aliases_ascii": [],
+    "keywords": ["paper", "stationery", "write"]
+  },
+  "penguin": {
+    "unicode": "1F427",
+    "unicode_alternates": [],
+    "name": "penguin",
+    "shortname": ":penguin:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐧"
+  },
+  "pennant_black": {
+    "unicode": "1F3F2",
+    "unicode_alternates": [],
+    "name": "black pennant",
+    "shortname": ":pennant_black:",
+    "category": "objects_symbols",
+    "aliases": [":black_pennant:"],
+    "aliases_ascii": [],
+    "keywords": ["flag", "athletics"]
+  },
+  "pennant_white": {
+    "unicode": "1F3F1",
+    "unicode_alternates": [],
+    "name": "white pennant",
+    "shortname": ":pennant_white:",
+    "category": "objects_symbols",
+    "aliases": [":white_pennant:"],
+    "aliases_ascii": [],
+    "keywords": ["flag", "athletics"]
+  },
+  "pensive": {
+    "unicode": "1F614",
+    "unicode_alternates": [],
+    "name": "pensive face",
+    "shortname": ":pensive:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "okay", "sad", "pensive", "thoughtful", "think", "reflective", "wistful", "meditate", "serious"],
+    "moji": "😔"
+  },
+  "performing_arts": {
+    "unicode": "1F3AD",
+    "unicode_alternates": [],
+    "name": "performing arts",
+    "shortname": ":performing_arts:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["acting", "drama", "theater", "performing", "arts", "performance", "entertainment", "acting", "story", "mask", "masks"],
+    "moji": "🎭"
+  },
+  "persevere": {
+    "unicode": "1F623",
+    "unicode_alternates": [],
+    "name": "persevering face",
+    "shortname": ":persevere:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [">.<"],
+    "keywords": ["endure", "persevere", "face", "no", "sick", "upset"],
+    "moji": "😣"
+  },
+  "person_frowning": {
+    "unicode": "1F64D",
+    "unicode_alternates": [],
+    "name": "person frowning",
+    "shortname": ":person_frowning:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "woman", "dejected", "rejected", "sad", "frown"],
+    "moji": "🙍"
+  },
+  "person_with_blond_hair": {
+    "unicode": "1F471",
+    "unicode_alternates": [],
+    "name": "person with blond hair",
+    "shortname": ":person_with_blond_hair:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["male", "man", "blonde", "young", "western", "westerner", "occidental"],
+    "moji": "👱"
+  },
+  "person_with_pouting_face": {
+    "unicode": "1F64E",
+    "unicode_alternates": [],
+    "name": "person with pouting face",
+    "shortname": ":person_with_pouting_face:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "woman", "pout", "sexy", "cute", "annoyed"],
+    "moji": "🙎"
+  },
+  "pig": {
+    "unicode": "1F437",
+    "unicode_alternates": [],
+    "name": "pig face",
+    "shortname": ":pig:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "oink"],
+    "moji": "🐷"
+  },
+  "pig2": {
+    "unicode": "1F416",
+    "unicode_alternates": [],
+    "name": "pig",
+    "shortname": ":pig2:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "pig", "piggy", "pork", "ham", "hog", "bacon", "oink", "slop", "livestock", "greed", "greedy"],
+    "moji": "🐖"
+  },
+  "pig_nose": {
+    "unicode": "1F43D",
+    "unicode_alternates": [],
+    "name": "pig nose",
+    "shortname": ":pig_nose:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "oink", "pig", "nose", "snout", "food", "eat", "cute", "oink", "pink", "smell", "truffle"],
+    "moji": "🐽"
+  },
+  "pill": {
+    "unicode": "1F48A",
+    "unicode_alternates": [],
+    "name": "pill",
+    "shortname": ":pill:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["health", "medicine"],
+    "moji": "💊"
+  },
+  "pineapple": {
+    "unicode": "1F34D",
+    "unicode_alternates": [],
+    "name": "pineapple",
+    "shortname": ":pineapple:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "nature", "pineapple", "pina", "tropical", "flower"],
+    "moji": "🍍"
+  },
+  "piracy": {
+    "unicode": "1F572",
+    "unicode_alternates": [],
+    "name": "no piracy",
+    "shortname": ":piracy:",
+    "category": "objects_symbols",
+    "aliases": [":no_piracy:"],
+    "aliases_ascii": [],
+    "keywords": ["theft", "rule"]
+  },
+  "pisces": {
+    "unicode": "2653",
+    "unicode_alternates": ["2653-FE0F"],
+    "name": "pisces",
+    "shortname": ":pisces:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["pisces", "fish", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "purple-square", "sign", "zodiac", "horoscope"],
+    "moji": "♓"
+  },
+  "pizza": {
+    "unicode": "1F355",
+    "unicode_alternates": [],
+    "name": "slice of pizza",
+    "shortname": ":pizza:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "party", "pizza", "pie", "new york", "italian", "italy", "slice", "peperoni"],
+    "moji": "🍕"
+  },
+  "point_down": {
+    "unicode": "1F447",
+    "unicode_alternates": [],
+    "name": "white down pointing backhand index",
+    "shortname": ":point_down:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["direction", "fingers", "hand"],
+    "moji": "👇"
+  },
+  "point_left": {
+    "unicode": "1F448",
+    "unicode_alternates": [],
+    "name": "white left pointing backhand index",
+    "shortname": ":point_left:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["direction", "fingers", "hand"],
+    "moji": "👈"
+  },
+  "point_right": {
+    "unicode": "1F449",
+    "unicode_alternates": [],
+    "name": "white right pointing backhand index",
+    "shortname": ":point_right:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["direction", "fingers", "hand"],
+    "moji": "👉"
+  },
+  "point_up": {
+    "unicode": "261D",
+    "unicode_alternates": ["261D-FE0F"],
+    "name": "white up pointing index",
+    "shortname": ":point_up:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["direction", "fingers", "hand"],
+    "moji": "☝"
+  },
+  "point_up_2": {
+    "unicode": "1F446",
+    "unicode_alternates": [],
+    "name": "white up pointing backhand index",
+    "shortname": ":point_up_2:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["direction", "fingers", "hand"],
+    "moji": "👆"
+  },
+  "police_car": {
+    "unicode": "1F693",
+    "unicode_alternates": [],
+    "name": "police car",
+    "shortname": ":police_car:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cars", "enforcement", "law", "transportation", "vehicle", "police", "car", "emergency", "ticket", "citation", "crime", "help", "officer"],
+    "moji": "🚓"
+  },
+  "poodle": {
+    "unicode": "1F429",
+    "unicode_alternates": [],
+    "name": "poodle",
+    "shortname": ":poodle:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["101", "animal", "dog", "nature", "poodle", "dog", "clip", "showy", "sophisticated", "vain"],
+    "moji": "🐩"
+  },
+  "poop": {
+    "unicode": "1F4A9",
+    "unicode_alternates": [],
+    "name": "pile of poo",
+    "shortname": ":poop:",
+    "category": "emoticons",
+    "aliases": [":shit:", ":hankey:", ":poo:"],
+    "aliases_ascii": [],
+    "keywords": ["poop", "shit", "shitface", "turd", "poo"],
+    "moji": "💩"
+  },
+  "post_office": {
+    "unicode": "1F3E3",
+    "unicode_alternates": [],
+    "name": "japanese post office",
+    "shortname": ":post_office:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "communication", "email"],
+    "moji": "🏣"
+  },
+  "postal_horn": {
+    "unicode": "1F4EF",
+    "unicode_alternates": [],
+    "name": "postal horn",
+    "shortname": ":postal_horn:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["instrument", "music"],
+    "moji": "📯"
+  },
+  "postbox": {
+    "unicode": "1F4EE",
+    "unicode_alternates": [],
+    "name": "postbox",
+    "shortname": ":postbox:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["email", "envelope", "letter"],
+    "moji": "📮"
+  },
+  "potable_water": {
+    "unicode": "1F6B0",
+    "unicode_alternates": [],
+    "name": "potable water symbol",
+    "shortname": ":potable_water:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "cleaning", "faucet", "liquid", "restroom", "potable", "water", "drinkable", "pure", "clear", "clean", "aqua", "h20"],
+    "moji": "🚰"
+  },
+  "pouch": {
+    "unicode": "1F45D",
+    "unicode_alternates": [],
+    "name": "pouch",
+    "shortname": ":pouch:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["accessories", "bag", "pouch", "bag", "cosmetic", "packing", "grandma", "makeup"],
+    "moji": "👝"
+  },
+  "poultry_leg": {
+    "unicode": "1F357",
+    "unicode_alternates": [],
+    "name": "poultry leg",
+    "shortname": ":poultry_leg:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "meat", "poultry", "leg", "chicken", "fried"],
+    "moji": "🍗"
+  },
+  "pound": {
+    "unicode": "1F4B7",
+    "unicode_alternates": [],
+    "name": "banknote with pound sign",
+    "shortname": ":pound:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bills", "british", "currency", "england", "money", "sterling", "uk", "pound", "britain", "british", "banknote", "money", "currency", "paper", "cash", "bills"],
+    "moji": "💷"
+  },
+  "pouting_cat": {
+    "unicode": "1F63E",
+    "unicode_alternates": [],
+    "name": "pouting cat face",
+    "shortname": ":pouting_cat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cats", "pout", "annoyed", "miffed", "glower", "frown"],
+    "moji": "😾"
+  },
+  "pray": {
+    "unicode": "1F64F",
+    "unicode_alternates": [],
+    "name": "person with folded hands",
+    "shortname": ":pray:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["highfive", "hope", "namaste", "please", "wish", "pray", "high five", "hands", "sorrow", "regret", "sorry"],
+    "moji": "🙏"
+  },
+  "princess": {
+    "unicode": "1F478",
+    "unicode_alternates": [],
+    "name": "princess",
+    "shortname": ":princess:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blond", "crown", "female", "girl", "woman", "princess", "royal", "royalty", "king", "queen", "daughter", "disney", "high-maintenance"],
+    "moji": "👸"
+  },
+  "printer": {
+    "unicode": "1F5A8",
+    "unicode_alternates": [],
+    "name": "printer",
+    "shortname": ":printer:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["hardcopy", "paper", "inkjet", "laser"]
+  },
+  "prohibited": {
+    "unicode": "1F6C7",
+    "unicode_alternates": [],
+    "name": "prohibited sign",
+    "shortname": ":prohibited:",
+    "category": "objects_symbols",
+    "aliases": [":prohibited_sign:"],
+    "aliases_ascii": [],
+    "keywords": ["no", "not", "denied", "disallow", "forbid", "limit", "stop"]
+  },
+  "projector": {
+    "unicode": "1F4FD",
+    "unicode_alternates": [],
+    "name": "film projector",
+    "shortname": ":projector:",
+    "category": "objects_symbols",
+    "aliases": [":film_projector:"],
+    "aliases_ascii": [],
+    "keywords": ["movie", "video", "motion", "picture", "8mm", "16mm"]
+  },
+  "punch": {
+    "unicode": "1F44A",
+    "unicode_alternates": [],
+    "name": "fisted hand sign",
+    "shortname": ":punch:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fist", "hand"],
+    "moji": "👊"
+  },
+  "purple_heart": {
+    "unicode": "1F49C",
+    "unicode_alternates": [],
+    "name": "purple heart",
+    "shortname": ":purple_heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines", "purple", "violet", "heart", "love", "sensitive", "understanding", "compassionate", "compassion", "duty", "honor", "royalty", "veteran", "sacrifice"],
+    "moji": "💜"
+  },
+  "purse": {
+    "unicode": "1F45B",
+    "unicode_alternates": [],
+    "name": "purse",
+    "shortname": ":purse:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["accessories", "fashion", "money", "purse", "clutch", "bag", "handbag", "coin bag", "accessory", "money", "ladies", "shopping"],
+    "moji": "👛"
+  },
+  "pushpin": {
+    "unicode": "1F4CC",
+    "unicode_alternates": [],
+    "name": "pushpin",
+    "shortname": ":pushpin:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["stationery"],
+    "moji": "📌"
+  },
+  "pushpin_black": {
+    "unicode": "1F588",
+    "unicode_alternates": [],
+    "name": "black pushpin",
+    "shortname": ":pushpin_black:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["stationery"]
+  },
+  "put_litter_in_its_place": {
+    "unicode": "1F6AE",
+    "unicode_alternates": [],
+    "name": "put litter in its place symbol",
+    "shortname": ":put_litter_in_its_place:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "litter", "waste", "trash", "garbage", "receptacle", "can"],
+    "moji": "🚮"
+  },
+  "question": {
+    "unicode": "2753",
+    "unicode_alternates": [],
+    "name": "black question mark ornament",
+    "shortname": ":question:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["confused", "doubt"],
+    "moji": "❓"
+  },
+  "rabbit": {
+    "unicode": "1F430",
+    "unicode_alternates": [],
+    "name": "rabbit face",
+    "shortname": ":rabbit:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐰"
+  },
+  "rabbit2": {
+    "unicode": "1F407",
+    "unicode_alternates": [],
+    "name": "rabbit",
+    "shortname": ":rabbit2:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "rabbit", "bunny", "easter", "reproduction", "prolific"],
+    "moji": "🐇"
+  },
+  "race_car": {
+    "unicode": "1F3CE",
+    "unicode_alternates": [],
+    "name": "racing car",
+    "shortname": ":race_car:",
+    "category": "activity",
+    "aliases": [":racing_car:"],
+    "aliases_ascii": [],
+    "keywords": ["formula 1", "race", "stock", "nascar", "speed", "drive"]
+  },
+  "racehorse": {
+    "unicode": "1F40E",
+    "unicode_alternates": [],
+    "name": "horse",
+    "shortname": ":racehorse:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "gamble", "horse", "powerful", "draft", "calvary", "cowboy", "cowgirl", "mounted", "race", "ride", "gallop", "trot", "colt", "filly", "mare", "stallion", "gelding", "yearling", "thoroughbred", "pony"],
+    "moji": "🐎"
+  },
+  "radio": {
+    "unicode": "1F4FB",
+    "unicode_alternates": [],
+    "name": "radio",
+    "shortname": ":radio:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "music", "podcast", "program"],
+    "moji": "📻"
+  },
+  "radio_button": {
+    "unicode": "1F518",
+    "unicode_alternates": [],
+    "name": "radio button",
+    "shortname": ":radio_button:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["input"],
+    "moji": "🔘"
+  },
+  "rage": {
+    "unicode": "1F621",
+    "unicode_alternates": [],
+    "name": "pouting face",
+    "shortname": ":rage:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["angry", "despise", "hate", "mad", "pout", "anger", "rage", "irate"],
+    "moji": "😡"
+  },
+  "railway_car": {
+    "unicode": "1F683",
+    "unicode_alternates": [],
+    "name": "railway car",
+    "shortname": ":railway_car:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "railway", "rail", "car", "coach", "train"],
+    "moji": "🚃"
+  },
+  "railway_track": {
+    "unicode": "1F6E4",
+    "unicode_alternates": [],
+    "name": "railway track",
+    "shortname": ":railway_track:",
+    "category": "travel_places",
+    "aliases": [":railroad_track:"],
+    "aliases_ascii": [],
+    "keywords": ["train", "trolley", "subway", "locomotive", "transit"]
+  },
+  "rainbow": {
+    "unicode": "1F308",
+    "unicode_alternates": [],
+    "name": "rainbow",
+    "shortname": ":rainbow:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["happy", "nature", "photo", "sky", "unicorn", "rainbow", "color", "pride", "diversity", "spectrum", "refract", "leprechaun", "gold"],
+    "moji": "🌈"
+  },
+  "raised_hand": {
+    "unicode": "270B",
+    "unicode_alternates": [],
+    "name": "raised hand",
+    "shortname": ":raised_hand:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "woman"],
+    "moji": "✋"
+  },
+  "raised_hands": {
+    "unicode": "1F64C",
+    "unicode_alternates": [],
+    "name": "person raising both hands in celebration",
+    "shortname": ":raised_hands:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["gesture", "hooray", "winning", "woot", "yay", "banzai"],
+    "moji": "🙌"
+  },
+  "raising_hand": {
+    "unicode": "1F64B",
+    "unicode_alternates": [],
+    "name": "happy person raising one hand",
+    "shortname": ":raising_hand:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girl", "woman", "hand", "raise", "notice", "attention", "answer"],
+    "moji": "🙋"
+  },
+  "ram": {
+    "unicode": "1F40F",
+    "unicode_alternates": [],
+    "name": "ram",
+    "shortname": ":ram:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "sheep", "ram", "sheep", "male", "horn", "horns"],
+    "moji": "🐏"
+  },
+  "ramen": {
+    "unicode": "1F35C",
+    "unicode_alternates": [],
+    "name": "steaming bowl",
+    "shortname": ":ramen:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chipsticks", "food", "japanese", "noodle", "ramen", "noodles", "bowl", "steaming", "soup"],
+    "moji": "🍜"
+  },
+  "rat": {
+    "unicode": "1F400",
+    "unicode_alternates": [],
+    "name": "rat",
+    "shortname": ":rat:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "mouse", "rat", "rodent", "crooked", "snitch"],
+    "moji": "🐀"
+  },
+  "recycle": {
+    "unicode": "267B",
+    "unicode_alternates": ["267B-FE0F"],
+    "name": "black universal recycling symbol",
+    "shortname": ":recycle:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "environment", "garbage", "trash"],
+    "moji": "â™»"
+  },
+  "red_car": {
+    "unicode": "1F697",
+    "unicode_alternates": [],
+    "name": "automobile",
+    "shortname": ":red_car:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle"],
+    "moji": "🚗"
+  },
+  "red_circle": {
+    "unicode": "1F534",
+    "unicode_alternates": [],
+    "name": "large red circle",
+    "shortname": ":red_circle:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "🔴"
+  },
+  "registered": {
+    "moji": "®",
+    "unicode": "00AE",
+    "unicode_alternates": [],
+    "name": "registered sign",
+    "shortname": ":registered:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alphabet", "circle"]
+  },
+  "relaxed": {
+    "unicode": "263A",
+    "unicode_alternates": ["263A-FE0F"],
+    "name": "white smiling face",
+    "shortname": ":relaxed:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blush", "face", "happiness", "massage", "smile"],
+    "moji": "☺"
+  },
+  "relieved": {
+    "unicode": "1F60C",
+    "unicode_alternates": [],
+    "name": "relieved face",
+    "shortname": ":relieved:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "happiness", "massage", "phew", "relaxed", "relieved", "satisfied", "phew", "relief"],
+    "moji": "😌"
+  },
+  "reminder_ribbon": {
+    "unicode": "1F397",
+    "unicode_alternates": [],
+    "name": "reminder ribbon",
+    "shortname": ":reminder_ribbon:",
+    "category": "celebration",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["awareness"]
+  },
+  "repeat": {
+    "unicode": "1F501",
+    "unicode_alternates": [],
+    "name": "clockwise rightwards and leftwards open circle arr",
+    "shortname": ":repeat:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["loop", "record"],
+    "moji": "🔁"
+  },
+  "repeat_one": {
+    "unicode": "1F502",
+    "unicode_alternates": [],
+    "name": "clockwise rightwards and leftwards open circle arr",
+    "shortname": ":repeat_one:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "loop"],
+    "moji": "🔂"
+  },
+  "restroom": {
+    "unicode": "1F6BB",
+    "unicode_alternates": [],
+    "name": "restroom",
+    "shortname": ":restroom:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "woman", "man", "unisex", "bathroom", "restroom", "sign", "shared", "toilet"],
+    "moji": "🚻"
+  },
+  "revolving_hearts": {
+    "unicode": "1F49E",
+    "unicode_alternates": [],
+    "name": "revolving hearts",
+    "shortname": ":revolving_hearts:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines", "heart", "hearts", "revolving", "moving", "circle", "multiple", "lovers"],
+    "moji": "💞"
+  },
+  "rewind": {
+    "unicode": "23EA",
+    "unicode_alternates": [],
+    "name": "black left-pointing double triangle",
+    "shortname": ":rewind:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "play"],
+    "moji": "⏪"
+  },
+  "ribbon": {
+    "unicode": "1F380",
+    "unicode_alternates": [],
+    "name": "ribbon",
+    "shortname": ":ribbon:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bowtie", "decoration", "girl", "pink", "ribbon", "lace", "wrap", "decorate"],
+    "moji": "🎀"
+  },
+  "rice": {
+    "unicode": "1F35A",
+    "unicode_alternates": [],
+    "name": "cooked rice",
+    "shortname": ":rice:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "rice", "white", "grain", "food", "bowl"],
+    "moji": "🍚"
+  },
+  "rice_ball": {
+    "unicode": "1F359",
+    "unicode_alternates": [],
+    "name": "rice ball",
+    "shortname": ":rice_ball:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "japanese", "rice", "ball", "white", "nori", "seaweed", "japanese"],
+    "moji": "🍙"
+  },
+  "rice_cracker": {
+    "unicode": "1F358",
+    "unicode_alternates": [],
+    "name": "rice cracker",
+    "shortname": ":rice_cracker:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "japanese", "rice", "cracker", "seaweed", "food", "japanese"],
+    "moji": "🍘"
+  },
+  "rice_scene": {
+    "unicode": "1F391",
+    "unicode_alternates": [],
+    "name": "moon viewing ceremony",
+    "shortname": ":rice_scene:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["photo", "moon", "viewing", "observing", "otsukimi", "tsukimi", "rice", "scene", "festival", "autumn"],
+    "moji": "🎑"
+  },
+  "right_speaker": {
+    "unicode": "1F568",
+    "unicode_alternates": [],
+    "name": "right speaker",
+    "shortname": ":right_speaker:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sound", "listen", "hear", "noise", "volume"]
+  },
+  "right_speaker_one": {
+    "unicode": "1F569",
+    "unicode_alternates": [],
+    "name": "right speaker with one sound wave",
+    "shortname": ":right_speaker_one:",
+    "category": "objects_symbols",
+    "aliases": [":right_speaker_with_one_sound_wave:"],
+    "aliases_ascii": [],
+    "keywords": ["low", "volume"]
+  },
+  "right_speaker_three": {
+    "unicode": "1F56A",
+    "unicode_alternates": [],
+    "name": "right speaker with three sound waves",
+    "shortname": ":right_speaker_three:",
+    "category": "objects_symbols",
+    "aliases": [":right_speaker_with_three_sound_waves:"],
+    "aliases_ascii": [],
+    "keywords": ["loud", "high", "volume"]
+  },
+  "ring": {
+    "unicode": "1F48D",
+    "unicode_alternates": [],
+    "name": "ring",
+    "shortname": ":ring:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["marriage", "propose", "valentines", "wedding"],
+    "moji": "💍"
+  },
+  "ringing_bell": {
+    "unicode": "1F56D",
+    "unicode_alternates": [],
+    "name": "ringing bell",
+    "shortname": ":ringing_bell:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alert", "ding", "volume", "sound", "chime"]
+  },
+  "rocket": {
+    "unicode": "1F680",
+    "unicode_alternates": [],
+    "name": "rocket",
+    "shortname": ":rocket:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["launch", "ship", "staffmode", "rocket", "space", "spacecraft", "astronaut", "cosmonaut"],
+    "moji": "🚀"
+  },
+  "roller_coaster": {
+    "unicode": "1F3A2",
+    "unicode_alternates": [],
+    "name": "roller coaster",
+    "shortname": ":roller_coaster:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["carnival", "fun", "photo", "play", "playground", "roller", "coaster", "amusement", "park", "fair", "ride", "entertainment"],
+    "moji": "🎢"
+  },
+  "rooster": {
+    "unicode": "1F413",
+    "unicode_alternates": [],
+    "name": "rooster",
+    "shortname": ":rooster:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "chicken", "nature", "rooster", "cockerel", "cock", "male", "cock-a-doodle-doo", "crowing"],
+    "moji": "🐓"
+  },
+  "rose": {
+    "unicode": "1F339",
+    "unicode_alternates": [],
+    "name": "rose",
+    "shortname": ":rose:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flowers", "love", "valentines", "rose", "fragrant", "flower", "thorns", "love", "petals", "romance"],
+    "moji": "🌹"
+  },
+  "rosette": {
+    "unicode": "1F3F5",
+    "unicode_alternates": [],
+    "name": "rosette",
+    "shortname": ":rosette:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flower"]
+  },
+  "rosette_black": {
+    "unicode": "1F3F6",
+    "unicode_alternates": [],
+    "name": "black rosette",
+    "shortname": ":rosette_black:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flower"]
+  },
+  "rotating_light": {
+    "unicode": "1F6A8",
+    "unicode_alternates": [],
+    "name": "police cars revolving light",
+    "shortname": ":rotating_light:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["911", "ambulance", "emergency", "police", "light", "police", "emergency"],
+    "moji": "🚨"
+  },
+  "round_pushpin": {
+    "unicode": "1F4CD",
+    "unicode_alternates": [],
+    "name": "round pushpin",
+    "shortname": ":round_pushpin:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["stationery"],
+    "moji": "📍"
+  },
+  "rowboat": {
+    "unicode": "1F6A3",
+    "unicode_alternates": [],
+    "name": "rowboat",
+    "shortname": ":rowboat:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["hobby", "ship", "sports", "water", "boat", "row", "oar", "paddle"],
+    "moji": "🚣"
+  },
+  "rugby_football": {
+    "unicode": "1F3C9",
+    "unicode_alternates": [],
+    "name": "rugby football",
+    "shortname": ":rugby_football:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sports", "rugby", "football", "ball", "sport", "team", "england"],
+    "moji": "🏉"
+  },
+  "runner": {
+    "unicode": "1F3C3",
+    "unicode_alternates": [],
+    "name": "runner",
+    "shortname": ":runner:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["exercise", "man", "walking", "run", "runner", "jog", "exercise", "sprint", "race", "dash"],
+    "moji": "🏃"
+  },
+  "running_shirt_with_sash": {
+    "unicode": "1F3BD",
+    "unicode_alternates": [],
+    "name": "running shirt with sash",
+    "shortname": ":running_shirt_with_sash:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["pageant", "play", "running", "run", "shirt", "cloths", "compete", "sports"],
+    "moji": "🎽"
+  },
+  "sagittarius": {
+    "unicode": "2650",
+    "unicode_alternates": ["2650-FE0F"],
+    "name": "sagittarius",
+    "shortname": ":sagittarius:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sagittarius", "centaur", "archer", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "sign", "zodiac", "horoscope"],
+    "moji": "♐"
+  },
+  "sailboat": {
+    "unicode": "26F5",
+    "unicode_alternates": ["26F5-FE0F"],
+    "name": "sailboat",
+    "shortname": ":sailboat:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["ship", "transportation"],
+    "moji": "⛵"
+  },
+  "sake": {
+    "unicode": "1F376",
+    "unicode_alternates": [],
+    "name": "sake bottle and cup",
+    "shortname": ":sake:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["beverage", "drink", "drunk", "wine", "sake", "wine", "rice", "ferment", "alcohol", "japanese", "drink"],
+    "moji": "🍶"
+  },
+  "sandal": {
+    "unicode": "1F461",
+    "unicode_alternates": [],
+    "name": "womans sandal",
+    "shortname": ":sandal:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fashion", "shoes"],
+    "moji": "👡"
+  },
+  "santa": {
+    "unicode": "1F385",
+    "unicode_alternates": [],
+    "name": "father christmas",
+    "shortname": ":santa:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["christmas", "father christmas", "festival", "male", "man", "xmas", "santa", "saint nick", "jolly", "ho ho ho", "north pole", "presents", "gifts", "naughty", "nice", "sleigh", "father", "christmas", "holiday"],
+    "moji": "🎅"
+  },
+  "satellite": {
+    "unicode": "1F4E1",
+    "unicode_alternates": [],
+    "name": "satellite antenna",
+    "shortname": ":satellite:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication"],
+    "moji": "📡"
+  },
+  "satellite_orbital": {
+    "unicode": "1F6F0",
+    "unicode_alternates": [],
+    "name": "satellite",
+    "shortname": ":satellite_orbital:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "orbital", "space"]
+  },
+  "saxophone": {
+    "unicode": "1F3B7",
+    "unicode_alternates": [],
+    "name": "saxophone",
+    "shortname": ":saxophone:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["instrument", "music", "saxophone", "sax", "music", "instrument", "woodwind"],
+    "moji": "🎷"
+  },
+  "school": {
+    "unicode": "1F3EB",
+    "unicode_alternates": [],
+    "name": "school",
+    "shortname": ":school:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["building", "school", "university", "elementary", "middle", "high", "college", "teach", "education"],
+    "moji": "🏫"
+  },
+  "school_satchel": {
+    "unicode": "1F392",
+    "unicode_alternates": [],
+    "name": "school satchel",
+    "shortname": ":school_satchel:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bag", "education", "student", "school", "satchel", "backpack", "bag", "packing", "pack", "hike", "education", "adventure", "travel", "sightsee"],
+    "moji": "🎒"
+  },
+  "scissors": {
+    "unicode": "2702",
+    "unicode_alternates": ["2702-FE0F"],
+    "name": "black scissors",
+    "shortname": ":scissors:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cut", "stationery"],
+    "moji": "✂"
+  },
+  "scorpius": {
+    "unicode": "264F",
+    "unicode_alternates": ["264F-FE0F"],
+    "name": "scorpius",
+    "shortname": ":scorpius:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["scorpius", "scorpion", "scorpio", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "sign", "zodiac", "horoscope"],
+    "moji": "♏"
+  },
+  "scream": {
+    "unicode": "1F631",
+    "unicode_alternates": [],
+    "name": "face screaming in fear",
+    "shortname": ":scream:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "munch", "scream", "painting", "artist", "alien"],
+    "moji": "😱"
+  },
+  "scream_cat": {
+    "unicode": "1F640",
+    "unicode_alternates": [],
+    "name": "weary cat face",
+    "shortname": ":scream_cat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cats", "munch", "weary", "sleepy", "tired", "tiredness", "study", "finals", "school", "exhausted", "scream", "painting", "artist"],
+    "moji": "🙀"
+  },
+  "scroll": {
+    "unicode": "1F4DC",
+    "unicode_alternates": [],
+    "name": "scroll",
+    "shortname": ":scroll:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["documents"],
+    "moji": "📜"
+  },
+  "seat": {
+    "unicode": "1F4BA",
+    "unicode_alternates": [],
+    "name": "seat",
+    "shortname": ":seat:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sit"],
+    "moji": "💺"
+  },
+  "secret": {
+    "unicode": "3299",
+    "unicode_alternates": ["3299-FE0F"],
+    "name": "circled ideograph secret",
+    "shortname": ":secret:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["privacy"],
+    "moji": "㊙"
+  },
+  "see_no_evil": {
+    "unicode": "1F648",
+    "unicode_alternates": [],
+    "name": "see-no-evil monkey",
+    "shortname": ":see_no_evil:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "monkey", "nature", "monkey", "see", "eyes", "vision", "sight", "mizaru"],
+    "moji": "🙈"
+  },
+  "seedling": {
+    "unicode": "1F331",
+    "unicode_alternates": [],
+    "name": "seedling",
+    "shortname": ":seedling:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["grass", "lawn", "nature", "plant", "seedling", "plant", "new", "start", "grow"],
+    "moji": "🌱"
+  },
+  "seven": {
+    "moji": "7️⃣",
+    "unicode": "0037-20E3",
+    "unicode_alternates": ["0037-FE0F-20E3"],
+    "name": "digit seven",
+    "shortname": ":seven:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["7", "blue-square", "numbers", "prime"]
+  },
+  "shaved_ice": {
+    "unicode": "1F367",
+    "unicode_alternates": [],
+    "name": "shaved ice",
+    "shortname": ":shaved_ice:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["desert", "hot", "shaved", "ice", "dessert", "treat", "syrup", "flavoring"],
+    "moji": "🍧"
+  },
+  "sheep": {
+    "unicode": "1F411",
+    "unicode_alternates": [],
+    "name": "sheep",
+    "shortname": ":sheep:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "sheep", "wool", "flock", "follower", "ewe", "female", "lamb"],
+    "moji": "🐑"
+  },
+  "shell": {
+    "unicode": "1F41A",
+    "unicode_alternates": [],
+    "name": "spiral shell",
+    "shortname": ":shell:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["beach", "nature", "sea", "shell", "spiral", "beach", "sand", "crab", "nautilus"],
+    "moji": "🐚"
+  },
+  "shield": {
+    "unicode": "1F6E1",
+    "unicode_alternates": [],
+    "name": "shield",
+    "shortname": ":shield:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["interstate", "route", "sign", "highway", "interstate"]
+  },
+  "ship": {
+    "unicode": "1F6A2",
+    "unicode_alternates": [],
+    "name": "ship",
+    "shortname": ":ship:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["titanic", "transportation", "ferry", "ship", "boat"],
+    "moji": "🚢"
+  },
+  "shirt": {
+    "unicode": "1F455",
+    "unicode_alternates": [],
+    "name": "t-shirt",
+    "shortname": ":shirt:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cloth", "fashion"],
+    "moji": "👕"
+  },
+  "shopping_bags": {
+    "unicode": "1F6CD",
+    "unicode_alternates": [],
+    "name": "shopping bags",
+    "shortname": ":shopping_bags:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["purchase", "mall", "buy", "store", "shop"]
+  },
+  "shower": {
+    "unicode": "1F6BF",
+    "unicode_alternates": [],
+    "name": "shower",
+    "shortname": ":shower:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bath", "clean", "wash", "bathroom", "shower", "soap", "water", "clean", "shampoo", "lather"],
+    "moji": "🚿"
+  },
+  "signal_strength": {
+    "unicode": "1F4F6",
+    "unicode_alternates": [],
+    "name": "antenna with bars",
+    "shortname": ":signal_strength:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "📶"
+  },
+  "six": {
+    "moji": "6️⃣",
+    "unicode": "0036-20E3",
+    "unicode_alternates": ["0036-FE0F-20E3"],
+    "name": "digit six",
+    "shortname": ":six:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["6", "blue-square", "numbers"]
+  },
+  "six_pointed_star": {
+    "unicode": "1F52F",
+    "unicode_alternates": [],
+    "name": "six pointed star with middle dot",
+    "shortname": ":six_pointed_star:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["purple-square"],
+    "moji": "🔯"
+  },
+  "ski": {
+    "unicode": "1F3BF",
+    "unicode_alternates": [],
+    "name": "ski and ski boot",
+    "shortname": ":ski:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cold", "sports", "winter", "ski", "downhill", "cross-country", "poles", "snow", "winter", "mountain", "alpine", "powder", "slalom", "freestyle"],
+    "moji": "🎿"
+  },
+  "skull": {
+    "unicode": "1F480",
+    "unicode_alternates": [],
+    "name": "skull",
+    "shortname": ":skull:",
+    "category": "emoticons",
+    "aliases": [":skeleton:"],
+    "aliases_ascii": [],
+    "keywords": ["dead", "skeleton", "dying"],
+    "moji": "💀"
+  },
+  "sleeping": {
+    "unicode": "1F634",
+    "unicode_alternates": [],
+    "name": "sleeping face",
+    "shortname": ":sleeping:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "sleepy", "tired", "sleep", "sleepy", "sleeping", "snore"],
+    "moji": "😴"
+  },
+  "sleeping_accommodation": {
+    "unicode": "1F6CC",
+    "unicode_alternates": [],
+    "name": "sleeping accommodation",
+    "shortname": ":sleeping_accommodation:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["hotel", "motel", "rest"]
+  },
+  "sleepy": {
+    "unicode": "1F62A",
+    "unicode_alternates": [],
+    "name": "sleepy face",
+    "shortname": ":sleepy:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "rest", "tired", "sleepy", "tired", "exhausted"],
+    "moji": "😪"
+  },
+  "slight_frown": {
+    "unicode": "1F641",
+    "unicode_alternates": [],
+    "name": "slightly frowning face",
+    "shortname": ":slight_frown:",
+    "category": "people",
+    "aliases": [":slightly_frowning_face:"],
+    "aliases_ascii": [],
+    "keywords": ["slight", "frown", "unhappy", "disappointed"]
+  },
+  "slight_smile": {
+    "unicode": "1F642",
+    "unicode_alternates": [],
+    "name": "slightly smiling face",
+    "shortname": ":slight_smile:",
+    "category": "people",
+    "aliases": [":slightly_smiling_face:"],
+    "aliases_ascii": [],
+    "keywords": ["slight", "smile", "happy"]
+  },
+  "slot_machine": {
+    "unicode": "1F3B0",
+    "unicode_alternates": [],
+    "name": "slot machine",
+    "shortname": ":slot_machine:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bet", "gamble", "vegas", "slot", "machine", "gamble", "one-armed bandit", "slots", "luck"],
+    "moji": "🎰"
+  },
+  "small_blue_diamond": {
+    "unicode": "1F539",
+    "unicode_alternates": [],
+    "name": "small blue diamond",
+    "shortname": ":small_blue_diamond:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "🔹"
+  },
+  "small_orange_diamond": {
+    "unicode": "1F538",
+    "unicode_alternates": [],
+    "name": "small orange diamond",
+    "shortname": ":small_orange_diamond:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "🔸"
+  },
+  "small_red_triangle": {
+    "unicode": "1F53A",
+    "unicode_alternates": [],
+    "name": "up-pointing red triangle",
+    "shortname": ":small_red_triangle:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "🔺"
+  },
+  "small_red_triangle_down": {
+    "unicode": "1F53B",
+    "unicode_alternates": [],
+    "name": "down-pointing red triangle",
+    "shortname": ":small_red_triangle_down:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "🔻"
+  },
+  "smile": {
+    "unicode": "1F604",
+    "unicode_alternates": [],
+    "name": "smiling face with open mouth and smiling eyes",
+    "shortname": ":smile:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":)", ":-)", "=]", "=)", ":]"],
+    "keywords": ["face", "funny", "haha", "happy", "joy", "laugh", "smile", "smiley", "smiling"],
+    "moji": "😄"
+  },
+  "smile_cat": {
+    "unicode": "1F638",
+    "unicode_alternates": [],
+    "name": "grinning cat face with smiling eyes",
+    "shortname": ":smile_cat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cats", "cat", "smile", "grin", "grinning"],
+    "moji": "😸"
+  },
+  "smiley": {
+    "unicode": "1F603",
+    "unicode_alternates": [],
+    "name": "smiling face with open mouth",
+    "shortname": ":smiley:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":D", ":-D", "=D"],
+    "keywords": ["face", "haha", "happy", "joy", "smiling", "smile", "smiley"],
+    "moji": "😃"
+  },
+  "smiley_cat": {
+    "unicode": "1F63A",
+    "unicode_alternates": [],
+    "name": "smiling cat face with open mouth",
+    "shortname": ":smiley_cat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cats", "happy", "smile", "smiley", "cat", "happy"],
+    "moji": "😺"
+  },
+  "smiling_imp": {
+    "unicode": "1F608",
+    "unicode_alternates": [],
+    "name": "smiling face with horns",
+    "shortname": ":smiling_imp:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["devil", "horns", "horns", "devil", "impish", "trouble"],
+    "moji": "😈"
+  },
+  "smirk": {
+    "unicode": "1F60F",
+    "unicode_alternates": [],
+    "name": "smirking face",
+    "shortname": ":smirk:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mean", "prank", "smile", "smug", "smirking", "smirk", "smug", "smile", "half-smile", "conceited"],
+    "moji": "😏"
+  },
+  "smirk_cat": {
+    "unicode": "1F63C",
+    "unicode_alternates": [],
+    "name": "cat face with wry smile",
+    "shortname": ":smirk_cat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cats", "smirk", "smirking", "wry", "confident", "confidence"],
+    "moji": "😼"
+  },
+  "smoking": {
+    "unicode": "1F6AC",
+    "unicode_alternates": [],
+    "name": "smoking symbol",
+    "shortname": ":smoking:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cigarette", "kills", "tobacco", "smoking", "cigarette", "smoke", "cancer", "lungs", "inhale", "tar", "nicotine"],
+    "moji": "🚬"
+  },
+  "snail": {
+    "unicode": "1F40C",
+    "unicode_alternates": [],
+    "name": "snail",
+    "shortname": ":snail:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "shell", "slow", "snail", "slow", "escargot", "french", "appetizer"],
+    "moji": "🐌"
+  },
+  "snake": {
+    "unicode": "1F40D",
+    "unicode_alternates": [],
+    "name": "snake",
+    "shortname": ":snake:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "evil"],
+    "moji": "🐍"
+  },
+  "snowboarder": {
+    "unicode": "1F3C2",
+    "unicode_alternates": [],
+    "name": "snowboarder",
+    "shortname": ":snowboarder:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sports", "winter", "snow", "boarding", "sports", "freestyle", "halfpipe", "board", "mountain", "alpine", "winter"],
+    "moji": "🏂"
+  },
+  "snowflake": {
+    "unicode": "2744",
+    "unicode_alternates": ["2744-FE0F"],
+    "name": "snowflake",
+    "shortname": ":snowflake:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["christmas", "cold", "season", "weather", "winter", "xmas", "snowflake", "snow", "frozen", "droplet", "ice", "crystal", "cold", "chilly", "winter", "unique", "special", "below zero", "elsa"],
+    "moji": "❄"
+  },
+  "snowman": {
+    "unicode": "26C4",
+    "unicode_alternates": ["26C4-FE0F"],
+    "name": "snowman without snow",
+    "shortname": ":snowman:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["christmas", "cold", "season", "weather", "winter", "xmas"],
+    "moji": "⛄"
+  },
+  "sob": {
+    "unicode": "1F62D",
+    "unicode_alternates": [],
+    "name": "loudly crying face",
+    "shortname": ":sob:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cry", "face", "sad", "tears", "upset", "cry", "sob", "tears", "sad", "melancholy", "morn", "somber", "hurt"],
+    "moji": "😭"
+  },
+  "soccer": {
+    "unicode": "26BD",
+    "unicode_alternates": ["26BD-FE0F"],
+    "name": "soccer ball",
+    "shortname": ":soccer:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["balls", "fifa", "football", "sports", "european", "football"],
+    "moji": "âš½"
+  },
+  "soon": {
+    "unicode": "1F51C",
+    "unicode_alternates": [],
+    "name": "soon with rightwards arrow above",
+    "shortname": ":soon:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arrow", "words"],
+    "moji": "🔜"
+  },
+  "sos": {
+    "unicode": "1F198",
+    "unicode_alternates": [],
+    "name": "squared sos",
+    "shortname": ":sos:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["emergency", "help", "red-square", "words"],
+    "moji": "🆘"
+  },
+  "sound": {
+    "unicode": "1F509",
+    "unicode_alternates": [],
+    "name": "speaker with one sound wave",
+    "shortname": ":sound:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["speaker", "volume"],
+    "moji": "🔉"
+  },
+  "space_invader": {
+    "unicode": "1F47E",
+    "unicode_alternates": [],
+    "name": "alien monster",
+    "shortname": ":space_invader:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arcade", "game"],
+    "moji": "👾"
+  },
+  "spades": {
+    "unicode": "2660",
+    "unicode_alternates": ["2660-FE0F"],
+    "name": "black spade suit",
+    "shortname": ":spades:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cards", "poker"],
+    "moji": "â™ "
+  },
+  "spaghetti": {
+    "unicode": "1F35D",
+    "unicode_alternates": [],
+    "name": "spaghetti",
+    "shortname": ":spaghetti:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "italian", "noodle", "spaghetti", "noodles", "tomato", "sauce", "italian"],
+    "moji": "🍝"
+  },
+  "sparkle": {
+    "unicode": "2747",
+    "unicode_alternates": ["2747-FE0F"],
+    "name": "sparkle",
+    "shortname": ":sparkle:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["green-square", "stars"],
+    "moji": "❇"
+  },
+  "sparkler": {
+    "unicode": "1F387",
+    "unicode_alternates": [],
+    "name": "firework sparkler",
+    "shortname": ":sparkler:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["night", "shine", "stars"],
+    "moji": "🎇"
+  },
+  "sparkles": {
+    "unicode": "2728",
+    "unicode_alternates": [],
+    "name": "sparkles",
+    "shortname": ":sparkles:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cool", "shine", "shiny", "stars"],
+    "moji": "✨"
+  },
+  "sparkling_heart": {
+    "unicode": "1F496",
+    "unicode_alternates": [],
+    "name": "sparkling heart",
+    "shortname": ":sparkling_heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines"],
+    "moji": "💖"
+  },
+  "speak_no_evil": {
+    "unicode": "1F64A",
+    "unicode_alternates": [],
+    "name": "speak-no-evil monkey",
+    "shortname": ":speak_no_evil:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "monkey", "monkey", "mouth", "talk", "say", "words", "verbal", "verbalize", "oral", "iwazaru"],
+    "moji": "🙊"
+  },
+  "speaker": {
+    "unicode": "1F508",
+    "unicode_alternates": [],
+    "name": "speaker",
+    "shortname": ":speaker:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sound", "listen", "hear", "noise"]
+  },
+  "speaking_head": {
+    "unicode": "1F5E3",
+    "unicode_alternates": [],
+    "name": "speaking head in silhouette",
+    "shortname": ":speaking_head:",
+    "category": "objects_symbols",
+    "aliases": [":speaking_head_in_silhouette:"],
+    "aliases_ascii": [],
+    "keywords": ["talk"]
+  },
+  "speech_balloon": {
+    "unicode": "1F4AC",
+    "unicode_alternates": [],
+    "name": "speech balloon",
+    "shortname": ":speech_balloon:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bubble", "words", "speech", "balloon", "talk", "conversation", "communication", "comic", "dialogue"],
+    "moji": "💬"
+  },
+  "speech_left": {
+    "unicode": "1F5E8",
+    "unicode_alternates": [],
+    "name": "left speech bubble",
+    "shortname": ":speech_left:",
+    "category": "objects_symbols",
+    "aliases": [":left_speech_bubble:"],
+    "aliases_ascii": [],
+    "keywords": ["balloon", "words", "talk", "conversation", "communication", "comic", "dialogue"]
+  },
+  "speech_right": {
+    "unicode": "1F5E9",
+    "unicode_alternates": [],
+    "name": "right speech bubble",
+    "shortname": ":speech_right:",
+    "category": "objects_symbols",
+    "aliases": [":right_speech_bubble:"],
+    "aliases_ascii": [],
+    "keywords": ["balloon", "words", "talk", "conversation", "communication", "comic", "dialogue"]
+  },
+  "speech_three": {
+    "unicode": "1F5EB",
+    "unicode_alternates": [],
+    "name": "three speech bubbles",
+    "shortname": ":speech_three:",
+    "category": "objects_symbols",
+    "aliases": [":three_speech_bubbles:"],
+    "aliases_ascii": [],
+    "keywords": ["balloon", "words", "talk", "conversation", "communication", "comic", "dialogue"]
+  },
+  "speech_two": {
+    "unicode": "1F5EA",
+    "unicode_alternates": [],
+    "name": "two speech bubbles",
+    "shortname": ":speech_two:",
+    "category": "objects_symbols",
+    "aliases": [":two_speech_bubbles:"],
+    "aliases_ascii": [],
+    "keywords": ["balloon", "words", "talk", "conversation", "communication", "comic", "dialogue"]
+  },
+  "speedboat": {
+    "unicode": "1F6A4",
+    "unicode_alternates": [],
+    "name": "speedboat",
+    "shortname": ":speedboat:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["ship", "transportation", "vehicle", "motor", "speed", "ski", "power", "boat"],
+    "moji": "🚤"
+  },
+  "spider": {
+    "unicode": "1F577",
+    "unicode_alternates": [],
+    "name": "spider",
+    "shortname": ":spider:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["arachnid", "eight-legged"]
+  },
+  "spider_web": {
+    "unicode": "1F578",
+    "unicode_alternates": [],
+    "name": "spider web",
+    "shortname": ":spider_web:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cobweb"]
+  },
+  "spy": {
+    "unicode": "1F575",
+    "unicode_alternates": [],
+    "name": "sleuth or spy",
+    "shortname": ":spy:",
+    "category": "people",
+    "aliases": [":sleuth_or_spy:"],
+    "aliases_ascii": [],
+    "keywords": ["pi", "undercover", "investigator"]
+  },
+  "stadium": {
+    "unicode": "1F3DF",
+    "unicode_alternates": [],
+    "name": "stadium",
+    "shortname": ":stadium:",
+    "category": "travel_places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sport", "event", "concert", "convention", "game"]
+  },
+  "star": {
+    "unicode": "2B50",
+    "unicode_alternates": ["2B50-FE0F"],
+    "name": "white medium star",
+    "shortname": ":star:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["night", "yellow"],
+    "moji": "⭐"
+  },
+  "star2": {
+    "unicode": "1F31F",
+    "unicode_alternates": [],
+    "name": "glowing star",
+    "shortname": ":star2:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["night", "sparkle", "glow", "glowing", "star", "five", "points", "classic"],
+    "moji": "🌟"
+  },
+  "stars": {
+    "unicode": "1F320",
+    "unicode_alternates": [],
+    "name": "shooting star",
+    "shortname": ":stars:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["night", "photo", "shooting", "shoot", "star", "sky", "night", "comet", "meteoroid"],
+    "moji": "🌠"
+  },
+  "station": {
+    "unicode": "1F689",
+    "unicode_alternates": [],
+    "name": "station",
+    "shortname": ":station:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["public", "transportation", "vehicle", "station", "train", "subway"],
+    "moji": "🚉"
+  },
+  "statue_of_liberty": {
+    "unicode": "1F5FD",
+    "unicode_alternates": [],
+    "name": "statue of liberty",
+    "shortname": ":statue_of_liberty:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["american", "newyork"],
+    "moji": "🗽"
+  },
+  "steam_locomotive": {
+    "unicode": "1F682",
+    "unicode_alternates": [],
+    "name": "steam locomotive",
+    "shortname": ":steam_locomotive:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["train", "transportation", "vehicle", "locomotive", "steam", "train", "engine"],
+    "moji": "🚂"
+  },
+  "stereo": {
+    "unicode": "1F4FE",
+    "unicode_alternates": [],
+    "name": "portable stereo",
+    "shortname": ":stereo:",
+    "category": "objects_symbols",
+    "aliases": [":portable_stereo:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "music", "program", "boom", "box"]
+  },
+  "stew": {
+    "unicode": "1F372",
+    "unicode_alternates": [],
+    "name": "pot of food",
+    "shortname": ":stew:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "meat", "stew", "hearty", "soup", "thick", "hot", "pot"],
+    "moji": "🍲"
+  },
+  "stock_chart": {
+    "unicode": "1F5E0",
+    "unicode_alternates": [],
+    "name": "stock chart",
+    "shortname": ":stock_chart:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["graph", "presentation", "stats", "business"]
+  },
+  "straight_ruler": {
+    "unicode": "1F4CF",
+    "unicode_alternates": [],
+    "name": "straight ruler",
+    "shortname": ":straight_ruler:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["stationery"],
+    "moji": "📏"
+  },
+  "strawberry": {
+    "unicode": "1F353",
+    "unicode_alternates": [],
+    "name": "strawberry",
+    "shortname": ":strawberry:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "nature", "strawberry", "short", "cake", "berry"],
+    "moji": "🍓"
+  },
+  "stuck_out_tongue": {
+    "unicode": "1F61B",
+    "unicode_alternates": [],
+    "name": "face with stuck-out tongue",
+    "shortname": ":stuck_out_tongue:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [":P", ":-P", "=P", ":-p", ":p", "=p", ":-Þ", ":Þ", ":þ", ":-þ", ":-b", ":b", "d:"],
+    "keywords": ["childish", "face", "mischievous", "playful", "prank", "tongue", "silly", "playful", "cheeky"],
+    "moji": "😛"
+  },
+  "stuck_out_tongue_closed_eyes": {
+    "unicode": "1F61D",
+    "unicode_alternates": [],
+    "name": "face with stuck-out tongue and tightly-closed eyes",
+    "shortname": ":stuck_out_tongue_closed_eyes:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "mischievous", "playful", "prank", "tongue", "kidding", "silly", "playful", "ecstatic"],
+    "moji": "😝"
+  },
+  "stuck_out_tongue_winking_eye": {
+    "unicode": "1F61C",
+    "unicode_alternates": [],
+    "name": "face with stuck-out tongue and winking eye",
+    "shortname": ":stuck_out_tongue_winking_eye:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [">:P", "X-P", "x-p"],
+    "keywords": ["childish", "face", "mischievous", "playful", "prank", "tongue", "wink", "winking", "kidding", "silly", "playful", "crazy"],
+    "moji": "😜"
+  },
+  "sun_with_face": {
+    "unicode": "1F31E",
+    "unicode_alternates": [],
+    "name": "sun with face",
+    "shortname": ":sun_with_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["morning", "sun", "anthropomorphic", "face", "sky"],
+    "moji": "🌞"
+  },
+  "sunflower": {
+    "unicode": "1F33B",
+    "unicode_alternates": [],
+    "name": "sunflower",
+    "shortname": ":sunflower:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "plant", "sunflower", "sun", "flower", "seeds", "yellow"],
+    "moji": "🌻"
+  },
+  "sunglasses": {
+    "unicode": "1F60E",
+    "unicode_alternates": [],
+    "name": "smiling face with sunglasses",
+    "shortname": ":sunglasses:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["B-)", "B)", "8)", "8-)", "B-D", "8-D"],
+    "keywords": ["cool", "face", "smiling", "sunglasses", "sun", "glasses", "sunny", "cool", "smooth"],
+    "moji": "😎"
+  },
+  "sunny": {
+    "unicode": "2600",
+    "unicode_alternates": ["2600-FE0F"],
+    "name": "black sun with rays",
+    "shortname": ":sunny:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["brightness", "weather"]
+  },
+  "sunrise": {
+    "unicode": "1F305",
+    "unicode_alternates": [],
+    "name": "sunrise",
+    "shortname": ":sunrise:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["morning", "photo", "vacation", "view", "sunrise", "sun", "morning", "color", "sky"],
+    "moji": "🌅"
+  },
+  "sunrise_over_mountains": {
+    "unicode": "1F304",
+    "unicode_alternates": [],
+    "name": "sunrise over mountains",
+    "shortname": ":sunrise_over_mountains:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["photo", "vacation", "view", "sunrise", "sun", "morning", "mountain", "rural", "color", "sky"],
+    "moji": "🌄"
+  },
+  "surfer": {
+    "unicode": "1F3C4",
+    "unicode_alternates": [],
+    "name": "surfer",
+    "shortname": ":surfer:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["ocean", "sea", "sports", "surfer", "surf", "wave", "ocean", "ride", "swell"],
+    "moji": "🏄"
+  },
+  "sushi": {
+    "unicode": "1F363",
+    "unicode_alternates": [],
+    "name": "sushi",
+    "shortname": ":sushi:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "japanese", "sushi", "fish", "raw", "nigiri", "japanese"],
+    "moji": "🍣"
+  },
+  "suspension_railway": {
+    "unicode": "1F69F",
+    "unicode_alternates": [],
+    "name": "suspension railway",
+    "shortname": ":suspension_railway:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "suspension", "railway", "rail", "train", "transportation"],
+    "moji": "🚟"
+  },
+  "sweat": {
+    "unicode": "1F613",
+    "unicode_alternates": [],
+    "name": "face with cold sweat",
+    "shortname": ":sweat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["':(", "':-(", "'=("],
+    "keywords": ["cold", "sweat", "sick", "anxious", "worried", "clammy", "diaphoresis", "face", "hot"],
+    "moji": "😓"
+  },
+  "sweat_drops": {
+    "unicode": "1F4A6",
+    "unicode_alternates": [],
+    "name": "splashing sweat symbol",
+    "shortname": ":sweat_drops:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["water"],
+    "moji": "💦"
+  },
+  "sweat_smile": {
+    "unicode": "1F605",
+    "unicode_alternates": [],
+    "name": "smiling face with open mouth and cold sweat",
+    "shortname": ":sweat_smile:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": ["':)", "':-)", "'=)", "':D", "':-D", "'=D"],
+    "keywords": ["face", "happy", "hot", "smiling", "cold", "sweat", "perspiration"],
+    "moji": "😅"
+  },
+  "sweet_potato": {
+    "unicode": "1F360",
+    "unicode_alternates": [],
+    "name": "roasted sweet potato",
+    "shortname": ":sweet_potato:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "nature", "sweet", "potato", "potassium", "roasted", "roast"],
+    "moji": "🍠"
+  },
+  "swimmer": {
+    "unicode": "1F3CA",
+    "unicode_alternates": [],
+    "name": "swimmer",
+    "shortname": ":swimmer:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sports", "swimmer", "swim", "water", "pool", "laps", "freestyle", "butterfly", "breaststroke", "backstroke"],
+    "moji": "🏊"
+  },
+  "symbols": {
+    "unicode": "1F523",
+    "unicode_alternates": [],
+    "name": "input symbol for symbols",
+    "shortname": ":symbols:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "🔣"
+  },
+  "syringe": {
+    "unicode": "1F489",
+    "unicode_alternates": [],
+    "name": "syringe",
+    "shortname": ":syringe:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blood", "drugs", "health", "hospital", "medicine", "needle"],
+    "moji": "💉"
+  },
+  "tada": {
+    "unicode": "1F389",
+    "unicode_alternates": [],
+    "name": "party popper",
+    "shortname": ":tada:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["contulations", "party", "party", "popper", "tada", "celebration", "victory", "announcement", "climax", "congratulations"],
+    "moji": "🎉"
+  },
+  "tanabata_tree": {
+    "unicode": "1F38B",
+    "unicode_alternates": [],
+    "name": "tanabata tree",
+    "shortname": ":tanabata_tree:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "plant", "tanabata", "tree", "festival", "star", "wish", "holiday"],
+    "moji": "🎋"
+  },
+  "tangerine": {
+    "unicode": "1F34A",
+    "unicode_alternates": [],
+    "name": "tangerine",
+    "shortname": ":tangerine:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "nature", "tangerine", "citrus", "orange"],
+    "moji": "🍊"
+  },
+  "taurus": {
+    "unicode": "2649",
+    "unicode_alternates": ["2649-FE0F"],
+    "name": "taurus",
+    "shortname": ":taurus:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["purple-square", "sign", "taurus", "bull", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "zodiac", "horoscope"],
+    "moji": "♉"
+  },
+  "taxi": {
+    "unicode": "1F695",
+    "unicode_alternates": [],
+    "name": "taxi",
+    "shortname": ":taxi:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cars", "transportation", "uber", "vehicle", "taxi", "car", "automobile", "city", "transport", "service"],
+    "moji": "🚕"
+  },
+  "tea": {
+    "unicode": "1F375",
+    "unicode_alternates": [],
+    "name": "teacup without handle",
+    "shortname": ":tea:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bowl", "breakfast", "british", "drink", "green", "tea", "leaf", "drink", "teacup", "hot", "beverage"],
+    "moji": "🍵"
+  },
+  "telephone": {
+    "unicode": "260E",
+    "unicode_alternates": ["260E-FE0F"],
+    "name": "black telephone",
+    "shortname": ":telephone:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "dial", "technology"],
+    "moji": "☎"
+  },
+  "telephone_black": {
+    "unicode": "1F57F",
+    "unicode_alternates": [],
+    "name": "black touchtone telephone",
+    "shortname": ":telephone_black:",
+    "category": "objects_symbols",
+    "aliases": [":black_touchtone_telephone:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "dial", "technology"]
+  },
+  "telephone_receiver": {
+    "unicode": "1F4DE",
+    "unicode_alternates": [],
+    "name": "telephone receiver",
+    "shortname": ":telephone_receiver:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["communication", "dial", "technology"],
+    "moji": "📞"
+  },
+  "telephone_white": {
+    "unicode": "1F57E",
+    "unicode_alternates": [],
+    "name": "white touchtone telephone",
+    "shortname": ":telephone_white:",
+    "category": "objects_symbols",
+    "aliases": [":white_touchtone_telephone:"],
+    "aliases_ascii": [],
+    "keywords": ["communication", "dial", "technology"]
+  },
+  "telescope": {
+    "unicode": "1F52D",
+    "unicode_alternates": [],
+    "name": "telescope",
+    "shortname": ":telescope:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["space", "stars"],
+    "moji": "🔭"
+  },
+  "tennis": {
+    "unicode": "1F3BE",
+    "unicode_alternates": [],
+    "name": "tennis racquet and ball",
+    "shortname": ":tennis:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["balls", "green", "sports", "tennis", "racket", "racquet", "ball", "game", "net", "court", "love"],
+    "moji": "🎾"
+  },
+  "tent": {
+    "unicode": "26FA",
+    "unicode_alternates": ["26FA-FE0F"],
+    "name": "tent",
+    "shortname": ":tent:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["camp", "outdoors", "photo"],
+    "moji": "⛺"
+  },
+  "thermometer": {
+    "unicode": "1F321",
+    "unicode_alternates": [],
+    "name": "thermometer",
+    "shortname": ":thermometer:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["temperature"]
+  },
+  "thought_balloon": {
+    "unicode": "1F4AD",
+    "unicode_alternates": [],
+    "name": "thought balloon",
+    "shortname": ":thought_balloon:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bubble", "cloud", "speech", "thought", "balloon", "comic", "think", "day dream", "wonder"],
+    "moji": "💭"
+  },
+  "thought_left": {
+    "unicode": "1F5EC",
+    "unicode_alternates": [],
+    "name": "left thought bubble",
+    "shortname": ":thought_left:",
+    "category": "objects_symbols",
+    "aliases": [":left_thought_bubble:"],
+    "aliases_ascii": [],
+    "keywords": ["balloon", "cloud", "comic", "think", "day dream", "wonder"]
+  },
+  "thought_right": {
+    "unicode": "1F5ED",
+    "unicode_alternates": [],
+    "name": "right thought bubble",
+    "shortname": ":thought_right:",
+    "category": "objects_symbols",
+    "aliases": [":right_thought_bubble:"],
+    "aliases_ascii": [],
+    "keywords": ["balloon", "cloud", "comic", "think", "day dream", "wonder"]
+  },
+  "three": {
+    "moji": "3️⃣",
+    "unicode": "0033-20E3",
+    "unicode_alternates": ["0033-FE0F-20E3"],
+    "name": "digit three",
+    "shortname": ":three:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["3", "blue-square", "numbers", "prime"]
+  },
+  "thumbs_down_reverse": {
+    "unicode": "1F593",
+    "unicode_alternates": [],
+    "name": "reversed thumbs down sign",
+    "shortname": ":thumbs_down_reverse:",
+    "category": "people",
+    "aliases": [":reversed_thumbs_down_sign:"],
+    "aliases_ascii": [],
+    "keywords": ["hand", "no", "-1"]
+  },
+  "thumbs_up_reverse": {
+    "unicode": "1F592",
+    "unicode_alternates": [],
+    "name": "reversed thumbs up sign",
+    "shortname": ":thumbs_up_reverse:",
+    "category": "people",
+    "aliases": [":reversed_thumbs_up_sign:"],
+    "aliases_ascii": [],
+    "keywords": ["cool", "hand", "like", "yes", "+1"]
+  },
+  "thumbsdown": {
+    "unicode": "1F44E",
+    "unicode_alternates": [],
+    "name": "thumbs down sign",
+    "shortname": ":thumbsdown:",
+    "category": "emoticons",
+    "aliases": [":-1:"],
+    "aliases_ascii": [],
+    "keywords": ["hand", "no"],
+    "moji": "👎"
+  },
+  "thumbsup": {
+    "unicode": "1F44D",
+    "unicode_alternates": [],
+    "name": "thumbs up sign",
+    "shortname": ":thumbsup:",
+    "category": "emoticons",
+    "aliases": [":+1:"],
+    "aliases_ascii": [],
+    "keywords": ["cool", "hand", "like", "yes"],
+    "moji": "👍"
+  },
+  "ticket": {
+    "unicode": "1F3AB",
+    "unicode_alternates": [],
+    "name": "ticket",
+    "shortname": ":ticket:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["concert", "event", "pass", "ticket", "show", "entertainment", "stub", "admission", "proof", "purchase"],
+    "moji": "🎫"
+  },
+  "tickets": {
+    "unicode": "1F39F",
+    "unicode_alternates": [],
+    "name": "admission tickets",
+    "shortname": ":tickets:",
+    "category": "activity",
+    "aliases": [":admission_tickets:"],
+    "aliases_ascii": [],
+    "keywords": ["concert", "event", "pass", "show", "entertainment", "stub", "proof", "purchase"]
+  },
+  "tiger": {
+    "unicode": "1F42F",
+    "unicode_alternates": [],
+    "name": "tiger face",
+    "shortname": ":tiger:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal"],
+    "moji": "🐯"
+  },
+  "tiger2": {
+    "unicode": "1F405",
+    "unicode_alternates": [],
+    "name": "tiger",
+    "shortname": ":tiger2:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "tiger", "cat", "striped", "tony", "tigger", "hobs"],
+    "moji": "🐅"
+  },
+  "tired_face": {
+    "unicode": "1F62B",
+    "unicode_alternates": [],
+    "name": "tired face",
+    "shortname": ":tired_face:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "frustrated", "sick", "upset", "whine", "exhausted", "sleepy", "tired"],
+    "moji": "😫"
+  },
+  "toilet": {
+    "unicode": "1F6BD",
+    "unicode_alternates": [],
+    "name": "toilet",
+    "shortname": ":toilet:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["restroom", "wc", "toilet", "bathroom", "throne", "porcelain", "waste", "flush", "plumbing"],
+    "moji": "🚽"
+  },
+  "tokyo_tower": {
+    "unicode": "1F5FC",
+    "unicode_alternates": [],
+    "name": "tokyo tower",
+    "shortname": ":tokyo_tower:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["japan", "photo"],
+    "moji": "🗼"
+  },
+  "tomato": {
+    "unicode": "1F345",
+    "unicode_alternates": [],
+    "name": "tomato",
+    "shortname": ":tomato:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "nature", "vegetable", "tomato", "fruit", "sauce", "italian"],
+    "moji": "🍅"
+  },
+  "tongue": {
+    "unicode": "1F445",
+    "unicode_alternates": [],
+    "name": "tongue",
+    "shortname": ":tongue:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mouth", "playful", "tongue", "mouth", "taste", "buds", "food", "silly", "playful", "tease", "kiss", "french kiss", "lick", "tasty", "playfulness", "silliness", "intimacy"],
+    "moji": "👅"
+  },
+  "tools": {
+    "unicode": "1F6E0",
+    "unicode_alternates": [],
+    "name": "hammer and wrench",
+    "shortname": ":tools:",
+    "category": "objects_symbols",
+    "aliases": [":hammer_and_wrench:"],
+    "aliases_ascii": [],
+    "keywords": ["tools"]
+  },
+  "top": {
+    "unicode": "1F51D",
+    "unicode_alternates": [],
+    "name": "top with upwards arrow above",
+    "shortname": ":top:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "words"],
+    "moji": "🔝"
+  },
+  "tophat": {
+    "unicode": "1F3A9",
+    "unicode_alternates": [],
+    "name": "top hat",
+    "shortname": ":tophat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["classy", "gentleman", "magic", "top", "hat", "cap", "beaver", "high", "tall", "stove", "pipe", "chimney", "topper", "london", "period piece", "magic", "magician"],
+    "moji": "🎩"
+  },
+  "trackball": {
+    "unicode": "1F5B2",
+    "unicode_alternates": [],
+    "name": "trackball",
+    "shortname": ":trackball:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["input", "device", "gadget"]
+  },
+  "tractor": {
+    "unicode": "1F69C",
+    "unicode_alternates": [],
+    "name": "tractor",
+    "shortname": ":tractor:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["agriculture", "car", "farming", "vehicle", "tractor", "farm", "construction", "machine", "digger"],
+    "moji": "🚜"
+  },
+  "traffic_light": {
+    "unicode": "1F6A5",
+    "unicode_alternates": [],
+    "name": "horizontal traffic light",
+    "shortname": ":traffic_light:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["traffic", "transportation", "traffic", "light", "stop", "go", "yield", "horizontal"],
+    "moji": "🚥"
+  },
+  "train": {
+    "unicode": "1F68B",
+    "unicode_alternates": [],
+    "name": "Tram Car",
+    "shortname": ":train:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["tram", "rail"]
+  },
+  "train2": {
+    "unicode": "1F686",
+    "unicode_alternates": [],
+    "name": "train",
+    "shortname": ":train2:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "train", "locomotive", "rail"],
+    "moji": "🚆"
+  },
+  "train_diesel": {
+    "unicode": "1F6F2",
+    "unicode_alternates": [],
+    "name": "diesel locomotive",
+    "shortname": ":train_diesel:",
+    "category": "travel_places",
+    "aliases": [":diesel_locomotive:"],
+    "aliases_ascii": [],
+    "keywords": ["train", "transportation", "engine", "rail"]
+  },
+  "tram": {
+    "unicode": "1F68A",
+    "unicode_alternates": [],
+    "name": "tram",
+    "shortname": ":tram:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "vehicle", "tram", "transportation", "transport"],
+    "moji": "🚊"
+  },
+  "triangle_round": {
+    "unicode": "1F6C6",
+    "unicode_alternates": [],
+    "name": "triangle with rounded corners",
+    "shortname": ":triangle_round:",
+    "category": "objects_symbols",
+    "aliases": [":triangle_with_rounded_corners:"],
+    "aliases_ascii": [],
+    "keywords": ["caution", "warning", "alert"]
+  },
+  "triangular_flag_on_post": {
+    "unicode": "1F6A9",
+    "unicode_alternates": [],
+    "name": "triangular flag on post",
+    "shortname": ":triangular_flag_on_post:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["triangle", "triangular", "flag", "golf", "post", "flagpole"],
+    "moji": "🚩"
+  },
+  "triangular_ruler": {
+    "unicode": "1F4D0",
+    "unicode_alternates": [],
+    "name": "triangular ruler",
+    "shortname": ":triangular_ruler:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["architect", "math", "sketch", "stationery"],
+    "moji": "📐"
+  },
+  "trident": {
+    "unicode": "1F531",
+    "unicode_alternates": [],
+    "name": "trident emblem",
+    "shortname": ":trident:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["spear", "weapon"],
+    "moji": "🔱"
+  },
+  "triumph": {
+    "unicode": "1F624",
+    "unicode_alternates": [],
+    "name": "face with look of triumph",
+    "shortname": ":triumph:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "gas", "phew", "triumph", "steam", "breath"],
+    "moji": "😤"
+  },
+  "trolleybus": {
+    "unicode": "1F68E",
+    "unicode_alternates": [],
+    "name": "trolleybus",
+    "shortname": ":trolleybus:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bart", "transportation", "vehicle", "trolley", "bus", "city", "transport", "transportation"],
+    "moji": "🚎"
+  },
+  "trophy": {
+    "unicode": "1F3C6",
+    "unicode_alternates": [],
+    "name": "trophy",
+    "shortname": ":trophy:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["award", "ceremony", "contest", "ftw", "place", "win", "trophy", "first", "show", "place", "win", "reward", "achievement", "medal"],
+    "moji": "🏆"
+  },
+  "tropical_drink": {
+    "unicode": "1F379",
+    "unicode_alternates": [],
+    "name": "tropical drink",
+    "shortname": ":tropical_drink:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["beverage", "tropical", "drink", "mixed", "pineapple", "coconut", "pina", "fruit", "umbrella"],
+    "moji": "🍹"
+  },
+  "tropical_fish": {
+    "unicode": "1F420",
+    "unicode_alternates": [],
+    "name": "tropical fish",
+    "shortname": ":tropical_fish:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "swim"],
+    "moji": "🐠"
+  },
+  "truck": {
+    "unicode": "1F69A",
+    "unicode_alternates": [],
+    "name": "delivery truck",
+    "shortname": ":truck:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["cars", "transportation", "truck", "delivery", "package"],
+    "moji": "🚚"
+  },
+  "trumpet": {
+    "unicode": "1F3BA",
+    "unicode_alternates": [],
+    "name": "trumpet",
+    "shortname": ":trumpet:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["brass", "music", "trumpet", "brass", "music", "instrument"],
+    "moji": "🎺"
+  },
+  "tulip": {
+    "unicode": "1F337",
+    "unicode_alternates": [],
+    "name": "tulip",
+    "shortname": ":tulip:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["flowers", "nature", "plant", "tulip", "flower", "bulb", "spring", "easter"],
+    "moji": "🌷"
+  },
+  "turned_ok_hand": {
+    "unicode": "1F58F",
+    "unicode_alternates": [],
+    "name": "turned ok hand sign",
+    "shortname": ":turned_ok_hand:",
+    "category": "people",
+    "aliases": [":turned_ok_hand_sign:"],
+    "aliases_ascii": [],
+    "keywords": ["perfect", "okay"]
+  },
+  "turtle": {
+    "unicode": "1F422",
+    "unicode_alternates": [],
+    "name": "turtle",
+    "shortname": ":turtle:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "slow", "turtle", "shell", "tortoise", "chelonian", "reptile", "slow", "snap", "steady"],
+    "moji": "🐢"
+  },
+  "twisted_rightwards_arrows": {
+    "unicode": "1F500",
+    "unicode_alternates": [],
+    "name": "twisted rightwards arrows",
+    "shortname": ":twisted_rightwards_arrows:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "🔀"
+  },
+  "two": {
+    "moji": "2️⃣",
+    "unicode": "0032-20E3",
+    "unicode_alternates": ["0032-FE0F-20E3"],
+    "name": "digit two",
+    "shortname": ":two:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["2", "blue-square", "numbers", "prime"]
+  },
+  "two_hearts": {
+    "unicode": "1F495",
+    "unicode_alternates": [],
+    "name": "two hearts",
+    "shortname": ":two_hearts:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines", "heart", "hearts", "two", "love", "emotion"],
+    "moji": "💕"
+  },
+  "two_men_holding_hands": {
+    "unicode": "1F46C",
+    "unicode_alternates": [],
+    "name": "two men holding hands",
+    "shortname": ":two_men_holding_hands:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bromance", "couple", "friends", "like", "love", "men", "gay", "homosexual", "friends", "hands", "holding", "team", "unity"],
+    "moji": "👬"
+  },
+  "two_women_holding_hands": {
+    "unicode": "1F46D",
+    "unicode_alternates": [],
+    "name": "two women holding hands",
+    "shortname": ":two_women_holding_hands:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["couple", "female", "friends", "like", "love", "women", "hands", "girlfriends", "friends", "sisters", "mother", "daughter", "gay", "homosexual", "couple", "unity"],
+    "moji": "👭"
+  },
+  "u5272": {
+    "unicode": "1F239",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-5272",
+    "shortname": ":u5272:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "cut", "divide", "kanji", "pink"],
+    "moji": "🈹"
+  },
+  "u5408": {
+    "unicode": "1F234",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-5408",
+    "shortname": ":u5408:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "japanese", "join", "kanji"],
+    "moji": "🈴"
+  },
+  "u55b6": {
+    "unicode": "1F23A",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-55b6",
+    "shortname": ":u55b6:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["japanese", "opening hours"],
+    "moji": "🈺"
+  },
+  "u6307": {
+    "unicode": "1F22F",
+    "unicode_alternates": ["1F22F-FE0F"],
+    "name": "squared cjk unified ideograph-6307",
+    "shortname": ":u6307:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "green-square", "kanji", "point"],
+    "moji": "🈯"
+  },
+  "u6708": {
+    "unicode": "1F237",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-6708",
+    "shortname": ":u6708:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "japanese", "kanji", "moon", "orange-square"],
+    "moji": "🈷"
+  },
+  "u6709": {
+    "unicode": "1F236",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-6709",
+    "shortname": ":u6709:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "have", "kanji", "orange-square"],
+    "moji": "🈶"
+  },
+  "u6e80": {
+    "unicode": "1F235",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-6e80",
+    "shortname": ":u6e80:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "full", "japanese", "kanji", "red-square"],
+    "moji": "🈵"
+  },
+  "u7121": {
+    "unicode": "1F21A",
+    "unicode_alternates": ["1F21A-FE0F"],
+    "name": "squared cjk unified ideograph-7121",
+    "shortname": ":u7121:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "japanese", "kanji", "no", "nothing", "orange-square"],
+    "moji": "🈚"
+  },
+  "u7533": {
+    "unicode": "1F238",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-7533",
+    "shortname": ":u7533:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "japanese", "kanji"],
+    "moji": "🈸"
+  },
+  "u7981": {
+    "unicode": "1F232",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-7981",
+    "shortname": ":u7981:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "forbidden", "japanese", "kanji", "limit", "restricted"],
+    "moji": "🈲"
+  },
+  "u7a7a": {
+    "unicode": "1F233",
+    "unicode_alternates": [],
+    "name": "squared cjk unified ideograph-7a7a",
+    "shortname": ":u7a7a:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["chinese", "empty", "japanese", "kanji"],
+    "moji": "🈳"
+  },
+  "umbrella": {
+    "unicode": "2614",
+    "unicode_alternates": ["2614-FE0F"],
+    "name": "umbrella with rain drops",
+    "shortname": ":umbrella:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["rain", "weather"],
+    "moji": "☔"
+  },
+  "unamused": {
+    "unicode": "1F612",
+    "unicode_alternates": [],
+    "name": "unamused face",
+    "shortname": ":unamused:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["bored", "face", "indifference", "serious", "straight face", "unamused", "not amused", "depressed", "unhappy", "disapprove", "lame"],
+    "moji": "😒"
+  },
+  "underage": {
+    "unicode": "1F51E",
+    "unicode_alternates": [],
+    "name": "no one under eighteen symbol",
+    "shortname": ":underage:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["18", "drink", "night", "pub"],
+    "moji": "🔞"
+  },
+  "unlock": {
+    "unicode": "1F513",
+    "unicode_alternates": [],
+    "name": "open lock",
+    "shortname": ":unlock:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["privacy", "security"],
+    "moji": "🔓"
+  },
+  "up": {
+    "unicode": "1F199",
+    "unicode_alternates": [],
+    "name": "squared up with exclamation mark",
+    "shortname": ":up:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square"],
+    "moji": "🆙"
+  },
+  "v": {
+    "unicode": "270C",
+    "unicode_alternates": ["270C-FE0F"],
+    "name": "victory hand",
+    "shortname": ":v:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fingers", "hand", "ohyeah", "peace", "two", "victory"],
+    "moji": "✌"
+  },
+  "vertical_traffic_light": {
+    "unicode": "1F6A6",
+    "unicode_alternates": [],
+    "name": "vertical traffic light",
+    "shortname": ":vertical_traffic_light:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["transportation", "traffic", "light", "stop", "go", "yield", "vertical"],
+    "moji": "🚦"
+  },
+  "vhs": {
+    "unicode": "1F4FC",
+    "unicode_alternates": [],
+    "name": "videocassette",
+    "shortname": ":vhs:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["oldschool", "record", "video"],
+    "moji": "📼"
+  },
+  "vibration_mode": {
+    "unicode": "1F4F3",
+    "unicode_alternates": [],
+    "name": "vibration mode",
+    "shortname": ":vibration_mode:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["orange-square", "phone"],
+    "moji": "📳"
+  },
+  "video_camera": {
+    "unicode": "1F4F9",
+    "unicode_alternates": [],
+    "name": "video camera",
+    "shortname": ":video_camera:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["film", "record"],
+    "moji": "📹"
+  },
+  "video_game": {
+    "unicode": "1F3AE",
+    "unicode_alternates": [],
+    "name": "video game",
+    "shortname": ":video_game:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["PS4", "console", "controller", "play", "video", "game", "console", "controller", "nintendo", "xbox", "playstation"],
+    "moji": "🎮"
+  },
+  "violin": {
+    "unicode": "1F3BB",
+    "unicode_alternates": [],
+    "name": "violin",
+    "shortname": ":violin:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["instrument", "music", "violin", "fiddle", "music", "instrument"],
+    "moji": "🎻"
+  },
+  "virgo": {
+    "unicode": "264D",
+    "unicode_alternates": ["264D-FE0F"],
+    "name": "virgo",
+    "shortname": ":virgo:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sign", "virgo", "maiden", "astrology", "greek", "constellation", "stars", "zodiac", "sign", "zodiac", "horoscope"],
+    "moji": "♍"
+  },
+  "volcano": {
+    "unicode": "1F30B",
+    "unicode_alternates": [],
+    "name": "volcano",
+    "shortname": ":volcano:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "photo", "volcano", "lava", "magma", "hot", "explode"],
+    "moji": "🌋"
+  },
+  "vs": {
+    "unicode": "1F19A",
+    "unicode_alternates": [],
+    "name": "squared vs",
+    "shortname": ":vs:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["orange-square", "words"],
+    "moji": "🆚"
+  },
+  "vulcan": {
+    "unicode": "1F596",
+    "unicode_alternates": [],
+    "name": "raised hand with part between middle and ring fingers",
+    "shortname": ":vulcan:",
+    "category": "people",
+    "aliases": [":raised_hand_with_part_between_middle_and_ring_fingers:"],
+    "aliases_ascii": [],
+    "keywords": ["vulcan", "spock", "leonard", "nimoy", "star trek", "live long"]
+  },
+  "walking": {
+    "unicode": "1F6B6",
+    "unicode_alternates": [],
+    "name": "pedestrian",
+    "shortname": ":walking:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["human", "man", "walk", "pedestrian", "stroll", "stride", "foot", "feet"],
+    "moji": "🚶"
+  },
+  "waning_crescent_moon": {
+    "unicode": "1F318",
+    "unicode_alternates": [],
+    "name": "waning crescent moon symbol",
+    "shortname": ":waning_crescent_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "crescent", "waning", "sky", "night", "cheese", "phase"],
+    "moji": "🌘"
+  },
+  "waning_gibbous_moon": {
+    "unicode": "1F316",
+    "unicode_alternates": [],
+    "name": "waning gibbous moon symbol",
+    "shortname": ":waning_gibbous_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "waning", "gibbous", "sky", "night", "cheese", "phase"],
+    "moji": "🌖"
+  },
+  "warning": {
+    "unicode": "26A0",
+    "unicode_alternates": ["26A0-FE0F"],
+    "name": "warning sign",
+    "shortname": ":warning:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["exclamation", "wip"],
+    "moji": "âš "
+  },
+  "wastebasket": {
+    "unicode": "1F5D1",
+    "unicode_alternates": [],
+    "name": "wastebasket",
+    "shortname": ":wastebasket:",
+    "category": "objects_symbols",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["trash", "garbage", "dispose"]
+  },
+  "watch": {
+    "unicode": "231A",
+    "unicode_alternates": ["231A-FE0F"],
+    "name": "watch",
+    "shortname": ":watch:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["accessories", "time"],
+    "moji": "⌚"
+  },
+  "water_buffalo": {
+    "unicode": "1F403",
+    "unicode_alternates": [],
+    "name": "water buffalo",
+    "shortname": ":water_buffalo:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "cow", "nature", "ox", "water", "buffalo", "asia", "bovine", "milk", "dairy"],
+    "moji": "🐃"
+  },
+  "watermelon": {
+    "unicode": "1F349",
+    "unicode_alternates": [],
+    "name": "watermelon",
+    "shortname": ":watermelon:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["food", "fruit", "melon", "watermelon", "summer", "fruit", "large"],
+    "moji": "🍉"
+  },
+  "wave": {
+    "unicode": "1F44B",
+    "unicode_alternates": [],
+    "name": "waving hand sign",
+    "shortname": ":wave:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["farewell", "gesture", "goodbye", "hands", "solong"],
+    "moji": "👋"
+  },
+  "wavy_dash": {
+    "unicode": "3030",
+    "unicode_alternates": [],
+    "name": "wavy dash",
+    "shortname": ":wavy_dash:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["draw", "line"],
+    "moji": "〰"
+  },
+  "waxing_crescent_moon": {
+    "unicode": "1F312",
+    "unicode_alternates": [],
+    "name": "waxing crescent moon symbol",
+    "shortname": ":waxing_crescent_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature", "moon", "waxing", "sky", "night", "cheese", "phase"],
+    "moji": "🌒"
+  },
+  "waxing_gibbous_moon": {
+    "unicode": "1F314",
+    "unicode_alternates": [],
+    "name": "waxing gibbous moon symbol",
+    "shortname": ":waxing_gibbous_moon:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["nature"],
+    "moji": "🌔"
+  },
+  "wc": {
+    "unicode": "1F6BE",
+    "unicode_alternates": [],
+    "name": "water closet",
+    "shortname": ":wc:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "restroom", "toilet", "water", "closet", "toilet", "bathroom", "throne", "porcelain", "waste", "flush", "plumbing"],
+    "moji": "🚾"
+  },
+  "weary": {
+    "unicode": "1F629",
+    "unicode_alternates": [],
+    "name": "weary face",
+    "shortname": ":weary:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "frustrated", "sad", "sleepy", "tired", "weary", "sleepy", "tired", "tiredness", "study", "finals", "school", "exhausted"],
+    "moji": "😩"
+  },
+  "wedding": {
+    "unicode": "1F492",
+    "unicode_alternates": [],
+    "name": "wedding",
+    "shortname": ":wedding:",
+    "category": "places",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "bride", "couple", "groom", "like", "love", "marriage"],
+    "moji": "💒"
+  },
+  "whale": {
+    "unicode": "1F433",
+    "unicode_alternates": [],
+    "name": "spouting whale",
+    "shortname": ":whale:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "ocean", "sea"],
+    "moji": "🐳"
+  },
+  "whale2": {
+    "unicode": "1F40B",
+    "unicode_alternates": [],
+    "name": "whale",
+    "shortname": ":whale2:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature", "ocean", "sea", "whale", "blubber", "bloated", "fat", "large", "massive"],
+    "moji": "🐋"
+  },
+  "wheelchair": {
+    "unicode": "267F",
+    "unicode_alternates": ["267F-FE0F"],
+    "name": "wheelchair symbol",
+    "shortname": ":wheelchair:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "disabled"],
+    "moji": "♿"
+  },
+  "white_check_mark": {
+    "unicode": "2705",
+    "unicode_alternates": [],
+    "name": "white heavy check mark",
+    "shortname": ":white_check_mark:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["agree", "green-square", "ok"],
+    "moji": "✅"
+  },
+  "white_circle": {
+    "unicode": "26AA",
+    "unicode_alternates": ["26AA-FE0F"],
+    "name": "medium white circle",
+    "shortname": ":white_circle:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "⚪"
+  },
+  "white_flower": {
+    "unicode": "1F4AE",
+    "unicode_alternates": [],
+    "name": "white flower",
+    "shortname": ":white_flower:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["japanese", "white", "flower", "teacher", "school", "grade", "score", "brilliance", "intelligence", "homework", "student", "assignment", "praise"],
+    "moji": "💮"
+  },
+  "white_large_square": {
+    "unicode": "2B1C",
+    "unicode_alternates": ["2B1C-FE0F"],
+    "name": "white large square",
+    "shortname": ":white_large_square:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "⬜"
+  },
+  "white_medium_small_square": {
+    "unicode": "25FD",
+    "unicode_alternates": ["25FD-FE0F"],
+    "name": "white medium small square",
+    "shortname": ":white_medium_small_square:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "â—½"
+  },
+  "white_medium_square": {
+    "unicode": "25FB",
+    "unicode_alternates": ["25FB-FE0F"],
+    "name": "white medium square",
+    "shortname": ":white_medium_square:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "â—»"
+  },
+  "white_small_square": {
+    "unicode": "25AB",
+    "unicode_alternates": ["25AB-FE0F"],
+    "name": "white small square",
+    "shortname": ":white_small_square:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "â–«"
+  },
+  "white_square_button": {
+    "unicode": "1F533",
+    "unicode_alternates": [],
+    "name": "white square button",
+    "shortname": ":white_square_button:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["shape"],
+    "moji": "🔳"
+  },
+  "wind_blowing_face": {
+    "unicode": "1F32C",
+    "unicode_alternates": [],
+    "name": "wind blowing face",
+    "shortname": ":wind_blowing_face:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["mother", "nature"]
+  },
+  "wind_chime": {
+    "unicode": "1F390",
+    "unicode_alternates": [],
+    "name": "wind chime",
+    "shortname": ":wind_chime:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["ding", "nature", "wind", "chime", "bell", "fūrin", "instrument", "music", "spirits", "soothing", "protective", "spiritual", "sound"],
+    "moji": "🎐"
+  },
+  "wine_glass": {
+    "unicode": "1F377",
+    "unicode_alternates": [],
+    "name": "wine glass",
+    "shortname": ":wine_glass:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["alcohol", "beverage", "booze", "bottle", "drink", "drunk", "fermented", "glass", "grapes", "tasting", "wine", "winery"],
+    "moji": "🍷"
+  },
+  "wink": {
+    "unicode": "1F609",
+    "unicode_alternates": [],
+    "name": "winking face",
+    "shortname": ":wink:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [";)", ";-)", "*-)", "*)", ";-]", ";]", ";D", ";^)"],
+    "keywords": ["face", "happy", "mischievous", "secret", "wink", "winking", "friendly", "joke"],
+    "moji": "😉"
+  },
+  "wolf": {
+    "unicode": "1F43A",
+    "unicode_alternates": [],
+    "name": "wolf face",
+    "shortname": ":wolf:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["animal", "nature"],
+    "moji": "🐺"
+  },
+  "woman": {
+    "unicode": "1F469",
+    "unicode_alternates": [],
+    "name": "woman",
+    "shortname": ":woman:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["female", "girls"],
+    "moji": "👩"
+  },
+  "womans_clothes": {
+    "unicode": "1F45A",
+    "unicode_alternates": [],
+    "name": "womans clothes",
+    "shortname": ":womans_clothes:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["fashion", "woman", "clothing", "clothes", "blouse", "shirt", "wardrobe", "breasts", "cleavage", "shopping", "shop", "dressing", "dressed"],
+    "moji": "👚"
+  },
+  "womans_hat": {
+    "unicode": "1F452",
+    "unicode_alternates": [],
+    "name": "womans hat",
+    "shortname": ":womans_hat:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["accessories", "fashion", "female"],
+    "moji": "👒"
+  },
+  "womens": {
+    "unicode": "1F6BA",
+    "unicode_alternates": [],
+    "name": "womens symbol",
+    "shortname": ":womens:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["purple-square", "woman", "bathroom", "restroom", "sign", "girl", "female", "avatar"],
+    "moji": "🚺"
+  },
+  "worried": {
+    "unicode": "1F61F",
+    "unicode_alternates": [],
+    "name": "worried face",
+    "shortname": ":worried:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["concern", "face", "nervous", "worried", "anxious", "distressed", "nervous", "tense"],
+    "moji": "😟"
+  },
+  "wrench": {
+    "unicode": "1F527",
+    "unicode_alternates": [],
+    "name": "wrench",
+    "shortname": ":wrench:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["diy", "ikea", "tools"],
+    "moji": "🔧"
+  },
+  "writing_hand": {
+    "unicode": "1F58E",
+    "unicode_alternates": [],
+    "name": "left writing hand",
+    "shortname": ":writing_hand:",
+    "category": "people",
+    "aliases": [":left_writing_hand:"],
+    "aliases_ascii": [],
+    "keywords": ["write", "sign", "signature", "draw"]
+  },
+  "x": {
+    "unicode": "274C",
+    "unicode_alternates": [],
+    "name": "cross mark",
+    "shortname": ":x:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["delete", "no", "remove"],
+    "moji": "❌"
+  },
+  "yellow_heart": {
+    "unicode": "1F49B",
+    "unicode_alternates": [],
+    "name": "yellow heart",
+    "shortname": ":yellow_heart:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["affection", "like", "love", "valentines", "yellow", "gold", "heart", "love", "friendship", "happy", "happiness", "trust", "compassionate", "respectful", "honest", "caring", "selfless"],
+    "moji": "💛"
+  },
+  "yen": {
+    "unicode": "1F4B4",
+    "unicode_alternates": [],
+    "name": "banknote with yen sign",
+    "shortname": ":yen:",
+    "category": "objects",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["currency", "dollar", "japanese", "money", "yen", "japan", "japanese", "banknote", "money", "currency", "paper", "cash", "bill"],
+    "moji": "💴"
+  },
+  "yum": {
+    "unicode": "1F60B",
+    "unicode_alternates": [],
+    "name": "face savouring delicious food",
+    "shortname": ":yum:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["face", "happy", "joy", "smile", "tongue", "delicious", "savoring", "food", "eat", "yummy", "yum", "tasty", "savory"],
+    "moji": "😋"
+  },
+  "zap": {
+    "unicode": "26A1",
+    "unicode_alternates": ["26A1-FE0F"],
+    "name": "high voltage sign",
+    "shortname": ":zap:",
+    "category": "nature",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["lightning bolt", "thunder", "weather"],
+    "moji": "âš¡"
+  },
+  "zero": {
+    "moji": "0️⃣",
+    "unicode": "0030-20E3",
+    "unicode_alternates": ["0030-FE0F-20E3"],
+    "name": "digit zero",
+    "shortname": ":zero:",
+    "category": "other",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["blue-square", "null", "numbers"]
+  },
+  "zzz": {
+    "unicode": "1F4A4",
+    "unicode_alternates": [],
+    "name": "sleeping symbol",
+    "shortname": ":zzz:",
+    "category": "emoticons",
+    "aliases": [],
+    "aliases_ascii": [],
+    "keywords": ["sleepy", "tired"],
+    "moji": "💤"
+  }
+}
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index b1cd80bdf65a246e7f9e6ea543c94d9d675f8c2e..26e7c956e8f79f2bc23ba4650c9e64693d1e75b0 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -67,9 +67,10 @@ module API
       expose :shared_runners_enabled
       expose :creator_id
       expose :namespace
-      expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ | project, options | project.forked? }
+      expose :forked_from_project, using: Entities::ForkedFromProject, if: lambda{ |project, options| project.forked? }
       expose :avatar_url
       expose :star_count, :forks_count
+      expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? }
     end
 
     class ProjectMember < UserBasic
@@ -165,7 +166,6 @@ module API
 
     class MergeRequest < ProjectEntity
       expose :target_branch, :source_branch
-      # deprecated, always returns 0
       expose :upvotes,  :downvotes
       expose :author, :assignee, using: Entities::UserBasic
       expose :source_project_id, :target_project_id
diff --git a/lib/api/files.rb b/lib/api/files.rb
index a7a768f8895ded69e5bfeba3c9e38819af79e6d6..8ad2c1883c77e7b91ee86026f5217264585eb235 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -7,7 +7,7 @@ module API
       def commit_params(attrs)
         {
           file_path: attrs[:file_path],
-          current_branch: attrs[:branch_name],
+          source_branch: attrs[:branch_name],
           target_branch: attrs[:branch_name],
           commit_message: attrs[:commit_message],
           file_content: attrs[:content],
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index bdf4b77596e41f313d5ea0e41cb12d881f9b7fdb..a9e0960872a08cb1b455a448b8458364acd95e8d 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -25,7 +25,7 @@ module API
         @projects = current_user.authorized_projects
         @projects = filter_projects(@projects)
         @projects = paginate @projects
-        present @projects, with: Entities::Project
+        present @projects, with: Entities::ProjectWithAccess, user: current_user
       end
 
       # Get an owned projects list for authenticated user
@@ -36,6 +36,17 @@ module API
         @projects = current_user.owned_projects
         @projects = filter_projects(@projects)
         @projects = paginate @projects
+        present @projects, with: Entities::ProjectWithAccess, user: current_user
+      end
+
+      # Gets starred project for the authenticated user
+      #
+      # Example Request:
+      #   GET /projects/starred
+      get '/starred' do
+        @projects = current_user.starred_projects
+        @projects = filter_projects(@projects)
+        @projects = paginate @projects
         present @projects, with: Entities::Project
       end
 
@@ -48,7 +59,7 @@ module API
         @projects = Project.all
         @projects = filter_projects(@projects)
         @projects = paginate @projects
-        present @projects, with: Entities::Project
+        present @projects, with: Entities::ProjectWithAccess, user: current_user
       end
 
       # Get a single project
diff --git a/lib/api/users.rb b/lib/api/users.rb
index a98d668e02d0db0c36719212d83bae75fcbb7c5a..3400f0713ef11c010e93680f41dd3a6e2e8796fb 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -8,11 +8,17 @@ module API
       #
       # Example Request:
       #  GET /users
+      #  GET /users?search=Admin
+      #  GET /users?username=root
       get do
-        @users = User.all
-        @users = @users.active if params[:active].present?
-        @users = @users.search(params[:search]) if params[:search].present?
-        @users = paginate @users
+        if params[:username].present?
+          @users = User.where(username: params[:username])
+        else
+          @users = User.all
+          @users = @users.active if params[:active].present?
+          @users = @users.search(params[:search]) if params[:search].present?
+          @users = paginate @users
+        end
 
         if current_user.is_admin?
           present @users, with: Entities::UserFull
diff --git a/lib/award_emoji.rb b/lib/award_emoji.rb
index 4d99164bc3319e8fc1dc241627d8735da93d1115..783fcfb61ad0363326eac5abff1970e1de318814 100644
--- a/lib/award_emoji.rb
+++ b/lib/award_emoji.rb
@@ -1,47 +1,51 @@
 class AwardEmoji
-  EMOJI_LIST = [
-    "+1", "-1", "100", "blush", "heart", "smile", "rage",
-    "beers", "disappointed", "ok_hand",
-    "helicopter", "shit", "airplane", "alarm_clock",
-    "ambulance", "anguished", "two_hearts", "wink"
-  ]
-
-  ALIASES = {
-    pout: "rage",
-    satisfied: "laughing",
-    hankey: "shit",
-    poop: "shit",
-    collision: "boom",
-    thumbsup: "+1",
-    thumbsdown: "-1",
-    punch: "facepunch",
-    raised_hand: "hand",
-    running: "runner",
-    ng_woman: "no_good",
-    shoe: "mans_shoe",
-    tshirt: "shirt",
-    honeybee: "bee",
-    flipper: "dolphin",
-    paw_prints: "feet",
-    waxing_gibbous_moon: "moon",
-    telephone: "phone",
-    knife: "hocho",
-    envelope: "email",
-    pencil: "memo",
-    open_book: "book",
-    sailboat: "boat",
-    red_car: "car",
-    lantern: "izakaya_lantern",
-    uk: "gb",
-    heavy_exclamation_mark: "exclamation",
-    squirrel: "shipit"
+  CATEGORIES = {
+    other: "Other",
+    objects: "Objects",
+    places: "Places",
+    travel_places: "Travel",
+    emoticons: "Emoticons",
+    objects_symbols: "Symbols",
+    nature: "Nature",
+    celebration: "Celebration",
+    people: "People",
+    activity: "Activity",
+    flags: "Flags",
+    food_drink: "Food"
   }.with_indifferent_access
 
-  def self.path_to_emoji_image(name)
-    "emoji/#{Emoji.emoji_filename(name)}.png"
+  def self.normilize_emoji_name(name)
+    aliases[name] || name
   end
 
-  def self.normilize_emoji_name(name)
-    ALIASES[name] || name
+  def self.emoji_by_category
+    unless @emoji_by_category
+      @emoji_by_category = {}
+
+      emojis.each do |emoji_name, data|
+        data["name"] = emoji_name
+
+        @emoji_by_category[data["category"]] ||= []
+        @emoji_by_category[data["category"]] << data
+      end
+
+      @emoji_by_category = @emoji_by_category.sort.to_h
+    end
+
+    @emoji_by_category
+  end
+
+  def self.emojis
+    @emojis ||= begin
+      json_path = File.join(Rails.root, 'fixtures', 'emojis', 'index.json' )
+      JSON.parse(File.read(json_path))
+    end
+  end
+
+  def self.aliases
+    @aliases ||= begin
+      json_path = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json' )
+      JSON.parse(File.read(json_path))
+    end
   end
 end
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index bdaa4721b4bcdc863f07f1dab60f3bc4bd22f292..63ad8910c0ff31b774051f4e66a4ea145a041a21 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -98,7 +98,7 @@ module Banzai
           project = project_from_ref(project_ref)
 
           if project && object = find_object(project, id)
-            title = escape_once(object_link_title(object))
+            title = object_link_title(object)
             klass = reference_class(object_sym)
 
             data  = data_attribute(
@@ -110,17 +110,11 @@ module Banzai
             url = matches[:url] if matches.names.include?("url")
             url ||= url_for_object(object, project)
 
-            text = link_text
-            unless text
-              text = object.reference_link_text(context[:project])
-
-              extras = object_link_text_extras(object, matches)
-              text += " (#{extras.join(", ")})" if extras.any?
-            end
+            text = link_text || object_link_text(object, matches)
 
             %(<a href="#{url}" #{data}
-                 title="#{title}"
-                 class="#{klass}">#{text}</a>)
+                 title="#{escape_once(title)}"
+                 class="#{klass}">#{escape_once(text)}</a>)
           else
             match
           end
@@ -140,6 +134,15 @@ module Banzai
       def object_link_title(object)
         "#{object_class.name.titleize}: #{object.title}"
       end
+
+      def object_link_text(object, matches)
+        text = object.reference_link_text(context[:project])
+
+        extras = object_link_text_extras(object, matches)
+        text += " (#{extras.join(", ")})" if extras.any?
+
+        text
+      end
     end
   end
 end
diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb
index f5737a7ac193afb9d40d96e7838371adefd72154..6136e73c096ab7df26c281a903840b64695e0803 100644
--- a/lib/banzai/filter/external_issue_reference_filter.rb
+++ b/lib/banzai/filter/external_issue_reference_filter.rb
@@ -23,6 +23,18 @@ module Banzai
         end
       end
 
+      def self.referenced_by(node)
+        project = Project.find(node.attr("data-project")) rescue nil
+        return unless project
+
+        id = node.attr("data-external-issue")
+        external_issue = ExternalIssue.new(id, project)
+
+        return unless external_issue
+
+        { external_issue: external_issue }
+      end
+
       def call
         # Early return if the project isn't using an external tracker
         return doc if project.nil? || project.default_issues_tracker?
@@ -46,18 +58,20 @@ module Banzai
       def issue_link_filter(text, link_text: nil)
         project = context[:project]
 
-        self.class.references_in(text) do |match, issue|
-          url = url_for_issue(issue, project, only_path: context[:only_path])
+        self.class.references_in(text) do |match, id|
+          ExternalIssue.new(id, project)
+
+          url = url_for_issue(id, project, only_path: context[:only_path])
 
-          title = escape_once("Issue in #{project.external_issue_tracker.title}")
+          title = "Issue in #{project.external_issue_tracker.title}"
           klass = reference_class(:issue)
-          data  = data_attribute(project: project.id)
+          data  = data_attribute(project: project.id, external_issue: id)
 
           text = link_text || match
 
           %(<a href="#{url}" #{data}
-               title="#{title}"
-               class="#{klass}">#{text}</a>)
+               title="#{escape_once(title)}"
+               class="#{klass}">#{escape_once(text)}</a>)
         end
       end
 
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index 07bac2dd7fd4897fcee8ea09567f803ceff03c58..a3a7a23c1e6ae272f950dcb76154c837d830c3e0 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -60,7 +60,7 @@ module Banzai
             text = link_text || render_colored_label(label)
 
             %(<a href="#{url}" #{data}
-                 class="#{klass}">#{text}</a>)
+                 class="#{klass}">#{escape_once(text)}</a>)
           else
             match
           end
diff --git a/lib/banzai/filter/markdown_filter.rb b/lib/banzai/filter/markdown_filter.rb
index 0072bab1f99e2c3b06561a4823f64bcb94846f61..d09cf41df394d478a04f125da729b2f13e03f235 100644
--- a/lib/banzai/filter/markdown_filter.rb
+++ b/lib/banzai/filter/markdown_filter.rb
@@ -6,7 +6,7 @@ module Banzai
     class MarkdownFilter < HTML::Pipeline::TextFilter
       def initialize(text, context = nil, result = nil)
         super text, context, result
-        @text = @text.gsub "\r", ''
+        @text = @text.delete "\r"
       end
 
       def call
diff --git a/lib/banzai/filter/redactor_filter.rb b/lib/banzai/filter/redactor_filter.rb
index 89e7a79789a7990feecab47884a224c31427930a..f01a32b5ae5e6055f69183e5005f7b08b8062fc7 100644
--- a/lib/banzai/filter/redactor_filter.rb
+++ b/lib/banzai/filter/redactor_filter.rb
@@ -11,7 +11,7 @@ module Banzai
     class RedactorFilter < HTML::Pipeline::Filter
       def call
         doc.css('a.gfm').each do |node|
-          unless user_can_reference?(node)
+          unless user_can_see_reference?(node)
             # The reference should be replaced by the original text,
             # which is not always the same as the rendered text.
             text = node.attr('data-original') || node.text
@@ -24,12 +24,12 @@ module Banzai
 
       private
 
-      def user_can_reference?(node)
+      def user_can_see_reference?(node)
         if node.has_attribute?('data-reference-filter')
           reference_type = node.attr('data-reference-filter')
           reference_filter = Banzai::Filter.const_get(reference_type)
 
-          reference_filter.user_can_reference?(current_user, node, context)
+          reference_filter.user_can_see_reference?(current_user, node, context)
         else
           true
         end
diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb
index 33457a3f361837e6daa228047fa48080ab80d09e..8ca05ace88cc55ea168935ed7d245b8ba61a7b40 100644
--- a/lib/banzai/filter/reference_filter.rb
+++ b/lib/banzai/filter/reference_filter.rb
@@ -12,7 +12,7 @@ module Banzai
     #   :project (required) - Current project, ignored if reference is cross-project.
     #   :only_path          - Generate path-only links.
     class ReferenceFilter < HTML::Pipeline::Filter
-      def self.user_can_reference?(user, node, context)
+      def self.user_can_see_reference?(user, node, context)
         if node.has_attribute?('data-project')
           project_id = node.attr('data-project').to_i
           return true if project_id == context[:project].try(:id)
@@ -24,6 +24,10 @@ module Banzai
         end
       end
 
+      def self.user_can_reference?(user, node, context)
+        true
+      end
+
       def self.referenced_by(node)
         raise NotImplementedError, "#{self} does not implement #{__method__}"
       end
@@ -44,11 +48,11 @@ module Banzai
       # Returns a String
       def data_attribute(attributes = {})
         attributes[:reference_filter] = self.class.name.demodulize
-        attributes.map { |key, value| %Q(data-#{key.to_s.dasherize}="#{value}") }.join(" ")
+        attributes.map { |key, value| %Q(data-#{key.to_s.dasherize}="#{escape_once(value)}") }.join(" ")
       end
 
       def escape_once(html)
-        ERB::Util.html_escape_once(html)
+        html.html_safe? ? html : ERB::Util.html_escape_once(html)
       end
 
       def ignore_parents
diff --git a/lib/banzai/filter/reference_gatherer_filter.rb b/lib/banzai/filter/reference_gatherer_filter.rb
index 855f238ac1ebf4d79c7f8c396aab45911b730846..12412ff7ea9267bc32244758d76edef439724669 100644
--- a/lib/banzai/filter/reference_gatherer_filter.rb
+++ b/lib/banzai/filter/reference_gatherer_filter.rb
@@ -35,7 +35,9 @@ module Banzai
 
         return if context[:reference_filter] && reference_filter != context[:reference_filter]
 
-        return unless reference_filter.user_can_reference?(current_user, node, context)
+        return if author && !reference_filter.user_can_reference?(author, node, context)
+
+        return unless reference_filter.user_can_see_reference?(current_user, node, context)
 
         references = reference_filter.referenced_by(node)
         return unless references
@@ -57,6 +59,10 @@ module Banzai
       def current_user
         context[:current_user]
       end
+
+      def author
+        context[:author]
+      end
     end
   end
 end
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb
index 92d130074dcd4d93c8ac382c0e1366c9174562a0..9b3e67206d5539c49f00d993cb9bdfa9c3ba5cd2 100644
--- a/lib/banzai/filter/table_of_contents_filter.rb
+++ b/lib/banzai/filter/table_of_contents_filter.rb
@@ -31,7 +31,7 @@ module Banzai
 
           id = text.downcase
           id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation
-          id.gsub!(' ', '-') # replace spaces with dash
+          id.tr!(' ', '-') # replace spaces with dash
           id.squeeze!('-') # replace multiple dashes with one
 
           uniq = (headers[id] > 0) ? "-#{headers[id]}" : ''
diff --git a/lib/banzai/filter/user_reference_filter.rb b/lib/banzai/filter/user_reference_filter.rb
index 67c24faf991243f4aa167fbde94ff17a9ccbc129..964ab60f614b9f3a75ab1039e71a3cd2abf733f9 100644
--- a/lib/banzai/filter/user_reference_filter.rb
+++ b/lib/banzai/filter/user_reference_filter.rb
@@ -39,7 +39,7 @@ module Banzai
         end
       end
 
-      def self.user_can_reference?(user, node, context)
+      def self.user_can_see_reference?(user, node, context)
         if node.has_attribute?('data-group')
           group = Group.find(node.attr('data-group')) rescue nil
           Ability.abilities.allowed?(user, :read_group, group)
@@ -48,6 +48,18 @@ module Banzai
         end
       end
 
+      def self.user_can_reference?(user, node, context)
+        # Only team members can reference `@all`
+        if node.has_attribute?('data-project')
+          project = Project.find(node.attr('data-project')) rescue nil
+          return false unless project
+
+          user && project.team.member?(user)
+        else
+          super
+        end
+      end
+
       def call
         replace_text_nodes_matching(User.reference_pattern) do |content|
           user_link_filter(content)
@@ -122,7 +134,7 @@ module Banzai
       end
 
       def link_tag(url, data, text)
-        %(<a href="#{url}" #{data} class="#{link_class}">#{text}</a>)
+        %(<a href="#{url}" #{data} class="#{link_class}">#{escape_once(text)}</a>)
       end
     end
   end
diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb
index 891c0fd7749aac0f984d41ecfe572054596dcea9..115ae91452486b304779a1f1d342ab16124f99e2 100644
--- a/lib/banzai/renderer.rb
+++ b/lib/banzai/renderer.rb
@@ -1,5 +1,7 @@
 module Banzai
   module Renderer
+    CACHE_ENABLED = false
+
     # Convert a Markdown String into an HTML-safe String of HTML
     #
     # Note that while the returned HTML will have been sanitized of dangerous
@@ -18,7 +20,7 @@ module Banzai
       cache_key = context.delete(:cache_key)
       cache_key = full_cache_key(cache_key, context[:pipeline])
 
-      if cache_key
+      if cache_key && CACHE_ENABLED
         Rails.cache.fetch(cache_key) do
           cacheless_render(text, context)
         end
diff --git a/lib/ci/api/helpers.rb b/lib/ci/api/helpers.rb
index 443563c2e4a4c8b1cb48af76ff093c891ad25fd0..1c91204e98ca1c9331f0c597d4e8bb5933b3c7cd 100644
--- a/lib/ci/api/helpers.rb
+++ b/lib/ci/api/helpers.rb
@@ -19,7 +19,7 @@ module Ci
       end
 
       def runner_registration_token_valid?
-        params[:token] == current_application_settings.ensure_runners_registration_token
+        params[:token] == current_application_settings.runners_registration_token
       end
 
       def update_runner_last_contact
diff --git a/lib/gitlab/backend/shell.rb b/lib/gitlab/backend/shell.rb
index 87ac30b5ffef959e7baa2a60f8e28d41310099ed..459e3d6bcdbf1e6c6235ae5a59d4128dce3011a1 100644
--- a/lib/gitlab/backend/shell.rb
+++ b/lib/gitlab/backend/shell.rb
@@ -2,7 +2,7 @@ module Gitlab
   class Shell
     class Error < StandardError; end
 
-    class KeyAdder < Struct.new(:io)
+    KeyAdder = Struct.new(:io) do
       def add_key(id, key)
         key.gsub!(/[[:space:]]+/, ' ').strip!
         io.puts("#{id}\t#{key}")
diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb
index 35e34d033e0ccc8a31b501f8412b5a58b0231917..03aac1a025a8d14b244a62b15cec763e56d16fb6 100644
--- a/lib/gitlab/bitbucket_import/project_creator.rb
+++ b/lib/gitlab/bitbucket_import/project_creator.rb
@@ -11,7 +11,8 @@ module Gitlab
       end
 
       def execute
-        project = ::Projects::CreateService.new(current_user,
+        project = ::Projects::CreateService.new(
+          current_user,
           name: repo["name"],
           path: repo["slug"],
           description: repo["description"],
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 46a4ef0e31febfd300cbc35bc5abb88291e59f27..7a86c09158ed4fa8712945284344225dea21ec08 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -38,7 +38,9 @@ module Gitlab
                  true
                end
 
-      use_db && ActiveRecord::Base.connection.active? && ActiveRecord::Base.connection.table_exists?('application_settings')
+      use_db && ActiveRecord::Base.connection.active? &&
+                !ActiveRecord::Migrator.needs_migration? &&
+                ActiveRecord::Base.connection.table_exists?('application_settings')
     end
   end
 end
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 142058aa69d46e0b1429c5e0b0b8f18ae09cfb16..79061cd014181d0375b622431ae41c5379f493c6 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -46,11 +46,11 @@ module Gitlab
       end
 
       def added_lines
-        diff_lines.select(&:added?).size
+        diff_lines.count(&:added?)
       end
 
       def removed_lines
-        diff_lines.select(&:removed?).size
+        diff_lines.count(&:removed?)
       end
     end
   end
diff --git a/lib/gitlab/fogbugz_import/importer.rb b/lib/gitlab/fogbugz_import/importer.rb
index 496256700b87e6059ef37a943f8f8e595f553b79..403ebeec47417d678a0a617fa6697ec89ba0953a 100644
--- a/lib/gitlab/fogbugz_import/importer.rb
+++ b/lib/gitlab/fogbugz_import/importer.rb
@@ -199,7 +199,7 @@ module Gitlab
         s = s.gsub(/^#/, "\\#")
         s = s.gsub(/^-/, "\\-")
         s = s.gsub("`", "\\~")
-        s = s.gsub("\r", "")
+        s = s.delete("\r")
         s = s.gsub("\n", "  \n")
         s
       end
diff --git a/lib/gitlab/fogbugz_import/project_creator.rb b/lib/gitlab/fogbugz_import/project_creator.rb
index 8b1b6f48ed500573377c4e91ed59405f12b28c0a..e0163499e3094066b386167d9527eaa60f6158fa 100644
--- a/lib/gitlab/fogbugz_import/project_creator.rb
+++ b/lib/gitlab/fogbugz_import/project_creator.rb
@@ -12,7 +12,8 @@ module Gitlab
       end
 
       def execute
-        project = ::Projects::CreateService.new(current_user,
+        project = ::Projects::CreateService.new(
+          current_user,
           name: repo.safe_name,
           path: repo.path,
           namespace: namespace,
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index 0c350d7c675e1977077944a7c1eff2f5a355c93b..f065cc5e9e9962c70407370403881452dab5c795 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -20,6 +20,10 @@ module Gitlab
       def blank_ref?(ref)
         ref == BLANK_SHA
       end
+
+      def version
+        Gitlab::VersionInfo.parse(Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --version)).first)
+      end
     end
   end
 end
diff --git a/lib/gitlab/gitlab_import/project_creator.rb b/lib/gitlab/gitlab_import/project_creator.rb
index d9452de6a5093b99990a79f44fb29ce1986d6098..7baaadb813c60ab555f2f4c993bc6c5b5f24c2dc 100644
--- a/lib/gitlab/gitlab_import/project_creator.rb
+++ b/lib/gitlab/gitlab_import/project_creator.rb
@@ -11,7 +11,8 @@ module Gitlab
       end
 
       def execute
-        project = ::Projects::CreateService.new(current_user,
+        project = ::Projects::CreateService.new(
+          current_user,
           name: repo["name"],
           path: repo["path"],
           description: repo["description"],
diff --git a/lib/gitlab/gitorious_import/project_creator.rb b/lib/gitlab/gitorious_import/project_creator.rb
index cc9a91c91f4538faa2158d8b11234874863b128e..8e22aa9286ddf4d2a332f2daca87a6ab5f2eee9d 100644
--- a/lib/gitlab/gitorious_import/project_creator.rb
+++ b/lib/gitlab/gitorious_import/project_creator.rb
@@ -10,7 +10,8 @@ module Gitlab
       end
 
       def execute
-        ::Projects::CreateService.new(current_user,
+        ::Projects::CreateService.new(
+          current_user,
           name: repo.name,
           path: repo.path,
           description: repo.description,
diff --git a/lib/gitlab/google_code_import/importer.rb b/lib/gitlab/google_code_import/importer.rb
index 87fee28dc010adfcae54c903c427a67d8634b54a..62da327931faff96264b4152325c321bc7f16281 100644
--- a/lib/gitlab/google_code_import/importer.rb
+++ b/lib/gitlab/google_code_import/importer.rb
@@ -171,8 +171,6 @@ module Gitlab
         when /\AMilestone:/
           "#fee3ff"
 
-        when *@closed_statuses.map { |s| nice_status_name(s) }
-          "#cfcfcf"
         when "Status: New"
           "#428bca"
         when "Status: Accepted"
@@ -199,6 +197,8 @@ module Gitlab
           "#8e44ad"
         when "Type: Other"
           "#7f8c8d"
+        when *@closed_statuses.map { |s| nice_status_name(s) }
+          "#cfcfcf"
         else
           "#e2e2e2"
         end
@@ -227,7 +227,7 @@ module Gitlab
         s = s.gsub("`", "\\`")
 
         # Carriage returns make me sad
-        s = s.gsub("\r", "")
+        s = s.delete("\r")
 
         # Markdown ignores single newlines, but we need them as <br />.
         s = s.gsub("\n", "  \n")
diff --git a/lib/gitlab/google_code_import/project_creator.rb b/lib/gitlab/google_code_import/project_creator.rb
index 1cb7d16aeb3f0021ea7528f29b5be797e3b2caa1..87821c2346094f94869b8144a2a6412c739618af 100644
--- a/lib/gitlab/google_code_import/project_creator.rb
+++ b/lib/gitlab/google_code_import/project_creator.rb
@@ -11,7 +11,8 @@ module Gitlab
       end
 
       def execute
-        project = ::Projects::CreateService.new(current_user,
+        project = ::Projects::CreateService.new(
+          current_user,
           name: repo.name,
           path: repo.name,
           description: repo.summary,
diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb
index 4be99dd88c29dd87ba829973da60aeca464dbf2d..aef08c97d1d7edf18a23b02f82a0eedcb5af40e1 100644
--- a/lib/gitlab/ldap/user.rb
+++ b/lib/gitlab/ldap/user.rb
@@ -14,7 +14,7 @@ module Gitlab
           # LDAP distinguished name is case-insensitive
           identity = ::Identity.
             where(provider: provider).
-            where('lower(extern_uid) = ?', uid.mb_chars.downcase.to_s).last
+            iwhere(extern_uid: uid).last
           identity && identity.user
         end
       end
@@ -31,7 +31,7 @@ module Gitlab
 
       def find_by_uid_and_provider
         self.class.find_by_uid_and_provider(
-          auth_hash.uid.downcase, auth_hash.provider)
+          auth_hash.uid, auth_hash.provider)
       end
 
       def find_by_email
@@ -47,7 +47,7 @@ module Gitlab
         # find_or_initialize_by doesn't update `gl_user.identities`, and isn't autosaved.
         identity = gl_user.identities.find { |identity|  identity.provider == auth_hash.provider }
         identity ||= gl_user.identities.build(provider: auth_hash.provider)
-        
+
         # For a new user set extern_uid to the LDAP DN
         # For an existing user with matching email but changed DN, update the DN.
         # For an existing user with no change in DN, this line changes nothing.
diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2d266ccfe9e64252996ff290ed1d42ab4c6a09c2
--- /dev/null
+++ b/lib/gitlab/metrics.rb
@@ -0,0 +1,104 @@
+module Gitlab
+  module Metrics
+    extend Gitlab::CurrentSettings
+
+    RAILS_ROOT   = Rails.root.to_s
+    METRICS_ROOT = Rails.root.join('lib', 'gitlab', 'metrics').to_s
+    PATH_REGEX   = /^#{RAILS_ROOT}\/?/
+
+    def self.pool_size
+      current_application_settings[:metrics_pool_size] || 16
+    end
+
+    def self.timeout
+      current_application_settings[:metrics_timeout] || 10
+    end
+
+    def self.enabled?
+      current_application_settings[:metrics_enabled] || false
+    end
+
+    def self.mri?
+      RUBY_ENGINE == 'ruby'
+    end
+
+    def self.method_call_threshold
+      # This is memoized since this method is called for every instrumented
+      # method. Loading data from an external cache on every method call slows
+      # things down too much.
+      @method_call_threshold ||=
+        (current_application_settings[:metrics_method_call_threshold] || 10)
+    end
+
+    def self.pool
+      @pool
+    end
+
+    def self.hostname
+      @hostname
+    end
+
+    # Returns a relative path and line number based on the last application call
+    # frame.
+    def self.last_relative_application_frame
+      frame = caller_locations.find do |l|
+        l.path.start_with?(RAILS_ROOT) && !l.path.start_with?(METRICS_ROOT)
+      end
+
+      if frame
+        return frame.path.sub(PATH_REGEX, ''), frame.lineno
+      else
+        return nil, nil
+      end
+    end
+
+    def self.submit_metrics(metrics)
+      prepared = prepare_metrics(metrics)
+
+      pool.with do |connection|
+        prepared.each do |metric|
+          begin
+            connection.write_points([metric])
+          rescue StandardError
+          end
+        end
+      end
+    end
+
+    def self.prepare_metrics(metrics)
+      metrics.map do |hash|
+        new_hash = hash.symbolize_keys
+
+        new_hash[:tags].each do |key, value|
+          if value.blank?
+            new_hash[:tags].delete(key)
+          else
+            new_hash[:tags][key] = escape_value(value)
+          end
+        end
+
+        new_hash
+      end
+    end
+
+    def self.escape_value(value)
+      value.to_s.gsub('=', '\\=')
+    end
+
+    @hostname = Socket.gethostname
+
+    # When enabled this should be set before being used as the usual pattern
+    # "@foo ||= bar" is _not_ thread-safe.
+    if enabled?
+      @pool = ConnectionPool.new(size: pool_size, timeout: timeout) do
+        host = current_application_settings[:metrics_host]
+        user = current_application_settings[:metrics_username]
+        pw   = current_application_settings[:metrics_password]
+        port = current_application_settings[:metrics_port]
+
+        InfluxDB::Client.
+          new(udp: { host: host, port: port }, username: user, password: pw)
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/delta.rb b/lib/gitlab/metrics/delta.rb
new file mode 100644
index 0000000000000000000000000000000000000000..bcf28eed84d897c7f08cfd6691cbc9c4c8fadb68
--- /dev/null
+++ b/lib/gitlab/metrics/delta.rb
@@ -0,0 +1,32 @@
+module Gitlab
+  module Metrics
+    # Class for calculating the difference between two numeric values.
+    #
+    # Every call to `compared_with` updates the internal value. This makes it
+    # possible to use a single Delta instance to calculate the delta over time
+    # of an ever increasing number.
+    #
+    # Example usage:
+    #
+    #     delta = Delta.new(0)
+    #
+    #     delta.compared_with(10) # => 10
+    #     delta.compared_with(15) # => 5
+    #     delta.compared_with(20) # => 5
+    class Delta
+      def initialize(value = 0)
+        @value = value
+      end
+
+      # new_value - The value to compare with as a Numeric.
+      #
+      # Returns a new Numeric (depending on the type of `new_value`).
+      def compared_with(new_value)
+        delta  = new_value - @value
+        @value = new_value
+
+        delta
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb
new file mode 100644
index 0000000000000000000000000000000000000000..06fc2f259483d713e8a6340496980f27b5dfbf23
--- /dev/null
+++ b/lib/gitlab/metrics/instrumentation.rb
@@ -0,0 +1,146 @@
+module Gitlab
+  module Metrics
+    # Module for instrumenting methods.
+    #
+    # This module allows instrumenting of methods without having to actually
+    # alter the target code (e.g. by including modules).
+    #
+    # Example usage:
+    #
+    #     Gitlab::Metrics::Instrumentation.instrument_method(User, :by_login)
+    module Instrumentation
+      SERIES = 'method_calls'
+
+      def self.configure
+        yield self
+      end
+
+      # Instruments a class method.
+      #
+      # mod  - The module to instrument as a Module/Class.
+      # name - The name of the method to instrument.
+      def self.instrument_method(mod, name)
+        instrument(:class, mod, name)
+      end
+
+      # Instruments an instance method.
+      #
+      # mod  - The module to instrument as a Module/Class.
+      # name - The name of the method to instrument.
+      def self.instrument_instance_method(mod, name)
+        instrument(:instance, mod, name)
+      end
+
+      # Recursively instruments all subclasses of the given root module.
+      #
+      # This can be used to for example instrument all ActiveRecord models (as
+      # these all inherit from ActiveRecord::Base).
+      #
+      # This method can optionally take a block to pass to `instrument_methods`
+      # and `instrument_instance_methods`.
+      #
+      # root - The root module for which to instrument subclasses. The root
+      #        module itself is not instrumented.
+      def self.instrument_class_hierarchy(root, &block)
+        visit = root.subclasses
+
+        until visit.empty?
+          klass = visit.pop
+
+          instrument_methods(klass, &block)
+          instrument_instance_methods(klass, &block)
+
+          klass.subclasses.each { |c| visit << c }
+        end
+      end
+
+      # Instruments all public methods of a module.
+      #
+      # This method optionally takes a block that can be used to determine if a
+      # method should be instrumented or not. The block is passed the receiving
+      # module and an UnboundMethod. If the block returns a non truthy value the
+      # method is not instrumented.
+      #
+      # mod - The module to instrument.
+      def self.instrument_methods(mod)
+        mod.public_methods(false).each do |name|
+          method = mod.method(name)
+
+          if method.owner == mod.singleton_class
+            if !block_given? || block_given? && yield(mod, method)
+              instrument_method(mod, name)
+            end
+          end
+        end
+      end
+
+      # Instruments all public instance methods of a module.
+      #
+      # See `instrument_methods` for more information.
+      #
+      # mod - The module to instrument.
+      def self.instrument_instance_methods(mod)
+        mod.public_instance_methods(false).each do |name|
+          method = mod.instance_method(name)
+
+          if method.owner == mod
+            if !block_given? || block_given? && yield(mod, method)
+              instrument_instance_method(mod, name)
+            end
+          end
+        end
+      end
+
+      # Instruments a method.
+      #
+      # type - The type (:class or :instance) of method to instrument.
+      # mod  - The module containing the method.
+      # name - The name of the method to instrument.
+      def self.instrument(type, mod, name)
+        return unless Metrics.enabled?
+
+        name       = name.to_sym
+        alias_name = :"_original_#{name}"
+        target     = type == :instance ? mod : mod.singleton_class
+
+        if type == :instance
+          target = mod
+          label  = "#{mod.name}##{name}"
+        else
+          target = mod.singleton_class
+          label  = "#{mod.name}.#{name}"
+        end
+
+        target.class_eval <<-EOF, __FILE__, __LINE__ + 1
+          alias_method #{alias_name.inspect}, #{name.inspect}
+
+          def #{name}(*args, &block)
+            trans = Gitlab::Metrics::Instrumentation.transaction
+
+            if trans
+              start    = Time.now
+              retval   = __send__(#{alias_name.inspect}, *args, &block)
+              duration = (Time.now - start) * 1000.0
+
+              if duration >= Gitlab::Metrics.method_call_threshold
+                trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES,
+                                 { duration: duration },
+                                 method: #{label.inspect})
+              end
+
+              retval
+            else
+              __send__(#{alias_name.inspect}, *args, &block)
+            end
+          end
+        EOF
+      end
+
+      # Small layer of indirection to make it easier to stub out the current
+      # transaction.
+      def self.transaction
+        Transaction.current
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/metric.rb b/lib/gitlab/metrics/metric.rb
new file mode 100644
index 0000000000000000000000000000000000000000..753008df99af03142b2b1954afc0ec24601e0731
--- /dev/null
+++ b/lib/gitlab/metrics/metric.rb
@@ -0,0 +1,31 @@
+module Gitlab
+  module Metrics
+    # Class for storing details of a single metric (label, value, etc).
+    class Metric
+      attr_reader :series, :values, :tags, :created_at
+
+      # series - The name of the series (as a String) to store the metric in.
+      # values - A Hash containing the values to store.
+      # tags   - A Hash containing extra tags to add to the metrics.
+      def initialize(series, values, tags = {})
+        @values     = values
+        @series     = series
+        @tags       = tags
+        @created_at = Time.now.utc
+      end
+
+      # Returns a Hash in a format that can be directly written to InfluxDB.
+      def to_hash
+        {
+          series: @series,
+          tags:   @tags.merge(
+            hostname:     Metrics.hostname,
+            process_type: Sidekiq.server? ? 'sidekiq' : 'rails'
+          ),
+          values:    @values,
+          timestamp: @created_at.to_i * 1_000_000_000
+        }
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/obfuscated_sql.rb b/lib/gitlab/metrics/obfuscated_sql.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fe97d7a0534e1e160d74051ec4ee30fe7631a3fc
--- /dev/null
+++ b/lib/gitlab/metrics/obfuscated_sql.rb
@@ -0,0 +1,47 @@
+module Gitlab
+  module Metrics
+    # Class for producing SQL queries with sensitive data stripped out.
+    class ObfuscatedSQL
+      REPLACEMENT = /
+        \d+(\.\d+)?      # integers, floats
+        | '.+?'          # single quoted strings
+        | \/.+?(?<!\\)\/ # regexps (including escaped slashes)
+      /x
+
+      MYSQL_REPLACEMENTS = /
+        ".+?" # double quoted strings
+      /x
+
+      # Regex to replace consecutive placeholders with a single one indicating
+      # the length. This can be useful when a "IN" statement uses thousands of
+      # IDs (storing this would just be a waste of space).
+      CONSECUTIVE = /(\?(\s*,\s*)?){2,}/
+
+      # sql - The raw SQL query as a String.
+      def initialize(sql)
+        @sql = sql
+      end
+
+      # Returns a new, obfuscated SQL query.
+      def to_s
+        regex = REPLACEMENT
+
+        if Gitlab::Database.mysql?
+          regex = Regexp.union(regex, MYSQL_REPLACEMENTS)
+        end
+
+        sql = @sql.gsub(regex, '?').gsub(CONSECUTIVE) do |match|
+          "#{match.count(',') + 1} values"
+        end
+
+        # InfluxDB escapes double quotes upon output, so lets get rid of them
+        # whenever we can.
+        if Gitlab::Database.postgresql?
+          sql = sql.delete('"')
+        end
+
+        sql.tr("\n", ' ')
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/rack_middleware.rb b/lib/gitlab/metrics/rack_middleware.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5c0587c4c51396d331a67681650b60b50dfa5df4
--- /dev/null
+++ b/lib/gitlab/metrics/rack_middleware.rb
@@ -0,0 +1,49 @@
+module Gitlab
+  module Metrics
+    # Rack middleware for tracking Rails requests.
+    class RackMiddleware
+      CONTROLLER_KEY = 'action_controller.instance'
+
+      def initialize(app)
+        @app = app
+      end
+
+      # env - A Hash containing Rack environment details.
+      def call(env)
+        trans  = transaction_from_env(env)
+        retval = nil
+
+        begin
+          retval = trans.run { @app.call(env) }
+
+        # Even in the event of an error we want to submit any metrics we
+        # might've gathered up to this point.
+        ensure
+          if env[CONTROLLER_KEY]
+            tag_controller(trans, env)
+          end
+
+          trans.finish
+        end
+
+        retval
+      end
+
+      def transaction_from_env(env)
+        trans = Transaction.new
+
+        trans.add_tag(:request_method, env['REQUEST_METHOD'])
+        trans.add_tag(:request_uri, env['REQUEST_URI'])
+
+        trans
+      end
+
+      def tag_controller(trans, env)
+        controller = env[CONTROLLER_KEY]
+        label      = "#{controller.class.name}##{controller.action_name}"
+
+        trans.add_tag(:action, label)
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/sampler.rb b/lib/gitlab/metrics/sampler.rb
new file mode 100644
index 0000000000000000000000000000000000000000..998578e1c0a704e9f4c120474dfe2baa2e95604b
--- /dev/null
+++ b/lib/gitlab/metrics/sampler.rb
@@ -0,0 +1,98 @@
+module Gitlab
+  module Metrics
+    # Class that sends certain metrics to InfluxDB at a specific interval.
+    #
+    # This class is used to gather statistics that can't be directly associated
+    # with a transaction such as system memory usage, garbage collection
+    # statistics, etc.
+    class Sampler
+      # interval - The sampling interval in seconds.
+      def initialize(interval = 15)
+        @interval = interval
+        @metrics  = []
+
+        @last_minor_gc = Delta.new(GC.stat[:minor_gc_count])
+        @last_major_gc = Delta.new(GC.stat[:major_gc_count])
+
+        if Gitlab::Metrics.mri?
+          require 'allocations'
+
+          Allocations.start
+        end
+      end
+
+      def start
+        Thread.new do
+          Thread.current.abort_on_exception = true
+
+          loop do
+            sleep(@interval)
+
+            sample
+          end
+        end
+      end
+
+      def sample
+        sample_memory_usage
+        sample_file_descriptors
+        sample_objects
+        sample_gc
+
+        flush
+      ensure
+        GC::Profiler.clear
+        @metrics.clear
+      end
+
+      def flush
+        Metrics.submit_metrics(@metrics.map(&:to_hash))
+      end
+
+      def sample_memory_usage
+        @metrics << Metric.new('memory_usage', value: System.memory_usage)
+      end
+
+      def sample_file_descriptors
+        @metrics << Metric.
+          new('file_descriptors', value: System.file_descriptor_count)
+      end
+
+      if Metrics.mri?
+        def sample_objects
+          sample = Allocations.to_hash
+          counts = sample.each_with_object({}) do |(klass, count), hash|
+            hash[klass.name] = count
+          end
+
+          # Symbols aren't allocated so we'll need to add those manually.
+          counts['Symbol'] = Symbol.all_symbols.length
+
+          counts.each do |name, count|
+            @metrics << Metric.new('object_counts', { count: count }, type: name)
+          end
+        end
+      else
+        def sample_objects
+        end
+      end
+
+      def sample_gc
+        time  = GC::Profiler.total_time * 1000.0
+        stats = GC.stat.merge(total_time: time)
+
+        # We want the difference of GC runs compared to the last sample, not the
+        # total amount since the process started.
+        stats[:minor_gc_count] =
+          @last_minor_gc.compared_with(stats[:minor_gc_count])
+
+        stats[:major_gc_count] =
+          @last_major_gc.compared_with(stats[:major_gc_count])
+
+        stats[:count] = stats[:minor_gc_count] + stats[:major_gc_count]
+
+        @metrics << Metric.new('gc_statistics', stats)
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/sidekiq_middleware.rb b/lib/gitlab/metrics/sidekiq_middleware.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ad441decfa251670545e86ba10cb0e074c1fc9d2
--- /dev/null
+++ b/lib/gitlab/metrics/sidekiq_middleware.rb
@@ -0,0 +1,23 @@
+module Gitlab
+  module Metrics
+    # Sidekiq middleware for tracking jobs.
+    #
+    # This middleware is intended to be used as a server-side middleware.
+    class SidekiqMiddleware
+      def call(worker, message, queue)
+        trans = Transaction.new
+
+        begin
+          trans.run { yield }
+        ensure
+          tag_worker(trans, worker)
+          trans.finish
+        end
+      end
+
+      def tag_worker(trans, worker)
+        trans.add_tag(:action, "#{worker.class.name}#perform")
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/subscribers/action_view.rb b/lib/gitlab/metrics/subscribers/action_view.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7e0dcf99d926178ccfd52ee176f31a204646edbf
--- /dev/null
+++ b/lib/gitlab/metrics/subscribers/action_view.rb
@@ -0,0 +1,53 @@
+module Gitlab
+  module Metrics
+    module Subscribers
+      # Class for tracking the rendering timings of views.
+      class ActionView < ActiveSupport::Subscriber
+        attach_to :action_view
+
+        SERIES = 'views'
+
+        def render_template(event)
+          track(event) if current_transaction
+        end
+
+        alias_method :render_view, :render_template
+
+        private
+
+        def track(event)
+          values = values_for(event)
+          tags   = tags_for(event)
+
+          current_transaction.add_metric(SERIES, values, tags)
+        end
+
+        def relative_path(path)
+          path.gsub(/^#{Rails.root.to_s}\/?/, '')
+        end
+
+        def values_for(event)
+          { duration: event.duration }
+        end
+
+        def tags_for(event)
+          path = relative_path(event.payload[:identifier])
+          tags = { view: path }
+
+          file, line = Metrics.last_relative_application_frame
+
+          if file and line
+            tags[:file] = file
+            tags[:line] = line
+          end
+
+          tags
+        end
+
+        def current_transaction
+          Transaction.current
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d947c128ce22249a882d0816878bcb7b8bca23b5
--- /dev/null
+++ b/lib/gitlab/metrics/subscribers/active_record.rb
@@ -0,0 +1,48 @@
+module Gitlab
+  module Metrics
+    module Subscribers
+      # Class for tracking raw SQL queries.
+      #
+      # Queries are obfuscated before being logged to ensure no private data is
+      # exposed via InfluxDB/Grafana.
+      class ActiveRecord < ActiveSupport::Subscriber
+        attach_to :active_record
+
+        SERIES = 'sql_queries'
+
+        def sql(event)
+          return unless current_transaction
+
+          values = values_for(event)
+          tags   = tags_for(event)
+
+          current_transaction.add_metric(SERIES, values, tags)
+        end
+
+        private
+
+        def values_for(event)
+          { duration: event.duration }
+        end
+
+        def tags_for(event)
+          sql  = ObfuscatedSQL.new(event.payload[:sql]).to_s
+          tags = { sql: sql }
+
+          file, line = Metrics.last_relative_application_frame
+
+          if file and line
+            tags[:file] = file
+            tags[:line] = line
+          end
+
+          tags
+        end
+
+        def current_transaction
+          Transaction.current
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
new file mode 100644
index 0000000000000000000000000000000000000000..83371265278f6da3b93d1bb34bd0186771e6cc7f
--- /dev/null
+++ b/lib/gitlab/metrics/system.rb
@@ -0,0 +1,35 @@
+module Gitlab
+  module Metrics
+    # Module for gathering system/process statistics such as the memory usage.
+    #
+    # This module relies on the /proc filesystem being available. If /proc is
+    # not available the methods of this module will be stubbed.
+    module System
+      if File.exist?('/proc')
+        # Returns the current process' memory usage in bytes.
+        def self.memory_usage
+          mem   = 0
+          match = File.read('/proc/self/status').match(/VmRSS:\s+(\d+)/)
+
+          if match and match[1]
+            mem = match[1].to_f * 1024
+          end
+
+          mem
+        end
+
+        def self.file_descriptor_count
+          Dir.glob('/proc/self/fd/*').length
+        end
+      else
+        def self.memory_usage
+          0.0
+        end
+
+        def self.file_descriptor_count
+          0
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a61dbd989e782a064cc7f3c0cd7f8074de873579
--- /dev/null
+++ b/lib/gitlab/metrics/transaction.rb
@@ -0,0 +1,66 @@
+module Gitlab
+  module Metrics
+    # Class for storing metrics information of a single transaction.
+    class Transaction
+      THREAD_KEY = :_gitlab_metrics_transaction
+
+      SERIES = 'transactions'
+
+      attr_reader :uuid, :tags
+
+      def self.current
+        Thread.current[THREAD_KEY]
+      end
+
+      # name - The name of this transaction as a String.
+      def initialize
+        @metrics = []
+        @uuid    = SecureRandom.uuid
+
+        @started_at  = nil
+        @finished_at = nil
+
+        @tags = {}
+      end
+
+      def duration
+        @finished_at ? (@finished_at - @started_at) * 1000.0 : 0.0
+      end
+
+      def run
+        Thread.current[THREAD_KEY] = self
+
+        @started_at = Time.now
+
+        yield
+      ensure
+        @finished_at = Time.now
+
+        Thread.current[THREAD_KEY] = nil
+      end
+
+      def add_metric(series, values, tags = {})
+        tags = tags.merge(transaction_id: @uuid)
+
+        @metrics << Metric.new(series, values, tags)
+      end
+
+      def add_tag(key, value)
+        @tags[key] = value
+      end
+
+      def finish
+        track_self
+        submit
+      end
+
+      def track_self
+        add_metric(SERIES, { duration: duration }, @tags)
+      end
+
+      def submit
+        Metrics.submit_metrics(@metrics.map(&:to_hash))
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/o_auth/session.rb b/lib/gitlab/o_auth/session.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f33bfd0bd0e684e6ca8ba31796b1878889b2c8f1
--- /dev/null
+++ b/lib/gitlab/o_auth/session.rb
@@ -0,0 +1,17 @@
+module Gitlab
+  module OAuth
+    module Session
+      def self.create(provider, ticket)
+        Rails.cache.write("gitlab:#{provider}:#{ticket}", ticket, expires_in: Gitlab.config.omniauth.cas3.session_duration)
+      end
+
+      def self.destroy(provider, ticket)
+        Rails.cache.delete("gitlab:#{provider}:#{ticket}")
+      end
+
+      def self.valid?(provider, ticket)
+        Rails.cache.read("gitlab:#{provider}:#{ticket}").present?
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb
index 17ce4d4b1747e7004ed7e628b5c01f85008df745..f1a362f5303a296099c4ed7c725312b9498605a1 100644
--- a/lib/gitlab/o_auth/user.rb
+++ b/lib/gitlab/o_auth/user.rb
@@ -64,7 +64,7 @@ module Gitlab
 
         # If a corresponding person exists with same uid in a LDAP server,
         # set up a Gitlab user with dual LDAP and Omniauth identities.
-        if user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn.downcase, ldap_person.provider)
+        if user = Gitlab::LDAP::User.find_by_uid_and_provider(ldap_person.dn, ldap_person.provider)
           # Case when a LDAP user already exists in Gitlab. Add the Omniauth identity to existing account.
           user.identities.build(extern_uid: auth_hash.uid, provider: auth_hash.provider)
         else
diff --git a/lib/gitlab/recaptcha.rb b/lib/gitlab/recaptcha.rb
new file mode 100644
index 0000000000000000000000000000000000000000..70e7f25d518f6f62d0b2c969d2c5e104829d707a
--- /dev/null
+++ b/lib/gitlab/recaptcha.rb
@@ -0,0 +1,14 @@
+module Gitlab
+  module Recaptcha
+    def self.load_configurations!
+      if current_application_settings.recaptcha_enabled
+        ::Recaptcha.configure do |config|
+          config.public_key  = current_application_settings.recaptcha_site_key
+          config.private_key = current_application_settings.recaptcha_private_key
+        end
+
+        true
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index 42f7c26f3c4a10a8d0b0834c81daa2beab2f2bd5..be795649e59ab6015f114cb196e4c95ad902a58f 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -3,11 +3,12 @@ require 'banzai'
 module Gitlab
   # Extract possible GFM references from an arbitrary String for further processing.
   class ReferenceExtractor < Banzai::ReferenceExtractor
-    attr_accessor :project, :current_user
+    attr_accessor :project, :current_user, :author
 
-    def initialize(project, current_user = nil)
+    def initialize(project, current_user = nil, author = nil)
       @project = project
       @current_user = current_user
+      @author = author
 
       @references = {}
 
@@ -18,10 +19,24 @@ module Gitlab
       super(text, context.merge(project: project))
     end
 
-    %i(user label issue merge_request snippet commit commit_range).each do |type|
+    %i(user label merge_request snippet commit commit_range).each do |type|
       define_method("#{type}s") do
-        @references[type] ||= references(type, project: project, current_user: current_user)
+        @references[type] ||= references(type, reference_context)
       end
     end
+
+    def issues
+      if project && project.jira_tracker?
+        @references[:external_issue] ||= references(:external_issue, reference_context)
+      else
+        @references[:issue] ||= references(:issue, reference_context)
+      end
+    end
+
+    private
+
+    def reference_context
+      { project: project, current_user: current_user, author: author }
+    end
   end
 end
diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index 335dc44be19d2cee966cbb6d407d11c0f4db23d4..3160a3c7582547aa117bae1285e0e3ce9424e2d4 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -51,6 +51,15 @@ module Gitlab
       def allowed_fork_levels(origin_level)
         [PRIVATE, INTERNAL, PUBLIC].select{ |level| level <= origin_level }
       end
+
+      def level_name(level)
+        level_name = 'Unknown'
+        options.each do |name, lvl|
+          level_name = name if lvl == level.to_i
+        end
+
+        level_name
+      end
     end
 
     def private?
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index 6762ca47c328cc0db82d85f7b220b5f356b1cc15..8c309efc7b8fc58c227fc21e51b01b01fa3efb27 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -39,7 +39,7 @@ module Rouge
           lineanchorsid: 'L',
           anchorlinenos: false,
           inline_theme: nil
-        )
+      )
         @nowrap = nowrap
         @cssclass = cssclass
         @linenos = linenos
diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab
index 43fda6fa92e59f8d3f3302be51f36b4e8ceee9ec..c5f07c8b508a948796901b0cf6bcc5024360ba71 100755
--- a/lib/support/init.d/gitlab
+++ b/lib/support/init.d/gitlab
@@ -33,12 +33,13 @@ app_user="git"
 app_root="/home/$app_user/gitlab"
 pid_path="$app_root/tmp/pids"
 socket_path="$app_root/tmp/sockets"
+rails_socket="$socket_path/gitlab.socket"
 web_server_pid_path="$pid_path/unicorn.pid"
 sidekiq_pid_path="$pid_path/sidekiq.pid"
 mail_room_enabled=false
 mail_room_pid_path="$pid_path/mail_room.pid"
 gitlab_workhorse_pid_path="$pid_path/gitlab-workhorse.pid"
-gitlab_workhorse_options="-listenUmask 0 -listenNetwork unix -listenAddr $socket_path/gitlab-workhorse.socket -authBackend http://127.0.0.1:8080"
+gitlab_workhorse_options="-listenUmask 0 -listenNetwork unix -listenAddr $socket_path/gitlab-workhorse.socket -authBackend http://127.0.0.1:8080 -authSocket $rails_socket -documentRoot $app_root/public"
 gitlab_workhorse_log="$app_root/log/gitlab-workhorse.log"
 shell_path="/bin/bash"
 
@@ -91,7 +92,7 @@ check_pids(){
 
 ## Called when we have started the two processes and are waiting for their pid files.
 wait_for_pids(){
-  # We are sleeping a bit here mostly because sidekiq is slow at writing it's pid
+  # We are sleeping a bit here mostly because sidekiq is slow at writing its pid
   i=0;
   while [ ! -f $web_server_pid_path ] || [ ! -f $sidekiq_pid_path ] || [ ! -f $gitlab_workhorse_pid_path ] || { [ "$mail_room_enabled" = true ] && [ ! -f $mail_room_pid_path ]; }; do
     sleep 0.1;
@@ -107,7 +108,7 @@ wait_for_pids(){
 }
 
 # We use the pids in so many parts of the script it makes sense to always check them.
-# Only after start() is run should the pids change. Sidekiq sets it's own pid.
+# Only after start() is run should the pids change. Sidekiq sets its own pid.
 check_pids
 
 
@@ -289,7 +290,7 @@ stop_gitlab() {
   sleep 1
   # Cleaning up unused pids
   rm "$web_server_pid_path" 2>/dev/null
-  # rm "$sidekiq_pid_path" 2>/dev/null # Sidekiq seems to be cleaning up it's own pid.
+  # rm "$sidekiq_pid_path" 2>/dev/null # Sidekiq seems to be cleaning up its own pid.
   rm -f "$gitlab_workhorse_pid_path"
   if [ "$mail_room_enabled" = true ]; then
     rm "$mail_room_pid_path" 2>/dev/null
@@ -298,7 +299,7 @@ stop_gitlab() {
   print_status
 }
 
-## Prints the status of GitLab and it's components.
+## Prints the status of GitLab and its components.
 print_status() {
   check_status
   if [ "$web_status" != "0" ] && [ "$sidekiq_status" != "0" ] && [ "$gitlab_workhorse_status" != "0" ] && { [ "$mail_room_enabled" != true ] || [ "$mail_room_status" != "0" ]; }; then
@@ -332,7 +333,7 @@ print_status() {
   fi
 }
 
-## Tells unicorn to reload it's config and Sidekiq to restart
+## Tells unicorn to reload its config and Sidekiq to restart
 reload_gitlab(){
   exit_if_not_running
   if [ "$wpid" = "0" ];then
diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example
index 79ae8e0ae55abf2fb3fe76dd692b1b4fe9dd3462..1937ca582b0548939c42d2aca1bab39b45357b2a 100755
--- a/lib/support/init.d/gitlab.default.example
+++ b/lib/support/init.d/gitlab.default.example
@@ -9,11 +9,11 @@ RAILS_ENV="production"
 # The default is "git".
 app_user="git"
 
-# app_root defines the folder in which gitlab and it's components are installed.
+# app_root defines the folder in which gitlab and its components are installed.
 # The default is "/home/$app_user/gitlab"
 app_root="/home/$app_user/gitlab"
 
-# pid_path defines a folder in which the gitlab and it's components place their pids.
+# pid_path defines a folder in which the gitlab and its components place their pids.
 # This variable is also used below to define the relevant pids for the gitlab components.
 # The default is "$app_root/tmp/pids"
 pid_path="$app_root/tmp/pids"
@@ -36,7 +36,7 @@ gitlab_workhorse_pid_path="$pid_path/gitlab-workhorse.pid"
 # '-listenNetwork tcp -listenAddr localhost:8181'.
 # The -authBackend setting tells gitlab-workhorse where it can reach
 # Unicorn.
-gitlab_workhorse_options="-listenUmask 0 -listenNetwork unix -listenAddr $socket_path/gitlab-workhorse.socket -authBackend http://127.0.0.1:8080"
+gitlab_workhorse_options="-listenUmask 0 -listenNetwork unix -listenAddr $socket_path/gitlab-workhorse.socket -authBackend http://127.0.0.1:8080 -authSocket $socket_path/gitlab.socket -documentRoot $app_root/public"
 gitlab_workhorse_log="$app_root/log/gitlab-workhorse.log"
 
 # mail_room_enabled specifies whether mail_room, which is used to process incoming email, is enabled.
diff --git a/lib/support/nginx/gitlab b/lib/support/nginx/gitlab
index 2a79fbdcf93c8fddfd1c487318f88c09d0bbaf2e..fc5475c4eef881b2b67e8bcc231f622144b93fa0 100644
--- a/lib/support/nginx/gitlab
+++ b/lib/support/nginx/gitlab
@@ -10,34 +10,12 @@
 ## If you change this file in a Merge Request, please also create
 ## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
 ##
-##################################
-##        CHUNKED TRANSFER      ##
-##################################
-##
-## It is a known issue that Git-over-HTTP requires chunked transfer encoding [0]
-## which is not supported by Nginx < 1.3.9 [1]. As a result, pushing a large object
-## with Git (i.e. a single large file) can lead to a 411 error. In theory you can get
-## around this by tweaking this configuration file and either:
-## - installing an old version of Nginx with the chunkin module [2] compiled in, or
-## - using a newer version of Nginx.
-##
-## At the time of writing we do not know if either of these theoretical solutions works.
-## As a workaround users can use Git over SSH to push large files.
-##
-## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99
-## [1] https://github.com/agentzh/chunkin-nginx-module#status
-## [2] https://github.com/agentzh/chunkin-nginx-module
-##
 ###################################
 ##         configuration         ##
 ###################################
 ##
 ## See installation.md#using-https for additional HTTPS configuration details.
 
-upstream gitlab {
-  server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0;
-}
-
 upstream gitlab-workhorse {
   server unix:/home/git/gitlab/tmp/sockets/gitlab-workhorse.socket fail_timeout=0;
 }
@@ -54,10 +32,6 @@ server {
   server_tokens off; ## Don't show the nginx version number, a security best practice
   root /home/git/gitlab/public;
 
-  ## Increase this if you want to upload large attachments
-  ## Or if you want to accept large git objects over http
-  client_max_body_size 20m;
-
   ## See app/controllers/application_controller.rb for headers set
 
   ## Individual nginx logs for this GitLab vhost
@@ -65,103 +39,8 @@ server {
   error_log   /var/log/nginx/gitlab_error.log;
 
   location / {
-    ## Serve static files from defined root folder.
-    ## @gitlab is a named location for the upstream fallback, see below.
-    try_files $uri /index.html $uri.html @gitlab;
-  }
-
-  ## We route uploads through GitLab to prevent XSS and enforce access control.
-  location /uploads/ {
-    ## If you use HTTPS make sure you disable gzip compression
-    ## to be safe against BREACH attack.
-    # gzip off;
-
-    ## https://github.com/gitlabhq/gitlabhq/issues/694
-    ## Some requests take more than 30 seconds.
-    proxy_read_timeout      300;
-    proxy_connect_timeout   300;
-    proxy_redirect          off;
-
-    proxy_set_header    Host                $http_host;
-    proxy_set_header    X-Real-IP           $remote_addr;
-    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
-    proxy_set_header    X-Forwarded-Proto   $scheme;
-    proxy_set_header    X-Frame-Options     SAMEORIGIN;
-
-    proxy_pass http://gitlab;
-  }
-
-  ## If a file, which is not found in the root folder is requested,
-  ## then the proxy passes the request to the upsteam (gitlab unicorn).
-  location @gitlab {
-    ## If you use HTTPS make sure you disable gzip compression
-    ## to be safe against BREACH attack.
-    # gzip off;
-
-    ## https://github.com/gitlabhq/gitlabhq/issues/694
-    ## Some requests take more than 30 seconds.
-    proxy_read_timeout      300;
-    proxy_connect_timeout   300;
-    proxy_redirect          off;
-
-    proxy_set_header    Host                $http_host;
-    proxy_set_header    X-Real-IP           $remote_addr;
-    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
-    proxy_set_header    X-Forwarded-Proto   $scheme;
-    proxy_set_header    X-Frame-Options     SAMEORIGIN;
-
-    proxy_pass http://gitlab;
-  }
-
-  location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  location ~ ^/api/v3/projects/.*/repository/archive {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  # Build artifacts should be submitted to this location
-  location ~ ^/[\w\.-]+/[\w\.-]+/builds/download {
     client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  # Build artifacts should be submitted to this location
-  location ~ /ci/api/v1/builds/[0-9]+/artifacts {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  location @gitlab-workhorse {
-    client_max_body_size 0;
-    ## If you use HTTPS make sure you disable gzip compression
-    ## to be safe against BREACH attack.
-    # gzip off;
+    gzip off;
 
     ## https://github.com/gitlabhq/gitlabhq/issues/694
     ## Some requests take more than 30 seconds.
@@ -169,14 +48,7 @@ server {
     proxy_connect_timeout   300;
     proxy_redirect          off;
 
-    # Do not buffer Git HTTP responses
-    proxy_buffering off;
-
-    # The following settings only work with NGINX 1.7.11 or newer
-    #
-    # # Pass chunked request bodies to gitlab-workhorse as-is
-    # proxy_request_buffering off;
-    # proxy_http_version 1.1;
+    proxy_http_version 1.1;
 
     proxy_set_header    Host                $http_host;
     proxy_set_header    X-Real-IP           $remote_addr;
@@ -185,18 +57,4 @@ server {
 
     proxy_pass http://gitlab-workhorse;
   }
-
-  ## Enable gzip compression as per rails guide:
-  ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
-  ## WARNING: If you are using relative urls remove the block below
-  ## See config/application.rb under "Relative url support" for the list of
-  ## other files that need to be changed for relative url support
-  location ~ ^/(assets)/ {
-    root /home/git/gitlab/public;
-    gzip_static on; # to serve pre-gzipped version
-    expires max;
-    add_header Cache-Control public;
-  }
-
-  error_page 502 /502.html;
 }
diff --git a/lib/support/nginx/gitlab-ssl b/lib/support/nginx/gitlab-ssl
index 79fe1474821293ab2be6c743d8b679633141f9cd..1e5f85413ec6dd8d124c4795f3b9dbfa32acfa86 100644
--- a/lib/support/nginx/gitlab-ssl
+++ b/lib/support/nginx/gitlab-ssl
@@ -14,34 +14,12 @@
 ## If you change this file in a Merge Request, please also create
 ## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests
 ##
-##################################
-##        CHUNKED TRANSFER      ##
-##################################
-##
-## It is a known issue that Git-over-HTTP requires chunked transfer encoding [0]
-## which is not supported by Nginx < 1.3.9 [1]. As a result, pushing a large object
-## with Git (i.e. a single large file) can lead to a 411 error. In theory you can get
-## around this by tweaking this configuration file and either:
-## - installing an old version of Nginx with the chunkin module [2] compiled in, or
-## - using a newer version of Nginx.
-##
-## At the time of writing we do not know if either of these theoretical solutions works.
-## As a workaround users can use Git over SSH to push large files.
-##
-## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99
-## [1] https://github.com/agentzh/chunkin-nginx-module#status
-## [2] https://github.com/agentzh/chunkin-nginx-module
-##
 ###################################
 ##         configuration         ##
 ###################################
 ##
 ## See installation.md#using-https for additional HTTPS configuration details.
 
-upstream gitlab {
-  server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0;
-}
-
 upstream gitlab-workhorse {
   server unix:/home/git/gitlab/tmp/sockets/gitlab-workhorse.socket fail_timeout=0;
 }
@@ -61,7 +39,6 @@ server {
   error_log   /var/log/nginx/gitlab_error.log;
 }
 
-
 ## HTTPS host
 server {
   listen 0.0.0.0:443 ssl;
@@ -70,10 +47,6 @@ server {
   server_tokens off; ## Don't show the nginx version number, a security best practice
   root /home/git/gitlab/public;
 
-  ## Increase this if you want to upload large attachments
-  ## Or if you want to accept large git objects over http
-  client_max_body_size 20m;
-
   ## Strong SSL Security
   ## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/
   ssl on;
@@ -110,104 +83,7 @@ server {
   error_log   /var/log/nginx/gitlab_error.log;
 
   location / {
-    ## Serve static files from defined root folder.
-    ## @gitlab is a named location for the upstream fallback, see below.
-    try_files $uri /index.html $uri.html @gitlab;
-  }
-
-  ## We route uploads through GitLab to prevent XSS and enforce access control.
-  location /uploads/ {
-    ## If you use HTTPS make sure you disable gzip compression
-    ## to be safe against BREACH attack.
-    gzip off;
-
-    ## https://github.com/gitlabhq/gitlabhq/issues/694
-    ## Some requests take more than 30 seconds.
-    proxy_read_timeout      300;
-    proxy_connect_timeout   300;
-    proxy_redirect          off;
-
-    proxy_set_header    Host                $http_host;
-    proxy_set_header    X-Real-IP           $remote_addr;
-    proxy_set_header    X-Forwarded-Ssl     on;
-    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
-    proxy_set_header    X-Forwarded-Proto   $scheme;
-    proxy_set_header    X-Frame-Options     SAMEORIGIN;
-
-    proxy_pass http://gitlab;
-  }
-
-  ## If a file, which is not found in the root folder is requested,
-  ## then the proxy passes the request to the upsteam (gitlab unicorn).
-  location @gitlab {
-    ## If you use HTTPS make sure you disable gzip compression
-    ## to be safe against BREACH attack.
-    gzip off;
-
-    ## https://github.com/gitlabhq/gitlabhq/issues/694
-    ## Some requests take more than 30 seconds.
-    proxy_read_timeout      300;
-    proxy_connect_timeout   300;
-    proxy_redirect          off;
-
-    proxy_set_header    Host                $http_host;
-    proxy_set_header    X-Real-IP           $remote_addr;
-    proxy_set_header    X-Forwarded-Ssl     on;
-    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
-    proxy_set_header    X-Forwarded-Proto   $scheme;
-    proxy_set_header    X-Frame-Options     SAMEORIGIN;
-
-    proxy_pass http://gitlab;
-  }
-
-  location ~ ^/[\w\.-]+/[\w\.-]+/gitlab-lfs/objects {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive {
     client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  location ~ ^/api/v3/projects/.*/repository/archive {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  # Build artifacts should be submitted to this location
-  location ~ ^/[\w\.-]+/[\w\.-]+/builds/download {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  # Build artifacts should be submitted to this location
-  location ~ /ci/api/v1/builds/[0-9]+/artifacts {
-    client_max_body_size 0;
-    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
-    error_page 418 = @gitlab-workhorse;
-    return 418;
-  }
-
-  location @gitlab-workhorse {
-    client_max_body_size 0;
-    ## If you use HTTPS make sure you disable gzip compression
-    ## to be safe against BREACH attack.
     gzip off;
 
     ## https://github.com/gitlabhq/gitlabhq/issues/694
@@ -216,14 +92,7 @@ server {
     proxy_connect_timeout   300;
     proxy_redirect          off;
 
-    # Do not buffer Git HTTP responses
-    proxy_buffering off;
-
-    # The following settings only work with NGINX 1.7.11 or newer
-    #
-    # # Pass chunked request bodies to gitlab-workhorse as-is
-    # proxy_request_buffering off;
-    # proxy_http_version 1.1;
+    proxy_http_version 1.1;
 
     proxy_set_header    Host                $http_host;
     proxy_set_header    X-Real-IP           $remote_addr;
@@ -232,18 +101,4 @@ server {
     proxy_set_header    X-Forwarded-Proto   $scheme;
     proxy_pass http://gitlab-workhorse;
   }
-
-  ## Enable gzip compression as per rails guide:
-  ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
-  ## WARNING: If you are using relative urls remove the block below
-  ## See config/application.rb under "Relative url support" for the list of
-  ## other files that need to be changed for relative url support
-  location ~ ^/(assets)/ {
-    root /home/git/gitlab/public;
-    gzip_static on; # to serve pre-gzipped version
-    expires max;
-    add_header Cache-Control public;
-  }
-
-  error_page 502 /502.html;
 }
diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb
index a474574c6e5a40284b9a57e9d6ad9ffdd44b81a5..e74731c9ed82b07093aa3718306dbeac5ce9bebe 100644
--- a/spec/controllers/projects/tree_controller_spec.rb
+++ b/spec/controllers/projects/tree_controller_spec.rb
@@ -98,7 +98,7 @@ describe Projects::TreeController do
            project_id: project.to_param,
            id: 'master',
            dir_name: path,
-           new_branch: target_branch,
+           target_branch: target_branch,
            commit_message: 'Test commit message')
     end
 
@@ -108,8 +108,8 @@ describe Projects::TreeController do
 
       it 'redirects to the new directory' do
         expect(subject).
-            to redirect_to("/#{project.path_with_namespace}/blob/#{target_branch}/#{path}")
-        expect(flash[:notice]).to eq('The directory has been successfully created')
+            to redirect_to("/#{project.path_with_namespace}/tree/#{target_branch}/#{path}")
+        expect(flash[:notice]).to eq('The directory has been successfully created.')
       end
     end
 
@@ -119,7 +119,7 @@ describe Projects::TreeController do
 
       it 'does not allow overwriting of existing files' do
         expect(subject).
-            to redirect_to("/#{project.path_with_namespace}/blob/master")
+            to redirect_to("/#{project.path_with_namespace}/tree/master")
         expect(flash[:alert]).to eq('Directory already exists as a file')
       end
     end
diff --git a/spec/factories.rb b/spec/factories.rb
index 4bf93adabe27c31e5977daa3eb85726ce88e2a17..d6b4efa9a03d78b858ccf43b2e2d0cc54e57c9c0 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -43,7 +43,8 @@ FactoryGirl.define do
       end
 
       after(:create) do |user, evaluator|
-        user.identities << create(:identity,
+        user.identities << create(
+          :identity,
           provider: evaluator.provider,
           extern_uid: evaluator.extern_uid
         )
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 66a2cc0c157a90737ab32cdb29055552d926079e..26d03944b8a24dd811e1a6da96f05b73118ae215 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -63,7 +63,7 @@ describe "Admin Runners" do
   end
 
   describe 'runners registration token' do
-    let!(:token) { current_application_settings.ensure_runners_registration_token }
+    let!(:token) { current_application_settings.runners_registration_token }
     before { visit admin_runners_path }
 
     it 'has a registration token' do
diff --git a/spec/features/ci_lint_spec.rb b/spec/features/ci_lint_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e6e73e5e67ca34dd3ea2734fc30842bdf0d9c6a2
--- /dev/null
+++ b/spec/features/ci_lint_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe 'CI Lint' do
+  before do
+    login_as :user
+  end
+
+  describe 'YAML parsing' do
+    before do
+      visit ci_lint_path
+      fill_in 'content', with: yaml_content
+      click_on 'Validate'
+    end
+
+    context 'YAML is correct' do
+      let(:yaml_content) do
+        File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
+      end
+
+      it 'Yaml parsing' do
+        within "table" do
+          expect(page).to have_content('Job - rspec')
+          expect(page).to have_content('Job - spinach')
+          expect(page).to have_content('Deploy Job - staging')
+          expect(page).to have_content('Deploy Job - production')
+        end
+      end
+    end
+
+    context 'YAML is incorrect' do
+      let(:yaml_content) { '' }
+
+      it 'displays information about an error' do
+        expect(page).to have_content('Status: syntax is incorrect')
+        expect(page).to have_content('Error: Please provide content of .gitlab-ci.yml')
+      end
+    end
+  end
+end
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index ecc85376ffc22067694922833748d524f113d5ad..fe7f07f5b75017293b4772d71c7ecd746a2da46c 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -19,30 +19,13 @@ describe 'Commits' do
     let!(:build) { FactoryGirl.create :ci_build, commit: commit }
 
     describe 'Project commits' do
-      context 'builds enabled' do
-        context '.gitlab-ci.yml found' do
-          before do
-            visit namespace_project_commits_path(project.namespace, project, :master)
-          end
-
-          it 'should show build status' do
-            page.within("//li[@id='commit-#{commit.short_sha}']") do
-              expect(page).to have_css(".ci-status-link")
-            end
-          end
-        end
+      before do
+        visit namespace_project_commits_path(project.namespace, project, :master)
+      end
 
-        context 'no .gitlab-ci.yml found' do
-          before do
-            stub_ci_commit_yaml_file(nil)
-            visit namespace_project_commits_path(project.namespace, project, :master)
-          end
-
-          it 'should not show build status' do
-            page.within("//li[@id='commit-#{commit.short_sha}']") do
-              expect(page).to have_no_css(".ci-status-link")
-            end
-          end
+      it 'should show build status' do
+        page.within("//li[@id='commit-#{commit.short_sha}']") do
+          expect(page).to have_css(".ci-status-link")
         end
       end
     end
diff --git a/spec/features/issues/filter_by_milestone_spec.rb b/spec/features/issues/filter_by_milestone_spec.rb
index f600f8684acfcf2eeec6a5e73bc1c964fb2b4498..38c8d343ce3bd79b1462905104e464fbebec152f 100644
--- a/spec/features/issues/filter_by_milestone_spec.rb
+++ b/spec/features/issues/filter_by_milestone_spec.rb
@@ -13,7 +13,7 @@ feature 'Issue filtering by Milestone', feature: true do
     visit_issues(project)
     filter_by_milestone(Milestone::None.title)
 
-    expect(page).to have_css('.issue-title', count: 1)
+    expect(page).to have_css('.title', count: 1)
   end
 
   scenario 'filters by a specific Milestone', js: true do
@@ -23,7 +23,7 @@ feature 'Issue filtering by Milestone', feature: true do
     visit_issues(project)
     filter_by_milestone(milestone.title)
 
-    expect(page).to have_css('.issue-title', count: 1)
+    expect(page).to have_css('.title', count: 1)
   end
 
   def visit_issues(project)
diff --git a/spec/features/lint_spec.rb b/spec/features/lint_spec.rb
deleted file mode 100644
index 5d8f56e2cfb160bac8f81f0e6a41e276d0a7713a..0000000000000000000000000000000000000000
--- a/spec/features/lint_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'spec_helper'
-
-describe "Lint" do
-  before do
-    login_as :user
-  end
-
-  it "Yaml parsing", js: true do
-    content = File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
-    visit ci_lint_path 
-    fill_in "content", with: content
-    click_on "Validate"
-    within "table" do
-      expect(page).to have_content("Job - rspec")
-      expect(page).to have_content("Job - spinach")
-      expect(page).to have_content("Deploy Job - staging")
-      expect(page).to have_content("Deploy Job - production")
-    end
-  end
-
-  it "Yaml parsing with error", js: true do
-    visit ci_lint_path
-    fill_in "content", with: ""
-    click_on "Validate"
-    expect(page).to have_content("Status: syntax is incorrect")
-    expect(page).to have_content("Error: Please provide content of .gitlab-ci.yml")
-  end
-end
diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb
index 922c76285d1865baca9aa06007aab96e9985a7df..2451e56fe7ce6338b3863e06dee98c2351bec2bc 100644
--- a/spec/features/login_spec.rb
+++ b/spec/features/login_spec.rb
@@ -98,4 +98,56 @@ feature 'Login', feature: true do
       expect(page).to have_content('Invalid login or password.')
     end
   end
+
+  describe 'with required two-factor authentication enabled' do
+    let(:user) { create(:user) }
+    before(:each) { stub_application_setting(require_two_factor_authentication: true) }
+
+    context 'with grace period defined' do
+      before(:each) do
+        stub_application_setting(two_factor_grace_period: 48)
+        login_with(user)
+      end
+
+      context 'within the grace period' do
+        it 'redirects to two-factor configuration page' do
+          expect(current_path).to eq new_profile_two_factor_auth_path
+          expect(page).to have_content('You must configure Two-Factor Authentication in your account until')
+        end
+
+        it 'two-factor configuration is skippable' do
+          expect(current_path).to eq new_profile_two_factor_auth_path
+
+          click_link 'Configure it later'
+          expect(current_path).to eq root_path
+        end
+      end
+
+      context 'after the grace period' do
+        let(:user) { create(:user, otp_grace_period_started_at: 9999.hours.ago) }
+
+        it 'redirects to two-factor configuration page' do
+          expect(current_path).to eq new_profile_two_factor_auth_path
+          expect(page).to have_content('You must configure Two-Factor Authentication in your account.')
+        end
+
+        it 'two-factor configuration is not skippable' do
+          expect(current_path).to eq new_profile_two_factor_auth_path
+          expect(page).not_to have_link('Configure it later')
+        end
+      end
+    end
+
+    context 'without grace pariod defined' do
+      before(:each) do
+        stub_application_setting(two_factor_grace_period: 0)
+        login_with(user)
+      end
+
+      it 'redirects to two-factor configuration page' do
+        expect(current_path).to eq new_profile_two_factor_auth_path
+        expect(page).to have_content('You must configure Two-Factor Authentication in your account.')
+      end
+    end
+  end
 end
diff --git a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb
index 28a46a0725d81c2e464607228f5ab52f8d30c7b9..7aa7eb965e908ee173aeda4fff7b815414389a2d 100644
--- a/spec/features/merge_requests/merge_when_build_succeeds_spec.rb
+++ b/spec/features/merge_requests/merge_when_build_succeeds_spec.rb
@@ -21,12 +21,12 @@ feature 'Merge When Build Succeeds', feature: true, js: true do
     end
 
     it 'displays the Merge When Build Succeeds button' do
-      expect(page).to have_link "Merge When Build Succeeds"
+      expect(page).to have_button "Merge When Build Succeeds"
     end
 
     context "Merge When Build succeeds enabled" do
       before do
-        click_link "Merge When Build Succeeds"
+        click_button "Merge When Build Succeeds"
       end
 
       it 'activates Merge When Build Succeeds feature' do
@@ -58,7 +58,7 @@ feature 'Merge When Build Succeeds', feature: true, js: true do
     it 'cancels the automatic merge' do
       click_link "Cancel Automatic Merge"
 
-      expect(page).to have_link  "Merge When Build Succeeds"
+      expect(page).to have_button "Merge When Build Succeeds"
 
       visit_merge_request(merge_request) # Needed to refresh the page
       expect(page).to have_content "Canceled the automatic merge"
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 09fcff2444ac83771442c68f0935fd591fdd4305..74b148f5d178b44fb55aa3340cbca7f4fefc5180 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -70,6 +70,20 @@ feature 'Project', feature: true do
     end
   end
 
+  describe 'leave project link' do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project, namespace: user.namespace) }
+
+    before do
+      login_with(user)
+      project.team.add_user(user, Gitlab::Access::MASTER)
+      visit namespace_project_path(project.namespace, project)
+    end
+
+    it { expect(page).to have_content('You have Master access to this project.') }
+    it { expect(page).to have_link('Leave this project') }
+  end
+
   def remove_with_confirm(button_text, confirm_with)
     click_button button_text
     fill_in 'confirm_name_input', with: confirm_with
diff --git a/spec/features/security/group_access_spec.rb b/spec/features/security/group_access_spec.rb
index 4b78e3a61f04ebeea7ffd9953bcccf7da94b6bfd..65f8073c6933937f2264d17103af85671ab64951 100644
--- a/spec/features/security/group_access_spec.rb
+++ b/spec/features/security/group_access_spec.rb
@@ -16,11 +16,11 @@ describe 'Group access', feature: true do
     end
   end
 
-  def group_member(access_level, group = group)
+  def group_member(access_level, grp = group())
     level = Object.const_get("Gitlab::Access::#{access_level.upcase}")
 
     create(:user).tap do |user|
-      group.add_user(user, level)
+      grp.add_user(user, level)
     end
   end
 
diff --git a/spec/features/task_lists_spec.rb b/spec/features/task_lists_spec.rb
index fca3c77fc64464e9e8a1fda7d31c237b7c699902..b7368cca29d0cdb3dbfcca4f7910718866e10cc7 100644
--- a/spec/features/task_lists_spec.rb
+++ b/spec/features/task_lists_spec.rb
@@ -47,7 +47,7 @@ feature 'Task Lists', feature: true do
     it 'contains the required selectors' do
       visit_issue(project, issue)
 
-      container = '.issue-details .description.js-task-list-container'
+      container = '.detail-page-description .description.js-task-list-container'
 
       expect(page).to have_selector(container)
       expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox")
@@ -123,7 +123,7 @@ feature 'Task Lists', feature: true do
     it 'contains the required selectors' do
       visit_merge_request(project, merge)
 
-      container = '.merge-request-details .description.js-task-list-container'
+      container = '.detail-page-description .description.js-task-list-container'
 
       expect(page).to have_selector(container)
       expect(page).to have_selector("#{container} .wiki .task-list .task-list-item .task-list-item-checkbox")
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 5568f06639c42b83c147fe9052007ab2e3e26a84..68527c3a4f84b173bf8e30e55e81e7d6d1963cd1 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -263,11 +263,12 @@ describe ApplicationHelper do
     end
 
     it 'includes a default js-timeago class' do
-      expect(element.attr('class')).to eq 'time_ago js-timeago'
+      expect(element.attr('class')).to eq 'time_ago js-timeago js-timeago-pending'
     end
 
     it 'accepts a custom html_class' do
-      expect(element(html_class: 'custom_class').attr('class')).to eq 'custom_class js-timeago'
+      expect(element(html_class: 'custom_class').attr('class')).
+        to eq 'custom_class js-timeago js-timeago-pending'
     end
 
     it 'accepts a custom tooltip placement' do
@@ -278,7 +279,7 @@ describe ApplicationHelper do
       el = element.next_element
 
       expect(el.name).to eq 'script'
-      expect(el.text).to include "$('.js-timeago').last().timeago()"
+      expect(el.text).to include "$('.js-timeago-pending').removeClass('js-timeago-pending').timeago()"
     end
 
     it 'allows the script tag to be excluded' do
diff --git a/spec/helpers/ci_status_helper_spec.rb b/spec/helpers/ci_status_helper_spec.rb
index 7fc53eb1472e321927c93eb7a3ad7a667f2e2df0..4f8d9c672620ce6c64b1c092b7944ca896c1e177 100644
--- a/spec/helpers/ci_status_helper_spec.rb
+++ b/spec/helpers/ci_status_helper_spec.rb
@@ -6,13 +6,8 @@ describe CiStatusHelper do
   let(:success_commit) { double("Ci::Commit", status: 'success') }
   let(:failed_commit) { double("Ci::Commit", status: 'failed') }
 
-  describe 'ci_status_color' do
-    it { expect(ci_status_icon(success_commit)).to include('fa-check') }
-    it { expect(ci_status_icon(failed_commit)).to include('fa-close') }
-  end
-
-  describe 'ci_status_color' do
-    it { expect(ci_status_color(success_commit)).to eq('green') }
-    it { expect(ci_status_color(failed_commit)).to eq('red') }
+  describe 'ci_status_icon' do
+    it { expect(helper.ci_status_icon(success_commit)).to include('fa-check') }
+    it { expect(helper.ci_status_icon(failed_commit)).to include('fa-close') }
   end
 end
diff --git a/spec/helpers/groups_helper.rb b/spec/helpers/groups_helper.rb
index 5d1744606818a3efbc04e15f22cc444fb49c644d..4ea90a80a926649ba2597bf08ddad0831a8c14e8 100644
--- a/spec/helpers/groups_helper.rb
+++ b/spec/helpers/groups_helper.rb
@@ -9,7 +9,7 @@ describe GroupsHelper do
       group.avatar = File.open(avatar_file_path)
       group.save!
       expect(group_icon(group.path).to_s).
-        to match("/uploads/group/avatar/#{ group.id }/banana_sample.gif")
+        to match("/uploads/group/avatar/#{group.id}/banana_sample.gif")
     end
 
     it 'should give default avatar_icon when no avatar is present' do
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 1f2c4ee77b59fdf79c94f5295f3c68048f5136c3..ffd8ebae029726441a736585a9dd7dae48678fac 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -127,18 +127,6 @@ describe IssuesHelper do
     it { is_expected.to eq("!1, !2, or !3") }
   end
 
-  describe "#url_to_emoji" do
-    it "returns url" do
-      expect(url_to_emoji("smile")).to include("emoji/1F604.png")
-    end
-  end
-
-  describe "#emoji_list" do
-    it "returns url" do
-      expect(emoji_list).to be_kind_of(Array)
-    end
-  end
-
   describe "#note_active_class" do
     before do
       @note = create :note
@@ -153,4 +141,11 @@ describe IssuesHelper do
       expect(note_active_class(Note.all, @note.author)).to eq("active")
     end
   end
+
+  describe "#awards_sort" do
+    it "sorts a hash so thumbsup and thumbsdown are always on top" do
+      data = { "thumbsdown" => "some value", "lifter" => "some value", "thumbsup" => "some value" }
+      expect(awards_sort(data).keys).to eq(["thumbsup", "thumbsdown", "lifter"])
+    end
+  end
 end
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index 0ef1efb8bce1ee6c01105aab7be74fd62b8af73a..600e1c4e9ecf1727403f68d7cca18bb270be25d7 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -1,24 +1,57 @@
 require 'spec_helper'
 
 describe MergeRequestsHelper do
-  describe "#issues_sentence" do
+  describe 'ci_build_details_path' do
+    let(:project) { create :project }
+    let(:merge_request) { MergeRequest.new }
+    let(:ci_service) { CiService.new }
+    let(:last_commit) { Ci::Commit.new({}) }
+
+    before do
+      allow(merge_request).to receive(:source_project).and_return(project)
+      allow(merge_request).to receive(:last_commit).and_return(last_commit)
+      allow(project).to receive(:ci_service).and_return(ci_service)
+      allow(last_commit).to receive(:sha).and_return('12d65c')
+    end
+
+    it 'does not include api credentials in a link' do
+      allow(ci_service).
+        to receive(:build_page).and_return("http://secretuser:secretpass@jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c")
+      expect(helper.ci_build_details_path(merge_request)).to_not match("secret")
+    end
+  end
+
+  describe '#issues_sentence' do
     subject { issues_sentence(issues) }
     let(:issues) do
       [build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)]
     end
 
     it { is_expected.to eq('#1, #2, and #3') }
+
+    context 'for JIRA issues' do
+      let(:project) { create(:project) }
+      let(:issues) do
+        [
+          JiraIssue.new('JIRA-123', project),
+          JiraIssue.new('JIRA-456', project),
+          JiraIssue.new('FOOBAR-7890', project)
+        ]
+      end
+
+      it { is_expected.to eq('FOOBAR-7890, JIRA-123, and JIRA-456') }
+    end
   end
 
-  describe "#format_mr_branch_names" do
-    describe "within the same project" do
+  describe '#format_mr_branch_names' do
+    describe 'within the same project' do
       let(:merge_request) { create(:merge_request) }
       subject { format_mr_branch_names(merge_request) }
 
       it { is_expected.to eq([merge_request.source_branch, merge_request.target_branch]) }
     end
 
-    describe "within different projects" do
+    describe 'within different projects' do
       let(:project) { create(:project) }
       let(:fork_project) { create(:project, forked_from_project: project) }
       let(:merge_request) { create(:merge_request, source_project: fork_project, target_project: project) }
diff --git a/spec/helpers/page_layout_helper_spec.rb b/spec/helpers/page_layout_helper_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..fd7107779f6cd99b2d5f3349be12573025811062
--- /dev/null
+++ b/spec/helpers/page_layout_helper_spec.rb
@@ -0,0 +1,129 @@
+require 'rails_helper'
+
+describe PageLayoutHelper do
+  describe 'page_description' do
+    it 'defaults to value returned by page_description_default helper' do
+      allow(helper).to receive(:page_description_default).and_return('Foo')
+
+      expect(helper.page_description).to eq 'Foo'
+    end
+
+    it 'returns the last-pushed description' do
+      helper.page_description('Foo')
+      helper.page_description('Bar')
+      helper.page_description('Baz')
+
+      expect(helper.page_description).to eq 'Baz'
+    end
+
+    it 'squishes multiple newlines' do
+      helper.page_description("Foo\nBar\nBaz")
+
+      expect(helper.page_description).to eq 'Foo Bar Baz'
+    end
+
+    it 'truncates' do
+      helper.page_description <<-LOREM.strip_heredoc
+        Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
+        ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis
+        dis parturient montes, nascetur ridiculus mus. Donec quam felis,
+        ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
+        quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget,
+        arcu.
+      LOREM
+
+      expect(helper.page_description).to end_with 'quam felis,...'
+    end
+
+    it 'sanitizes all HTML' do
+      helper.page_description("<b>Bold</b> <h1>Header</h1>")
+
+      expect(helper.page_description).to eq 'Bold Header'
+    end
+  end
+
+  describe 'page_description_default' do
+    it 'uses Project description when available' do
+      project = double(description: 'Project Description')
+      helper.instance_variable_set(:@project, project)
+
+      expect(helper.page_description_default).to eq 'Project Description'
+    end
+
+    it 'uses brand_title when Project description is nil' do
+      project = double(description: nil)
+      helper.instance_variable_set(:@project, project)
+
+      expect(helper).to receive(:brand_title).and_return('Brand Title')
+      expect(helper.page_description_default).to eq 'Brand Title'
+    end
+
+    it 'falls back to brand_title' do
+      allow(helper).to receive(:brand_title).and_return('Brand Title')
+
+      expect(helper.page_description_default).to eq 'Brand Title'
+    end
+  end
+
+  describe 'page_image' do
+    it 'defaults to the GitLab logo' do
+      expect(helper.page_image).to end_with 'assets/gitlab_logo.png'
+    end
+
+    context 'with @project' do
+      it 'uses Project avatar if available' do
+        project = double(avatar_url: 'http://example.com/uploads/avatar.png')
+        helper.instance_variable_set(:@project, project)
+
+        expect(helper.page_image).to eq project.avatar_url
+      end
+
+      it 'falls back to the default' do
+        project = double(avatar_url: nil)
+        helper.instance_variable_set(:@project, project)
+
+        expect(helper.page_image).to end_with 'assets/gitlab_logo.png'
+      end
+    end
+
+    context 'with @user' do
+      it 'delegates to avatar_icon helper' do
+        user = double('User')
+        helper.instance_variable_set(:@user, user)
+
+        expect(helper).to receive(:avatar_icon).with(user)
+
+        helper.page_image
+      end
+    end
+  end
+
+  describe 'page_card_attributes' do
+    it 'raises ArgumentError when given more than two attributes' do
+      map = { foo: 'foo', bar: 'bar', baz: 'baz' }
+
+      expect { helper.page_card_attributes(map) }.
+        to raise_error(ArgumentError, /more than two attributes/)
+    end
+
+    it 'rejects blank values' do
+      map = { foo: 'foo', bar: '' }
+      helper.page_card_attributes(map)
+
+      expect(helper.page_card_attributes).to eq({ foo: 'foo' })
+    end
+  end
+
+  describe 'page_card_meta_tags' do
+    it 'returns the twitter:label and twitter:data tags' do
+      allow(helper).to receive(:page_card_attributes).and_return(foo: 'bar')
+
+      tags = helper.page_card_meta_tags
+
+      aggregate_failures do
+        expect(tags).to include %q(<meta property="twitter:label1" content="foo" />)
+        expect(tags).to include %q(<meta property="twitter:data1" content="bar" />)
+      end
+    end
+  end
+end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index f2efb528aeb6cc1c9397e7a5c9a8676286f4085d..53207767581e906005768c4e3313ea0beca51b35 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -53,6 +53,16 @@ describe ProjectsHelper do
     end
   end
 
+  describe 'user_max_access_in_project' do
+    let(:project) { create(:project) }
+    let(:user) { create(:user) }
+    before do
+      project.team.add_user(user, Gitlab::Access::MASTER)
+    end
+
+    it { expect(helper.user_max_access_in_project(user.id, project)).to eq('Master') }
+  end
+
   describe "readme_cache_key" do
     let(:project) { create(:project) }
 
diff --git a/spec/javascripts/fixtures/issues_show.html.haml b/spec/javascripts/fixtures/issues_show.html.haml
index 7e8b2a64351f176907213128c04d0f4af597ae0c..470cabeafbb90718ad18d14423ef334ac3c61894 100644
--- a/spec/javascripts/fixtures/issues_show.html.haml
+++ b/spec/javascripts/fixtures/issues_show.html.haml
@@ -1,6 +1,16 @@
-%a.btn-close
+:css
+  .hidden { display: none !important; }
 
-.issue-details
+.flash-container
+  .flash-alert
+  .flash-notice
+
+.status-box.status-box-open Open
+.status-box.status-box-closed.hidden Closed
+%a.btn-close{"href" => "http://gitlab.com/issues/6/close"} Close
+%a.btn-reopen.hidden{"href" => "http://gitlab.com/issues/6/reopen"} Reopen
+
+.detail-page-description
   .description.js-task-list-container
     .wiki
       %ul.task-list
diff --git a/spec/javascripts/fixtures/merge_requests_show.html.haml b/spec/javascripts/fixtures/merge_requests_show.html.haml
index f0c622935f849cc2680fa27b3534ec035b05c76b..8447dfdda3205e6ac5b25a6cb25da8ba7ba3bffa 100644
--- a/spec/javascripts/fixtures/merge_requests_show.html.haml
+++ b/spec/javascripts/fixtures/merge_requests_show.html.haml
@@ -1,6 +1,6 @@
 %a.btn-close
 
-.merge-request-details
+.detail-page-description
   .description.js-task-list-container
     .wiki
       %ul.task-list
diff --git a/spec/javascripts/fixtures/new_branch.html.haml b/spec/javascripts/fixtures/new_branch.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..f06629e5eccd4ef5814c12e510479c3f0648af8d
--- /dev/null
+++ b/spec/javascripts/fixtures/new_branch.html.haml
@@ -0,0 +1,4 @@
+%form.js-create-branch-form
+  %input.js-branch-name
+  .js-branch-name-error
+  %input{id: "ref"}
diff --git a/spec/javascripts/issue_spec.js.coffee b/spec/javascripts/issue_spec.js.coffee
index 268e4c68c3150f230ffa44a949fcd2320ccd384d..7e67c77886109beb2b56c8b5c481744f16af3e16 100644
--- a/spec/javascripts/issue_spec.js.coffee
+++ b/spec/javascripts/issue_spec.js.coffee
@@ -20,3 +20,89 @@ describe 'Issue', ->
         expect(req.data.issue.description).not.toBe(null)
 
       $('.js-task-list-field').trigger('tasklist:changed')
+describe 'reopen/close issue', ->
+  fixture.preload('issues_show.html')
+  beforeEach ->
+    fixture.load('issues_show.html')
+    @issue = new Issue()
+  it 'closes an issue', ->
+    $.ajax = (obj) ->
+      expect(obj.type).toBe('PUT')
+      expect(obj.url).toBe('http://gitlab.com/issues/6/close')
+      obj.success saved: true
+    
+    $btnClose = $('a.btn-close')
+    $btnReopen = $('a.btn-reopen')
+    expect($btnReopen).toBeHidden()
+    expect($btnClose.text()).toBe('Close')
+    expect(typeof $btnClose.prop('disabled')).toBe('undefined')
+
+    $btnClose.trigger('click')
+    
+    expect($btnReopen).toBeVisible()
+    expect($btnClose).toBeHidden()
+    expect($('div.status-box-closed')).toBeVisible()
+    expect($('div.status-box-open')).toBeHidden()
+
+  it 'fails to closes an issue with success:false', ->
+
+    $.ajax = (obj) ->
+      expect(obj.type).toBe('PUT')
+      expect(obj.url).toBe('http://goesnowhere.nothing/whereami')
+      obj.success saved: false
+    
+    $btnClose = $('a.btn-close')
+    $btnReopen = $('a.btn-reopen')
+    $btnClose.attr('href','http://goesnowhere.nothing/whereami')
+    expect($btnReopen).toBeHidden()
+    expect($btnClose.text()).toBe('Close')
+    expect(typeof $btnClose.prop('disabled')).toBe('undefined')
+
+    $btnClose.trigger('click')
+    
+    expect($btnReopen).toBeHidden()
+    expect($btnClose).toBeVisible()
+    expect($('div.status-box-closed')).toBeHidden()
+    expect($('div.status-box-open')).toBeVisible()
+    expect($('div.flash-alert')).toBeVisible()
+    expect($('div.flash-alert').text()).toBe('Unable to update this issue at this time.')
+
+  it 'fails to closes an issue with HTTP error', ->
+
+    $.ajax = (obj) ->
+      expect(obj.type).toBe('PUT')
+      expect(obj.url).toBe('http://goesnowhere.nothing/whereami')
+      obj.error()
+    
+    $btnClose = $('a.btn-close')
+    $btnReopen = $('a.btn-reopen')
+    $btnClose.attr('href','http://goesnowhere.nothing/whereami')
+    expect($btnReopen).toBeHidden()
+    expect($btnClose.text()).toBe('Close')
+    expect(typeof $btnClose.prop('disabled')).toBe('undefined')
+
+    $btnClose.trigger('click')
+    
+    expect($btnReopen).toBeHidden()
+    expect($btnClose).toBeVisible()
+    expect($('div.status-box-closed')).toBeHidden()
+    expect($('div.status-box-open')).toBeVisible()
+    expect($('div.flash-alert')).toBeVisible()
+    expect($('div.flash-alert').text()).toBe('Unable to update this issue at this time.')
+
+  it 'reopens an issue', ->
+    $.ajax = (obj) ->
+      expect(obj.type).toBe('PUT')
+      expect(obj.url).toBe('http://gitlab.com/issues/6/reopen')
+      obj.success saved: true
+
+    $btnClose = $('a.btn-close')
+    $btnReopen = $('a.btn-reopen')
+    expect($btnReopen.text()).toBe('Reopen')
+
+    $btnReopen.trigger('click')
+
+    expect($btnReopen).toBeHidden()
+    expect($btnClose).toBeVisible()
+    expect($('div.status-box-open')).toBeVisible()
+    expect($('div.status-box-closed')).toBeHidden()
\ No newline at end of file
diff --git a/spec/javascripts/new_branch_spec.js.coffee b/spec/javascripts/new_branch_spec.js.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..f2ce85efcdcbbaac28c81ec75867d3723f587833
--- /dev/null
+++ b/spec/javascripts/new_branch_spec.js.coffee
@@ -0,0 +1,160 @@
+#= require jquery-ui
+#= require new_branch_form
+
+describe 'Branch', ->
+  describe 'create a new branch', ->
+    fixture.preload('new_branch.html')
+
+    fillNameWith = (value) ->
+      $('.js-branch-name').val(value).trigger('blur')
+
+    expectToHaveError = (error) ->
+      expect($('.js-branch-name-error span').text()).toEqual(error)
+
+    beforeEach ->
+      fixture.load('new_branch.html')
+      $('form').on 'submit', (e) -> e.preventDefault()
+
+      @form = new NewBranchForm($('.js-create-branch-form'), [])
+
+    it "can't start with a dot", ->
+      fillNameWith '.foo'
+      expectToHaveError "can't start with '.'"
+
+    it "can't start with a slash", ->
+      fillNameWith '/foo'
+      expectToHaveError "can't start with '/'"
+
+    it "can't have two consecutive dots", ->
+      fillNameWith 'foo..bar'
+      expectToHaveError "can't contain '..'"
+
+    it "can't have spaces anywhere", ->
+      fillNameWith ' foo'
+      expectToHaveError "can't contain spaces"
+      fillNameWith 'foo bar'
+      expectToHaveError "can't contain spaces"
+      fillNameWith 'foo '
+      expectToHaveError "can't contain spaces"
+
+    it "can't have ~ anywhere", ->
+      fillNameWith '~foo'
+      expectToHaveError "can't contain '~'"
+      fillNameWith 'foo~bar'
+      expectToHaveError "can't contain '~'"
+      fillNameWith 'foo~'
+      expectToHaveError "can't contain '~'"
+
+    it "can't have tilde anwhere", ->
+      fillNameWith '~foo'
+      expectToHaveError "can't contain '~'"
+      fillNameWith 'foo~bar'
+      expectToHaveError "can't contain '~'"
+      fillNameWith 'foo~'
+      expectToHaveError "can't contain '~'"
+
+    it "can't have caret anywhere", ->
+      fillNameWith '^foo'
+      expectToHaveError "can't contain '^'"
+      fillNameWith 'foo^bar'
+      expectToHaveError "can't contain '^'"
+      fillNameWith 'foo^'
+      expectToHaveError "can't contain '^'"
+
+    it "can't have : anywhere", ->
+      fillNameWith ':foo'
+      expectToHaveError "can't contain ':'"
+      fillNameWith 'foo:bar'
+      expectToHaveError "can't contain ':'"
+      fillNameWith ':foo'
+      expectToHaveError "can't contain ':'"
+
+    it "can't have question mark anywhere", ->
+      fillNameWith '?foo'
+      expectToHaveError "can't contain '?'"
+      fillNameWith 'foo?bar'
+      expectToHaveError "can't contain '?'"
+      fillNameWith 'foo?'
+      expectToHaveError "can't contain '?'"
+
+    it "can't have asterisk anywhere", ->
+      fillNameWith '*foo'
+      expectToHaveError "can't contain '*'"
+      fillNameWith 'foo*bar'
+      expectToHaveError "can't contain '*'"
+      fillNameWith 'foo*'
+      expectToHaveError "can't contain '*'"
+
+    it "can't have open bracket anywhere", ->
+      fillNameWith '[foo'
+      expectToHaveError "can't contain '['"
+      fillNameWith 'foo[bar'
+      expectToHaveError "can't contain '['"
+      fillNameWith 'foo['
+      expectToHaveError "can't contain '['"
+
+    it "can't have a backslash anywhere", ->
+      fillNameWith '\\foo'
+      expectToHaveError "can't contain '\\'"
+      fillNameWith 'foo\\bar'
+      expectToHaveError "can't contain '\\'"
+      fillNameWith 'foo\\'
+      expectToHaveError "can't contain '\\'"
+
+    it "can't contain a sequence @{ anywhere", ->
+      fillNameWith '@{foo'
+      expectToHaveError "can't contain '@{'"
+      fillNameWith 'foo@{bar'
+      expectToHaveError "can't contain '@{'"
+      fillNameWith 'foo@{'
+      expectToHaveError "can't contain '@{'"
+
+    it "can't have consecutive slashes", ->
+      fillNameWith 'foo//bar'
+      expectToHaveError "can't contain consecutive slashes"
+
+    it "can't end with a slash", ->
+      fillNameWith 'foo/'
+      expectToHaveError "can't end in '/'"
+
+    it "can't end with a dot", ->
+      fillNameWith 'foo.'
+      expectToHaveError "can't end in '.'"
+
+    it "can't end with .lock", ->
+      fillNameWith 'foo.lock'
+      expectToHaveError "can't end in '.lock'"
+
+    it "can't be the single character @", ->
+      fillNameWith '@'
+      expectToHaveError "can't be '@'"
+
+    it "concatenates all error messages", ->
+      fillNameWith '/foo bar?~.'
+      expectToHaveError "can't start with '/', can't contain spaces, '?', '~', can't end in '.'"
+
+    it "doesn't duplicate error messages", ->
+      fillNameWith '?foo?bar?zoo?'
+      expectToHaveError "can't contain '?'"
+
+    it "removes the error message when is a valid name", ->
+      fillNameWith 'foo?bar'
+      expect($('.js-branch-name-error span').length).toEqual(1)
+      fillNameWith 'foobar'
+      expect($('.js-branch-name-error span').length).toEqual(0)
+
+    it "can have dashes anywhere", ->
+      fillNameWith '-foo-bar-zoo-'
+      expect($('.js-branch-name-error span').length).toEqual(0)
+
+    it "can have underscores anywhere", ->
+      fillNameWith '_foo_bar_zoo_'
+      expect($('.js-branch-name-error span').length).toEqual(0)
+
+    it "can have numbers anywhere", ->
+      fillNameWith '1foo2bar3zoo4'
+      expect($('.js-branch-name-error span').length).toEqual(0)
+
+    it "can be only letters", ->
+      fillNameWith 'foo'
+      expect($('.js-branch-name-error span').length).toEqual(0)
diff --git a/spec/lib/banzai/filter/user_reference_filter_spec.rb b/spec/lib/banzai/filter/user_reference_filter_spec.rb
index 3534bf977846c9ea62dbfcaa3c7eecf40c01c76e..8bdebae1841bdf6782c8ff98199ffda81bf16cf6 100644
--- a/spec/lib/banzai/filter/user_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/user_reference_filter_spec.rb
@@ -37,9 +37,22 @@ describe Banzai::Filter::UserReferenceFilter, lib: true do
         .to eq urls.namespace_project_url(project.namespace, project)
     end
 
-    it 'adds to the results hash' do
-      result = reference_pipeline_result("Hey #{reference}")
-      expect(result[:references][:user]).to eq [project.creator]
+    context "when the author is a member of the project" do
+
+      it 'adds to the results hash' do
+        result = reference_pipeline_result("Hey #{reference}", author: project.creator)
+        expect(result[:references][:user]).to eq [project.creator]
+      end
+    end
+
+    context "when the author is not a member of the project" do
+
+      let(:other_user) { create(:user) }
+
+      it "doesn't add to the results hash" do
+        result = reference_pipeline_result("Hey #{reference}", author: other_user)
+        expect(result[:references][:user]).to eq []
+      end
     end
   end
 
diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
index c90133fbf03763c89628ff322bc88692d67fddf4..d15100fc6d8c075de90677c6129d4bb0d24c8fcc 100644
--- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
+++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
 module Ci
   describe GitlabCiYamlProcessor, lib: true do
     let(:path) { 'path' }
-    
+
     describe "#builds_for_ref" do
       let(:type) { 'test' }
 
@@ -29,7 +29,7 @@ module Ci
           when: "on_success"
         })
       end
-      
+
       describe :only do
         it "does not return builds if only has another branch" do
           config = YAML.dump({
@@ -517,7 +517,7 @@ module Ci
         end.to raise_error(GitlabCiYamlProcessor::ValidationError, "Unknown parameter: extra")
       end
 
-      it "returns errors if there is no any jobs defined" do
+      it "returns errors if there are no jobs defined" do
         config = YAML.dump({ before_script: ["bundle update"] })
         expect do
           GitlabCiYamlProcessor.new(config, path)
diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb
index 3bba5e2efa2c930c4ee406232c1e9349e72162a2..1e755259dae4a4bdb85e0f1eccd5ff8ccebefa23 100644
--- a/spec/lib/gitlab/ldap/user_spec.rb
+++ b/spec/lib/gitlab/ldap/user_spec.rb
@@ -42,6 +42,21 @@ describe Gitlab::LDAP::User, lib: true do
     end
   end
 
+  describe '.find_by_uid_and_provider' do
+    it 'retrieves the correct user' do
+      special_info = {
+        name: 'John Åström',
+        email: 'john@example.com',
+        nickname: 'jastrom'
+      }
+      special_hash = OmniAuth::AuthHash.new(uid: 'CN=John Åström,CN=Users,DC=Example,DC=com', provider: 'ldapmain', info: special_info)
+      special_chars_user = described_class.new(special_hash)
+      user = special_chars_user.save
+
+      expect(described_class.find_by_uid_and_provider(special_hash.uid, special_hash.provider)).to eq user
+    end
+  end
+
   describe :find_or_create do
     it "finds the user if already existing" do
       create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain')
diff --git a/spec/lib/gitlab/metrics/delta_spec.rb b/spec/lib/gitlab/metrics/delta_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..718387cdee1785a272c5b34b53de87f09f97e4c6
--- /dev/null
+++ b/spec/lib/gitlab/metrics/delta_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::Delta do
+  let(:delta) { described_class.new }
+
+  describe '#compared_with' do
+    it 'returns the delta as a Numeric' do
+      expect(delta.compared_with(5)).to eq(5)
+    end
+
+    it 'bases the delta on a previously used value' do
+      expect(delta.compared_with(5)).to eq(5)
+      expect(delta.compared_with(15)).to eq(10)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/instrumentation_spec.rb b/spec/lib/gitlab/metrics/instrumentation_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a7eab9d11cc76f531a5efe03b1a739c56455fc2a
--- /dev/null
+++ b/spec/lib/gitlab/metrics/instrumentation_spec.rb
@@ -0,0 +1,234 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::Instrumentation do
+  let(:transaction) { Gitlab::Metrics::Transaction.new }
+
+  before do
+    @dummy = Class.new do
+      def self.foo(text = 'foo')
+        text
+      end
+
+      def bar(text = 'bar')
+        text
+      end
+    end
+
+    allow(@dummy).to receive(:name).and_return('Dummy')
+  end
+
+  describe '.configure' do
+    it 'yields self' do
+      described_class.configure do |c|
+        expect(c).to eq(described_class)
+      end
+    end
+  end
+
+  describe '.instrument_method' do
+    describe 'with metrics enabled' do
+      before do
+        allow(Gitlab::Metrics).to receive(:enabled?).and_return(true)
+
+        described_class.instrument_method(@dummy, :foo)
+      end
+
+      it 'renames the original method' do
+        expect(@dummy).to respond_to(:_original_foo)
+      end
+
+      it 'calls the instrumented method with the correct arguments' do
+        expect(@dummy.foo).to eq('foo')
+      end
+
+      it 'tracks the call duration upon calling the method' do
+        allow(Gitlab::Metrics).to receive(:method_call_threshold).
+          and_return(0)
+
+        allow(described_class).to receive(:transaction).
+          and_return(transaction)
+
+        expect(transaction).to receive(:add_metric).
+          with(described_class::SERIES, an_instance_of(Hash),
+               method: 'Dummy.foo')
+
+        @dummy.foo
+      end
+
+      it 'does not track method calls below a given duration threshold' do
+        allow(Gitlab::Metrics).to receive(:method_call_threshold).
+          and_return(100)
+
+        expect(transaction).to_not receive(:add_metric)
+
+        @dummy.foo
+      end
+    end
+
+    describe 'with metrics disabled' do
+      before do
+        allow(Gitlab::Metrics).to receive(:enabled?).and_return(false)
+      end
+
+      it 'does not instrument the method' do
+        described_class.instrument_method(@dummy, :foo)
+
+        expect(@dummy).to_not respond_to(:_original_foo)
+      end
+    end
+  end
+
+  describe '.instrument_instance_method' do
+    describe 'with metrics enabled' do
+      before do
+        allow(Gitlab::Metrics).to receive(:enabled?).and_return(true)
+
+        described_class.
+          instrument_instance_method(@dummy, :bar)
+      end
+
+      it 'renames the original method' do
+        expect(@dummy.method_defined?(:_original_bar)).to eq(true)
+      end
+
+      it 'calls the instrumented method with the correct arguments' do
+        expect(@dummy.new.bar).to eq('bar')
+      end
+
+      it 'tracks the call duration upon calling the method' do
+        allow(Gitlab::Metrics).to receive(:method_call_threshold).
+          and_return(0)
+
+        allow(described_class).to receive(:transaction).
+          and_return(transaction)
+
+        expect(transaction).to receive(:add_metric).
+          with(described_class::SERIES, an_instance_of(Hash),
+               method: 'Dummy#bar')
+
+        @dummy.new.bar
+      end
+
+      it 'does not track method calls below a given duration threshold' do
+        allow(Gitlab::Metrics).to receive(:method_call_threshold).
+          and_return(100)
+
+        expect(transaction).to_not receive(:add_metric)
+
+        @dummy.new.bar
+      end
+    end
+
+    describe 'with metrics disabled' do
+      before do
+        allow(Gitlab::Metrics).to receive(:enabled?).and_return(false)
+      end
+
+      it 'does not instrument the method' do
+        described_class.
+          instrument_instance_method(@dummy, :bar)
+
+        expect(@dummy.method_defined?(:_original_bar)).to eq(false)
+      end
+    end
+  end
+
+  describe '.instrument_class_hierarchy' do
+    before do
+      allow(Gitlab::Metrics).to receive(:enabled?).and_return(true)
+
+      @child1 = Class.new(@dummy) do
+        def self.child1_foo; end
+        def child1_bar; end
+      end
+
+      @child2 = Class.new(@child1) do
+        def self.child2_foo; end
+        def child2_bar; end
+      end
+    end
+
+    it 'recursively instruments a class hierarchy' do
+      described_class.instrument_class_hierarchy(@dummy)
+
+      expect(@child1).to respond_to(:_original_child1_foo)
+      expect(@child2).to respond_to(:_original_child2_foo)
+
+      expect(@child1.method_defined?(:_original_child1_bar)).to eq(true)
+      expect(@child2.method_defined?(:_original_child2_bar)).to eq(true)
+    end
+
+    it 'does not instrument the root module' do
+      described_class.instrument_class_hierarchy(@dummy)
+
+      expect(@dummy).to_not respond_to(:_original_foo)
+      expect(@dummy.method_defined?(:_original_bar)).to eq(false)
+    end
+  end
+
+  describe '.instrument_methods' do
+    before do
+      allow(Gitlab::Metrics).to receive(:enabled?).and_return(true)
+    end
+
+    it 'instruments all public class methods' do
+      described_class.instrument_methods(@dummy)
+
+      expect(@dummy).to respond_to(:_original_foo)
+    end
+
+    it 'only instruments methods directly defined in the module' do
+      mod = Module.new do
+        def kittens
+        end
+      end
+
+      @dummy.extend(mod)
+
+      described_class.instrument_methods(@dummy)
+
+      expect(@dummy).to_not respond_to(:_original_kittens)
+    end
+
+    it 'can take a block to determine if a method should be instrumented' do
+      described_class.instrument_methods(@dummy) do
+        false
+      end
+
+      expect(@dummy).to_not respond_to(:_original_foo)
+    end
+  end
+
+  describe '.instrument_instance_methods' do
+    before do
+      allow(Gitlab::Metrics).to receive(:enabled?).and_return(true)
+    end
+
+    it 'instruments all public instance methods' do
+      described_class.instrument_instance_methods(@dummy)
+
+      expect(@dummy.method_defined?(:_original_bar)).to eq(true)
+    end
+
+    it 'only instruments methods directly defined in the module' do
+      mod = Module.new do
+        def kittens
+        end
+      end
+
+      @dummy.include(mod)
+
+      described_class.instrument_instance_methods(@dummy)
+
+      expect(@dummy.method_defined?(:_original_kittens)).to eq(false)
+    end
+
+    it 'can take a block to determine if a method should be instrumented' do
+      described_class.instrument_instance_methods(@dummy) do
+        false
+      end
+
+      expect(@dummy.method_defined?(:_original_bar)).to eq(false)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/metric_spec.rb b/spec/lib/gitlab/metrics/metric_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aa76315c79ce48d5379a883781ff37ef48a21eb0
--- /dev/null
+++ b/spec/lib/gitlab/metrics/metric_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::Metric do
+  let(:metric) do
+    described_class.new('foo', { number: 10 }, { host: 'localtoast' })
+  end
+
+  describe '#series' do
+    subject { metric.series }
+
+    it { is_expected.to eq('foo') }
+  end
+
+  describe '#values' do
+    subject { metric.values }
+
+    it { is_expected.to eq({ number: 10 }) }
+  end
+
+  describe '#tags' do
+    subject { metric.tags }
+
+    it { is_expected.to eq({ host: 'localtoast' }) }
+  end
+
+  describe '#to_hash' do
+    it 'returns a Hash' do
+      expect(metric.to_hash).to be_an_instance_of(Hash)
+    end
+
+    describe 'the returned Hash' do
+      let(:hash) { metric.to_hash }
+
+      it 'includes the series' do
+        expect(hash[:series]).to eq('foo')
+      end
+
+      it 'includes the tags' do
+        expect(hash[:tags]).to be_an_instance_of(Hash)
+
+        expect(hash[:tags][:hostname]).to be_an_instance_of(String)
+        expect(hash[:tags][:process_type]).to be_an_instance_of(String)
+      end
+
+      it 'includes the values' do
+        expect(hash[:values]).to eq({ number: 10 })
+      end
+
+      it 'includes the timestamp' do
+        expect(hash[:timestamp]).to be_an_instance_of(Fixnum)
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/obfuscated_sql_spec.rb b/spec/lib/gitlab/metrics/obfuscated_sql_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2b681c9fe347b2a4f15026c84fd6240fda25795f
--- /dev/null
+++ b/spec/lib/gitlab/metrics/obfuscated_sql_spec.rb
@@ -0,0 +1,93 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::ObfuscatedSQL do
+  describe '#to_s' do
+    it 'replaces newlines with a space' do
+      sql = described_class.new("SELECT x\nFROM y")
+
+      expect(sql.to_s).to eq('SELECT x FROM y')
+    end
+
+    describe 'using single values' do
+      it 'replaces a single integer' do
+        sql = described_class.new('SELECT x FROM y WHERE a = 10')
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE a = ?')
+      end
+
+      it 'replaces a single float' do
+        sql = described_class.new('SELECT x FROM y WHERE a = 10.5')
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE a = ?')
+      end
+
+      it 'replaces a single quoted string' do
+        sql = described_class.new("SELECT x FROM y WHERE a = 'foo'")
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE a = ?')
+      end
+
+      if Gitlab::Database.mysql?
+        it 'replaces a double quoted string' do
+          sql = described_class.new('SELECT x FROM y WHERE a = "foo"')
+
+          expect(sql.to_s).to eq('SELECT x FROM y WHERE a = ?')
+        end
+      end
+
+      it 'replaces a single regular expression' do
+        sql = described_class.new('SELECT x FROM y WHERE a = /foo/')
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE a = ?')
+      end
+
+      it 'replaces regular expressions using escaped slashes' do
+        sql = described_class.new('SELECT x FROM y WHERE a = /foo\/bar/')
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE a = ?')
+      end
+    end
+
+    describe 'using consecutive values' do
+      it 'replaces multiple integers' do
+        sql = described_class.new('SELECT x FROM y WHERE z IN (10, 20, 30)')
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE z IN (3 values)')
+      end
+
+      it 'replaces multiple floats' do
+        sql = described_class.new('SELECT x FROM y WHERE z IN (1.5, 2.5, 3.5)')
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE z IN (3 values)')
+      end
+
+      it 'replaces multiple single quoted strings' do
+        sql = described_class.new("SELECT x FROM y WHERE z IN ('foo', 'bar')")
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE z IN (2 values)')
+      end
+
+      if Gitlab::Database.mysql?
+        it 'replaces multiple double quoted strings' do
+          sql = described_class.new('SELECT x FROM y WHERE z IN ("foo", "bar")')
+
+          expect(sql.to_s).to eq('SELECT x FROM y WHERE z IN (2 values)')
+        end
+      end
+
+      it 'replaces multiple regular expressions' do
+        sql = described_class.new('SELECT x FROM y WHERE z IN (/foo/, /bar/)')
+
+        expect(sql.to_s).to eq('SELECT x FROM y WHERE z IN (2 values)')
+      end
+    end
+
+    if Gitlab::Database.postgresql?
+      it 'replaces double quotes' do
+        sql = described_class.new('SELECT "x" FROM "y"')
+
+        expect(sql.to_s).to eq('SELECT x FROM y')
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/rack_middleware_spec.rb b/spec/lib/gitlab/metrics/rack_middleware_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a143fe4cfcd68a8f4de75b6ae85b393125025a9f
--- /dev/null
+++ b/spec/lib/gitlab/metrics/rack_middleware_spec.rb
@@ -0,0 +1,63 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::RackMiddleware do
+  let(:app) { double(:app) }
+
+  let(:middleware) { described_class.new(app) }
+
+  let(:env) { { 'REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/foo' } }
+
+  describe '#call' do
+    before do
+      expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:finish)
+    end
+
+    it 'tracks a transaction' do
+      expect(app).to receive(:call).with(env).and_return('yay')
+
+      expect(middleware.call(env)).to eq('yay')
+    end
+
+    it 'tags a transaction with the name and action of a controller' do
+      klass      = double(:klass, name: 'TestController')
+      controller = double(:controller, class: klass, action_name: 'show')
+
+      env['action_controller.instance'] = controller
+
+      allow(app).to receive(:call).with(env)
+
+      expect(middleware).to receive(:tag_controller).
+        with(an_instance_of(Gitlab::Metrics::Transaction), env)
+
+      middleware.call(env)
+    end
+  end
+
+  describe '#transaction_from_env' do
+    let(:transaction) { middleware.transaction_from_env(env) }
+
+    it 'returns a Transaction' do
+      expect(transaction).to be_an_instance_of(Gitlab::Metrics::Transaction)
+    end
+
+    it 'tags the transaction with the request method and URI' do
+      expect(transaction.tags[:request_method]).to eq('GET')
+      expect(transaction.tags[:request_uri]).to eq('/foo')
+    end
+  end
+
+  describe '#tag_controller' do
+    let(:transaction) { middleware.transaction_from_env(env) }
+
+    it 'tags a transaction with the name and action of a controller' do
+      klass      = double(:klass, name: 'TestController')
+      controller = double(:controller, class: klass, action_name: 'show')
+
+      env['action_controller.instance'] = controller
+
+      middleware.tag_controller(transaction, env)
+
+      expect(transaction.tags[:action]).to eq('TestController#show')
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/sampler_spec.rb b/spec/lib/gitlab/metrics/sampler_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..51a941c48cd7ea01385901f3f099836e154d0d27
--- /dev/null
+++ b/spec/lib/gitlab/metrics/sampler_spec.rb
@@ -0,0 +1,97 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::Sampler do
+  let(:sampler) { described_class.new(5) }
+
+  after do
+    Allocations.stop if Gitlab::Metrics.mri?
+  end
+
+  describe '#start' do
+    it 'gathers a sample at a given interval' do
+      expect(sampler).to receive(:sleep).with(5)
+      expect(sampler).to receive(:sample)
+      expect(sampler).to receive(:loop).and_yield
+
+      sampler.start.join
+    end
+  end
+
+  describe '#sample' do
+    it 'samples various statistics' do
+      expect(sampler).to receive(:sample_memory_usage)
+      expect(sampler).to receive(:sample_file_descriptors)
+      expect(sampler).to receive(:sample_objects)
+      expect(sampler).to receive(:sample_gc)
+      expect(sampler).to receive(:flush)
+
+      sampler.sample
+    end
+
+    it 'clears any GC profiles' do
+      expect(sampler).to receive(:flush)
+      expect(GC::Profiler).to receive(:clear)
+
+      sampler.sample
+    end
+  end
+
+  describe '#flush' do
+    it 'schedules the metrics using Sidekiq' do
+      expect(Gitlab::Metrics).to receive(:submit_metrics).
+        with([an_instance_of(Hash)])
+
+      sampler.sample_memory_usage
+      sampler.flush
+    end
+  end
+
+  describe '#sample_memory_usage' do
+    it 'adds a metric containing the memory usage' do
+      expect(Gitlab::Metrics::System).to receive(:memory_usage).
+        and_return(9000)
+
+      expect(Gitlab::Metrics::Metric).to receive(:new).
+        with('memory_usage', value: 9000).
+        and_call_original
+
+      sampler.sample_memory_usage
+    end
+  end
+
+  describe '#sample_file_descriptors' do
+    it 'adds a metric containing the amount of open file descriptors' do
+      expect(Gitlab::Metrics::System).to receive(:file_descriptor_count).
+        and_return(4)
+
+      expect(Gitlab::Metrics::Metric).to receive(:new).
+        with('file_descriptors', value: 4).
+        and_call_original
+
+      sampler.sample_file_descriptors
+    end
+  end
+
+  describe '#sample_objects' do
+    it 'adds a metric containing the amount of allocated objects' do
+      expect(Gitlab::Metrics::Metric).to receive(:new).
+        with('object_counts', an_instance_of(Hash), an_instance_of(Hash)).
+        at_least(:once).
+        and_call_original
+
+      sampler.sample_objects
+    end
+  end
+
+  describe '#sample_gc' do
+    it 'adds a metric containing garbage collection statistics' do
+      expect(GC::Profiler).to receive(:total_time).and_return(0.24)
+
+      expect(Gitlab::Metrics::Metric).to receive(:new).
+        with('gc_statistics', an_instance_of(Hash)).
+        and_call_original
+
+      sampler.sample_gc
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb b/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5882e7d81c7c55059a6d71836ae937c6ecbeaede
--- /dev/null
+++ b/spec/lib/gitlab/metrics/sidekiq_middleware_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::SidekiqMiddleware do
+  let(:middleware) { described_class.new }
+
+  describe '#call' do
+    it 'tracks the transaction' do
+      worker = Class.new.new
+
+      expect_any_instance_of(Gitlab::Metrics::Transaction).to receive(:finish)
+
+      middleware.call(worker, 'test', :test) { nil }
+    end
+  end
+
+  describe '#tag_worker' do
+    it 'adds the worker class and action to the transaction' do
+      trans  = Gitlab::Metrics::Transaction.new
+      worker = double(:worker, class: double(:class, name: 'TestWorker'))
+
+      expect(trans).to receive(:add_tag).with(:action, 'TestWorker#perform')
+
+      middleware.tag_worker(trans, worker)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/subscribers/action_view_spec.rb b/spec/lib/gitlab/metrics/subscribers/action_view_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c6cd584663f26344861d6a20897e5a4f7b3c5dfe
--- /dev/null
+++ b/spec/lib/gitlab/metrics/subscribers/action_view_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::Subscribers::ActionView do
+  let(:transaction) { Gitlab::Metrics::Transaction.new }
+
+  let(:subscriber) { described_class.new }
+
+  let(:event) do
+    root = Rails.root.to_s
+
+    double(:event, duration: 2.1,
+                   payload:  { identifier: "#{root}/app/views/x.html.haml" })
+  end
+
+  before do
+    allow(subscriber).to receive(:current_transaction).and_return(transaction)
+
+    allow(Gitlab::Metrics).to receive(:last_relative_application_frame).
+      and_return(['app/views/x.html.haml', 4])
+  end
+
+  describe '#render_template' do
+    it 'tracks rendering of a template' do
+      values = { duration: 2.1 }
+      tags   = {
+        view: 'app/views/x.html.haml',
+        file: 'app/views/x.html.haml',
+        line: 4
+      }
+
+      expect(transaction).to receive(:add_metric).
+        with(described_class::SERIES, values, tags)
+
+      subscriber.render_template(event)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..05b6cc147162c76eb9533dd991aa4fa731be5f5c
--- /dev/null
+++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::Subscribers::ActiveRecord do
+  let(:transaction) { Gitlab::Metrics::Transaction.new }
+
+  let(:subscriber) { described_class.new }
+
+  let(:event) do
+    double(:event, duration: 0.2,
+                   payload:  { sql: 'SELECT * FROM users WHERE id = 10' })
+  end
+
+  before do
+    allow(subscriber).to receive(:current_transaction).and_return(transaction)
+
+    allow(Gitlab::Metrics).to receive(:last_relative_application_frame).
+      and_return(['app/models/foo.rb', 4])
+  end
+
+  describe '#sql' do
+    it 'tracks the execution of a SQL query' do
+      sql    = 'SELECT * FROM users WHERE id = ?'
+      values = { duration: 0.2 }
+      tags   = { sql: sql, file: 'app/models/foo.rb', line: 4 }
+
+      expect(transaction).to receive(:add_metric).
+        with(described_class::SERIES, values, tags)
+
+      subscriber.sql(event)
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/system_spec.rb b/spec/lib/gitlab/metrics/system_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f8c1d956ca1fb9e0c5cb41d2e7e2b6b7e217dfbd
--- /dev/null
+++ b/spec/lib/gitlab/metrics/system_spec.rb
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::System do
+  if File.exist?('/proc')
+    describe '.memory_usage' do
+      it "returns the process' memory usage in bytes" do
+        expect(described_class.memory_usage).to be > 0
+      end
+    end
+
+    describe '.file_descriptor_count' do
+      it 'returns the amount of open file descriptors' do
+        expect(described_class.file_descriptor_count).to be > 0
+      end
+    end
+  else
+    describe '.memory_usage' do
+      it 'returns 0.0' do
+        expect(described_class.memory_usage).to eq(0.0)
+      end
+    end
+
+    describe '.file_descriptor_count' do
+      it 'returns 0' do
+        expect(described_class.file_descriptor_count).to eq(0)
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics/transaction_spec.rb b/spec/lib/gitlab/metrics/transaction_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6862fc9e2d19d1939cca2b68478f4fda12f58512
--- /dev/null
+++ b/spec/lib/gitlab/metrics/transaction_spec.rb
@@ -0,0 +1,77 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics::Transaction do
+  let(:transaction) { described_class.new }
+
+  describe '#duration' do
+    it 'returns the duration of a transaction in seconds' do
+      transaction.run { sleep(0.5) }
+
+      expect(transaction.duration).to be >= 0.5
+    end
+  end
+
+  describe '#run' do
+    it 'yields the supplied block' do
+      expect { |b| transaction.run(&b) }.to yield_control
+    end
+
+    it 'stores the transaction in the current thread' do
+      transaction.run do
+        expect(Thread.current[described_class::THREAD_KEY]).to eq(transaction)
+      end
+    end
+
+    it 'removes the transaction from the current thread upon completion' do
+      transaction.run { }
+
+      expect(Thread.current[described_class::THREAD_KEY]).to be_nil
+    end
+  end
+
+  describe '#add_metric' do
+    it 'adds a metric tagged with the transaction UUID' do
+      expect(Gitlab::Metrics::Metric).to receive(:new).
+        with('foo', { number: 10 }, { transaction_id: transaction.uuid })
+
+      transaction.add_metric('foo', number: 10)
+    end
+  end
+
+  describe '#add_tag' do
+    it 'adds a tag' do
+      transaction.add_tag(:foo, 'bar')
+
+      expect(transaction.tags).to eq({ foo: 'bar' })
+    end
+  end
+
+  describe '#finish' do
+    it 'tracks the transaction details and submits them to Sidekiq' do
+      expect(transaction).to receive(:track_self)
+      expect(transaction).to receive(:submit)
+
+      transaction.finish
+    end
+  end
+
+  describe '#track_self' do
+    it 'adds a metric for the transaction itself' do
+      expect(transaction).to receive(:add_metric).
+        with(described_class::SERIES, { duration: transaction.duration }, {})
+
+      transaction.track_self
+    end
+  end
+
+  describe '#submit' do
+    it 'submits the metrics to Sidekiq' do
+      transaction.track_self
+
+      expect(Gitlab::Metrics).to receive(:submit_metrics).
+        with([an_instance_of(Hash)])
+
+      transaction.submit
+    end
+  end
+end
diff --git a/spec/lib/gitlab/metrics_spec.rb b/spec/lib/gitlab/metrics_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..6c0682cac4dcdd439e547d4cf7f42caa7c16a9db
--- /dev/null
+++ b/spec/lib/gitlab/metrics_spec.rb
@@ -0,0 +1,84 @@
+require 'spec_helper'
+
+describe Gitlab::Metrics do
+  describe '.pool_size' do
+    it 'returns a Fixnum' do
+      expect(described_class.pool_size).to be_an_instance_of(Fixnum)
+    end
+  end
+
+  describe '.timeout' do
+    it 'returns a Fixnum' do
+      expect(described_class.timeout).to be_an_instance_of(Fixnum)
+    end
+  end
+
+  describe '.enabled?' do
+    it 'returns a boolean' do
+      expect([true, false].include?(described_class.enabled?)).to eq(true)
+    end
+  end
+
+  describe '.hostname' do
+    it 'returns a String containing the hostname' do
+      expect(described_class.hostname).to eq(Socket.gethostname)
+    end
+  end
+
+  describe '.last_relative_application_frame' do
+    it 'returns an Array containing a file path and line number' do
+      file, line = described_class.last_relative_application_frame
+
+      expect(line).to eq(__LINE__ - 2)
+      expect(file).to eq('spec/lib/gitlab/metrics_spec.rb')
+    end
+  end
+
+  describe '#submit_metrics' do
+    it 'prepares and writes the metrics to InfluxDB' do
+      connection = double(:connection)
+      pool       = double(:pool)
+
+      expect(pool).to receive(:with).and_yield(connection)
+      expect(connection).to receive(:write_points).with(an_instance_of(Array))
+      expect(Gitlab::Metrics).to receive(:pool).and_return(pool)
+
+      described_class.submit_metrics([{ 'series' => 'kittens', 'tags' => {} }])
+    end
+  end
+
+  describe '#prepare_metrics' do
+    it 'returns a Hash with the keys as Symbols' do
+      metrics = described_class.
+        prepare_metrics([{ 'values' => {}, 'tags' => {} }])
+
+      expect(metrics).to eq([{ values: {}, tags: {} }])
+    end
+
+    it 'escapes tag values' do
+      metrics = described_class.prepare_metrics([
+        { 'values' => {}, 'tags' => { 'foo' => 'bar=' } }
+      ])
+
+      expect(metrics).to eq([{ values: {}, tags: { 'foo' => 'bar\\=' } }])
+    end
+
+    it 'drops empty tags' do
+      metrics = described_class.prepare_metrics([
+        { 'values' => {}, 'tags' => { 'cats' => '', 'dogs' => nil } }
+      ])
+
+      expect(metrics).to eq([{ values: {}, tags: {} }])
+    end
+  end
+
+  describe '#escape_value' do
+    it 'escapes an equals sign' do
+      expect(described_class.escape_value('foo=')).to eq('foo\\=')
+    end
+
+    it 'casts values to Strings' do
+      expect(described_class.escape_value(10)).to eq('10')
+    end
+  end
+end
diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb
index 66dc5d4911d8cd064e455e03ff3099c1646b71d5..7d963795e17b48265d15c55ac92d4b4598716409 100644
--- a/spec/lib/gitlab/reference_extractor_spec.rb
+++ b/spec/lib/gitlab/reference_extractor_spec.rb
@@ -97,6 +97,16 @@ describe Gitlab::ReferenceExtractor, lib: true do
     expect(extracted.first.commit_to).to eq commit
   end
 
+  context 'with an external issue tracker' do
+    let(:project) { create(:jira_project) }
+    subject { described_class.new(project, project.creator) }
+
+    it 'returns JIRA issues for a JIRA-integrated project' do
+      subject.analyze('JIRA-123 and FOOBAR-4567')
+      expect(subject.issues).to eq [JiraIssue.new('JIRA-123', project), JiraIssue.new('FOOBAR-4567', project)]
+    end
+  end
+
   context 'with a project with an underscore' do
     let(:other_project) { create(:project, path: 'test_project') }
     let(:issue) { create(:issue, project: other_project) }
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 5f64453a35f29132faf5640052b25314fcdef9e4..35d8220ae548ebce18ae2547f72352eada10e5f8 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -27,6 +27,7 @@
 #  admin_notification_email     :string(255)
 #  shared_runners_enabled       :boolean          default(TRUE), not null
 #  max_artifacts_size           :integer          default(100), not null
+#  runners_registration_token   :string(255)
 #
 
 require 'spec_helper'
diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb
index 96b6f1dbca6b24e365a367bdef7acfc0e8cb03d4..1c22e3cb7c405363d30a575ce90178341f345da8 100644
--- a/spec/models/build_spec.rb
+++ b/spec/models/build_spec.rb
@@ -189,6 +189,12 @@ describe Ci::Build, models: true do
 
       it { is_expected.to eq(98.29) }
     end
+
+    context 'using a regex capture' do
+      subject { build.extract_coverage('TOTAL      9926   3489    65%', 'TOTAL\s+\d+\s+\d+\s+(\d{1,3}\%)') }
+
+      it { is_expected.to eq(65) }
+    end
   end
 
   describe :variables do
@@ -390,4 +396,68 @@ describe Ci::Build, models: true do
     it { is_expected.to include('gitlab-ci-token') }
     it { is_expected.to include(project.web_url[7..-1]) }
   end
+
+  def create_mr(build, commit, factory: :merge_request, created_at: Time.now)
+    FactoryGirl.create(factory,
+                       source_project_id: commit.gl_project_id,
+                       target_project_id: commit.gl_project_id,
+                       source_branch: build.ref,
+                       created_at: created_at)
+  end
+
+  describe :merge_request do
+    context 'when a MR has a reference to the commit' do
+      before do
+        @merge_request = create_mr(build, commit, factory: :merge_request)
+
+        commits = [double(id: commit.sha)]
+        allow(@merge_request).to receive(:commits).and_return(commits)
+        allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request])
+      end
+
+      it 'returns the single associated MR' do
+        expect(build.merge_request.id).to eq(@merge_request.id)
+      end
+    end
+
+    context 'when there is not a MR referencing the commit' do
+      it 'returns nil' do
+        expect(build.merge_request).to be_nil
+      end
+    end
+
+    context 'when more than one MR have a reference to the commit' do
+      before do
+        @merge_request = create_mr(build, commit, factory: :merge_request)
+        @merge_request.close!
+        @merge_request2 = create_mr(build, commit, factory: :merge_request)
+
+        commits = [double(id: commit.sha)]
+        allow(@merge_request).to receive(:commits).and_return(commits)
+        allow(@merge_request2).to receive(:commits).and_return(commits)
+        allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request, @merge_request2])
+      end
+
+      it 'returns the first MR' do
+        expect(build.merge_request.id).to eq(@merge_request.id)
+      end
+    end
+
+    context 'when a Build is created after the MR' do
+      before do
+        @merge_request = create_mr(build, commit, factory: :merge_request_with_diffs)
+        commit2 = FactoryGirl.create :ci_commit, project: project
+        @build2 = FactoryGirl.create :ci_build, commit: commit2
+
+        commits = [double(id: commit.sha), double(id: commit2.sha)]
+        allow(@merge_request).to receive(:commits).and_return(commits)
+        allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request])
+      end
+
+      it 'returns the current MR' do
+        expect(@build2.merge_request.id).to eq(@merge_request.id)
+      end
+    end
+
+  end
 end
diff --git a/spec/models/ci/commit_spec.rb b/spec/models/ci/commit_spec.rb
index ac61c8fb525ff406e47b0bcd01a6a416e9a3d95f..b193e16e7f8dfee872048fe37dc65f62e537de2e 100644
--- a/spec/models/ci/commit_spec.rb
+++ b/spec/models/ci/commit_spec.rb
@@ -37,14 +37,14 @@ describe Ci::Commit, models: true do
 
     it 'returns ordered list of commits' do
       commit1 = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, project: project
-      commit2 = FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, project: project
+      commit2 = FactoryGirl.create :ci_commit, committed_at: 2.hours.ago, project: project
       expect(project.ci_commits.ordered).to eq([commit2, commit1])
     end
 
     it 'returns commits ordered by committed_at and id, with nulls last' do
       commit1 = FactoryGirl.create :ci_commit, committed_at: 1.hour.ago, project: project
       commit2 = FactoryGirl.create :ci_commit, committed_at: nil, project: project
-      commit3 = FactoryGirl.create :ci_commit, committed_at: 2.hour.ago, project: project
+      commit3 = FactoryGirl.create :ci_commit, committed_at: 2.hours.ago, project: project
       commit4 = FactoryGirl.create :ci_commit, committed_at: nil, project: project
       expect(project.ci_commits.ordered).to eq([commit2, commit4, commit3, commit1])
     end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 0f13c4410cdc482943c7d9e17c25b804e81acb57..021d62cdf0ce324711e69333ece64ed84f2484c8 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -81,4 +81,36 @@ describe Issue, "Issuable" do
       expect(hook_data[:object_attributes]).to eq(issue.hook_attrs)
     end
   end
+
+  describe '#card_attributes' do
+    it 'includes the author name' do
+      allow(issue).to receive(:author).and_return(double(name: 'Robert'))
+      allow(issue).to receive(:assignee).and_return(nil)
+
+      expect(issue.card_attributes).
+        to eq({ 'Author' => 'Robert', 'Assignee' => nil })
+    end
+
+    it 'includes the assignee name' do
+      allow(issue).to receive(:author).and_return(double(name: 'Robert'))
+      allow(issue).to receive(:assignee).and_return(double(name: 'Douwe'))
+
+      expect(issue.card_attributes).
+        to eq({ 'Author' => 'Robert', 'Assignee' => 'Douwe' })
+    end
+  end
+
+  describe "votes" do
+    before do
+      author = create :user
+      project = create :empty_project
+      issue.notes.awards.create!(note: "thumbsup", author: author, project: project)
+      issue.notes.awards.create!(note: "thumbsdown", author: author, project: project)
+    end
+
+    it "returns correct values" do
+      expect(issue.upvotes).to eq(1)
+      expect(issue.downvotes).to eq(1)
+    end
+  end
 end
diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb
index 6179882e93591f4556ddc9062b5c3ebba2dd14c0..20f0c561e44b16e3f9970f387ecc0a8d57e14fd8 100644
--- a/spec/models/concerns/mentionable_spec.rb
+++ b/spec/models/concerns/mentionable_spec.rb
@@ -1,5 +1,22 @@
 require 'spec_helper'
 
+describe Mentionable do
+  include Mentionable
+
+  def author
+    nil
+  end
+
+  describe :references do
+    let(:project) { create(:project) }
+
+    it 'excludes JIRA references' do
+      allow(project).to receive_messages(jira_tracker?: true)
+      expect(referenced_mentionables(project, 'JIRA-123')).to be_empty
+    end
+  end
+end
+
 describe Issue, "Mentionable" do
   describe '#mentioned_users' do
     let!(:user) { create(:user, username: 'stranger') }
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index a9b0b64e5deccaa9663f8a701936de37133f70a1..30c0a04b84045b315094c1fb9a9b380de70f4a53 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -2,7 +2,8 @@ require 'spec_helper'
 
 shared_examples 'TokenAuthenticatable' do
   describe 'dynamically defined methods' do
-    it { expect(described_class).to be_private_method_defined(:generate_token_for) }
+    it { expect(described_class).to be_private_method_defined(:generate_token) }
+    it { expect(described_class).to be_private_method_defined(:write_new_token) }
     it { expect(described_class).to respond_to("find_by_#{token_field}") }
     it { is_expected.to respond_to("ensure_#{token_field}") }
     it { is_expected.to respond_to("reset_#{token_field}!") }
@@ -24,11 +25,11 @@ describe ApplicationSetting, 'TokenAuthenticatable' do
   it_behaves_like 'TokenAuthenticatable'
 
   describe 'generating new token' do
-    subject { described_class.new }
-    let(:token) { subject.send(token_field) }
-
     context 'token is not generated yet' do
-      it { expect(token).to be nil }
+      describe 'token field accessor' do
+        subject { described_class.new.send(token_field) }
+        it { is_expected.to_not be_blank }
+      end
 
       describe 'ensured token' do
         subject { described_class.new.send("ensure_#{token_field}") }
@@ -36,11 +37,21 @@ describe ApplicationSetting, 'TokenAuthenticatable' do
         it { is_expected.to be_a String }
         it { is_expected.to_not be_blank }
       end
+
+      describe 'ensured! token' do
+        subject { described_class.new.send("ensure_#{token_field}!") }
+
+        it 'should persist new token' do
+          expect(subject).to eq described_class.current[token_field]
+        end
+      end
     end
 
     context 'token is generated' do
       before { subject.send("reset_#{token_field}!") }
-      it { expect(token).to be_a String }
+      it 'persists a new token 'do
+        expect(subject.send(:read_attribute, token_field)).to be_a String
+      end
     end
   end
 
diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb
index ba03e6aabd0352ecae60e036edd3e03b895b016a..197c99cd007ea9c80f30ef2474210b85d1d57907 100644
--- a/spec/models/global_milestone_spec.rb
+++ b/spec/models/global_milestone_spec.rb
@@ -62,4 +62,14 @@ describe GlobalMilestone, models: true do
       expect(@global_milestone.milestones.count).to eq(3)
     end
   end
+
+  describe :safe_title do
+    let(:milestone) { create(:milestone, title: "git / test", project: project1) }
+
+    it 'should strip out slashes and spaces' do
+      global_milestone = GlobalMilestone.new(milestone.title, [milestone])
+
+      expect(global_milestone.safe_title).to eq('git-test')
+    end
+  end
 end
diff --git a/spec/models/jira_issue_spec.rb b/spec/models/jira_issue_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1634265b439d1c18e8fd5ae4f010aa91cdc83cf1
--- /dev/null
+++ b/spec/models/jira_issue_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe JiraIssue do
+  let(:project) { create(:project) }
+  subject { JiraIssue.new('JIRA-123', project) }
+
+  describe 'id' do
+    subject { super().id }
+    it { is_expected.to eq('JIRA-123') }
+  end
+
+  describe 'iid' do
+    subject { super().iid }
+    it { is_expected.to eq('JIRA-123') }
+  end
+
+  describe 'to_s' do
+    subject { super().to_s }
+    it { is_expected.to eq('JIRA-123') }
+  end
+
+  describe :== do
+    specify { expect(subject).to eq(JiraIssue.new('JIRA-123', project)) }
+    specify { expect(subject).not_to eq(JiraIssue.new('JIRA-124', project)) }
+
+    it 'only compares with JiraIssues' do
+      expect(subject).not_to eq('JIRA-123')
+    end
+  end
+end
diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb
index d7fe01976d831a79bf760d9a23e5112a63848d6f..c962b83644a045664a6df0c86de8a401d0fb9588 100644
--- a/spec/models/key_spec.rb
+++ b/spec/models/key_spec.rb
@@ -81,7 +81,7 @@ describe Key, models: true do
 
     it 'rejects the multiple line key' do
       key = build(:key)
-      key.key.gsub!(' ', "\n")
+      key.key.tr!(' ', "\n")
       expect(key).not_to be_valid
     end
   end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 1aeba9b2b3bcef80dbdf80053ac632b34be003af..e0653a8327d61ac6de3dfdac0c8090bbbfb1ac2f 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -164,6 +164,17 @@ describe MergeRequest, models: true do
 
       expect(subject.closes_issues).to include(issue2)
     end
+
+    context 'for a project with JIRA integration' do
+      let(:issue0) { JiraIssue.new('JIRA-123', subject.project) }
+      let(:issue1) { JiraIssue.new('FOOBAR-4567', subject.project) }
+
+      it 'returns sorted JiraIssues' do
+        allow(subject.project).to receive_messages(default_branch: subject.target_branch)
+
+        expect(subject.closes_issues).to eq([issue0, issue1])
+      end
+    end
   end
 
   describe "#work_in_progress?" do
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 216c7dabae03f910b17ff1e30c2f62aa0b47433b..593d8f76215de366247727af77df18a42926ff5e 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -137,9 +137,14 @@ describe Note, models: true do
       create :note, note: "smile", is_award: true
     end
 
-    it "returns grouped array of notes" do
-      expect(Note.grouped_awards.first.first).to eq("smile")
-      expect(Note.grouped_awards.first.last).to match_array(Note.all)
+    it "returns grouped hash of notes" do
+      expect(Note.grouped_awards.keys.size).to eq(3)
+      expect(Note.grouped_awards["smile"]).to match_array(Note.all)
+    end
+
+    it "returns thumbsup and thumbsdown always" do
+      expect(Note.grouped_awards["thumbsup"]).to match_array(Note.none)
+      expect(Note.grouped_awards["thumbsdown"]).to match_array(Note.none)
     end
   end
 
@@ -164,8 +169,8 @@ describe Note, models: true do
     let(:issue) { create :issue }
 
     it "converts aliases to actual name" do
-      note = create :note, note: ":thumbsup:", noteable: issue
-      expect(note.reload.note).to eq("+1")
+      note = create :note, note: ":+1:", noteable: issue
+      expect(note.reload.note).to eq("thumbsup")
     end
   end
 end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
index a5662b08bdad255cec9634a944382f37ddd76251..91dd92b7c679aa06af80e1c27c365a27ac950039 100644
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -57,23 +57,21 @@ describe HipchatService, models: true do
 
     it 'should use v1 if version is provided' do
       allow(hipchat).to receive(:api_version).and_return('v1')
-      expect(HipChat::Client).to receive(:new).
-                                     with(token,
-                                          api_version: 'v1',
-                                          server_url: server_url).
-                                     and_return(
-                                         double(:hipchat_service).as_null_object)
+      expect(HipChat::Client).to receive(:new).with(
+        token,
+        api_version: 'v1',
+        server_url: server_url
+      ).and_return(double(:hipchat_service).as_null_object)
       hipchat.execute(push_sample_data)
     end
 
     it 'should use v2 as the version when nothing is provided' do
       allow(hipchat).to receive(:api_version).and_return('')
-      expect(HipChat::Client).to receive(:new).
-                                     with(token,
-                                          api_version: 'v2',
-                                          server_url: server_url).
-                                     and_return(
-                                         double(:hipchat_service).as_null_object)
+      expect(HipChat::Client).to receive(:new).with(
+        token,
+        api_version: 'v2',
+        server_url: server_url
+      ).and_return(double(:hipchat_service).as_null_object)
       hipchat.execute(push_sample_data)
     end
 
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 7d91ebe9ce652cd3f28befb0e0623271990f99fd..2f8193170aedf3009a9377879a2b4da0c7c11c08 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -26,6 +26,113 @@ describe JiraService, models: true do
     it { is_expected.to have_one :service_hook }
   end
 
+  describe "Execute" do
+    let(:user)    { create(:user) }
+    let(:project) { create(:project) }
+    let(:merge_request) { create(:merge_request) }
+
+    before do
+      @jira_service = JiraService.new
+      allow(@jira_service).to receive_messages(
+        project_id: project.id,
+        project: project,
+        service_hook: true,
+        project_url: 'http://jira.example.com',
+        username: 'gitlab_jira_username',
+        password: 'gitlab_jira_password'
+      )
+      @jira_service.save # will build API URL, as api_url was not specified above
+      @sample_data = Gitlab::PushDataBuilder.build_sample(project, user)
+      # https://github.com/bblimke/webmock#request-with-basic-authentication
+      @api_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions'
+      @comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment'
+
+      WebMock.stub_request(:post, @api_url)
+      WebMock.stub_request(:post, @comment_url)
+    end
+
+    it "should call JIRA API" do
+      @jira_service.execute(merge_request, JiraIssue.new("JIRA-123", project))
+      expect(WebMock).to have_requested(:post, @comment_url).with(
+        body: /Issue solved with/
+      ).once
+    end
+
+    it "calls the api with jira_issue_transition_id" do
+      @jira_service.jira_issue_transition_id = 'this-is-a-custom-id'
+      @jira_service.execute(merge_request, JiraIssue.new("JIRA-123", project))
+      expect(WebMock).to have_requested(:post, @api_url).with(
+        body: /this-is-a-custom-id/
+      ).once
+    end
+  end
+
+  describe "Stored password invalidation" do
+    let(:project) { create(:project) }
+
+    context "when a password was previously set" do
+      before do
+        @jira_service = JiraService.create(
+          project: create(:project),
+          properties: {
+            api_url: 'http://jira.example.com/rest/api/2',
+            username: 'mic',
+            password: "password"
+          }
+        )
+      end
+
+      it "reset password if url changed" do
+        @jira_service.api_url = 'http://jira_edited.example.com/rest/api/2'
+        @jira_service.save
+        expect(@jira_service.password).to be_nil
+      end
+
+      it "does not reset password if username changed" do
+        @jira_service.username = "some_name"
+        @jira_service.save
+        expect(@jira_service.password).to eq("password")
+      end
+
+      it "does not reset password if new url is set together with password, even if it's the same password" do
+        @jira_service.api_url = 'http://jira_edited.example.com/rest/api/2'
+        @jira_service.password = 'password'
+        @jira_service.save
+        expect(@jira_service.password).to eq("password")
+        expect(@jira_service.api_url).to eq("http://jira_edited.example.com/rest/api/2")
+      end
+
+      it "should reset password if url changed, even if setter called multiple times" do
+        @jira_service.api_url = 'http://jira1.example.com/rest/api/2'
+        @jira_service.api_url = 'http://jira1.example.com/rest/api/2'
+        @jira_service.save
+        expect(@jira_service.password).to be_nil
+      end
+    end
+
+    context "when no password was previously set" do
+      before do
+        @jira_service = JiraService.create(
+          project: create(:project),
+          properties: {
+            api_url: 'http://jira.example.com/rest/api/2',
+            username: 'mic'
+          }
+        )
+      end
+
+      it "saves password if new url is set together with password" do
+        @jira_service.api_url = 'http://jira_edited.example.com/rest/api/2'
+        @jira_service.password = 'password'
+        @jira_service.save
+        expect(@jira_service.password).to eq("password")
+        expect(@jira_service.api_url).to eq("http://jira_edited.example.com/rest/api/2")
+      end
+
+    end
+  end
+
+
   describe "Validations" do
     context "active" do
       before do
@@ -78,11 +185,12 @@ describe JiraService, models: true do
 
     context 'when gitlab.yml was initialized' do
       before do
-        settings = { "jira" => {
-          "title" => "Jira",
-          "project_url" => "http://jira.sample/projects/project_a",
-          "issues_url" => "http://jira.sample/issues/:id",
-          "new_issue_url" => "http://jira.sample/projects/project_a/issues/new"
+        settings = {
+          "jira" => {
+            "title" => "Jira",
+            "project_url" => "http://jira.sample/projects/project_a",
+            "issues_url" => "http://jira.sample/issues/:id",
+            "new_issue_url" => "http://jira.sample/projects/project_a/issues/new"
           }
         }
         allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
diff --git a/spec/models/project_services/slack_service/note_message_spec.rb b/spec/models/project_services/slack_service/note_message_spec.rb
index ebf8837570e1fa00870ccfb32bfbcaf554fccaa3..06006b9a4f530d525f28217f30be90550b64a4e1 100644
--- a/spec/models/project_services/slack_service/note_message_spec.rb
+++ b/spec/models/project_services/slack_service/note_message_spec.rb
@@ -89,10 +89,10 @@ describe SlackService::NoteMessage, models: true do
     it 'returns a message regarding notes on an issue' do
       message = SlackService::NoteMessage.new(@args)
       expect(message.pretext).to eq(
-                                     "Test User commented on " \
-      "<url|issue #20> in <somewhere.com|project_name>: " \
-      "*issue title*")
-      expected_attachments =  [
+        "Test User commented on " \
+        "<url|issue #20> in <somewhere.com|project_name>: " \
+        "*issue title*")
+      expected_attachments = [
           {
               text: "comment on an issue",
               color: color,
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 87582e074948b766cbaaea53c804bcf8d2a167bb..400bdf2d962bcdf35ded86db2715f44aba542fa4 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -172,13 +172,17 @@ describe Project, models: true do
 
   describe '#get_issue' do
     let(:project) { create(:empty_project) }
-    let(:issue)   { create(:issue, project: project) }
+    let!(:issue)  { create(:issue, project: project) }
 
     context 'with default issues tracker' do
       it 'returns an issue' do
         expect(project.get_issue(issue.iid)).to eq issue
       end
 
+      it 'returns count of open issues' do
+        expect(project.open_issues_count).to eq(1)
+      end
+
       it 'returns nil when no issue found' do
         expect(project.get_issue(999)).to be_nil
       end
@@ -548,4 +552,28 @@ describe Project, models: true do
       end
     end
   end
+
+  describe '#visibility_level_allowed?' do
+    let(:project) { create :project, visibility_level: Gitlab::VisibilityLevel::INTERNAL }
+
+    context 'when checking on non-forked project' do
+      it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
+      it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_truthy }
+      it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PUBLIC)).to be_truthy }
+    end
+
+    context 'when checking on forked project' do
+      let(:forked_project) { create :forked_project_with_submodules }
+
+      before do
+        forked_project.build_forked_project_link(forked_to_project_id: forked_project.id, forked_from_project_id: project.id)
+        forked_project.save
+      end
+
+      it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
+      it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_truthy }
+      it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::PUBLIC)).to be_falsey }
+    end
+
+  end
 end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index daa9d1087bfad6e47d5aebb4e3fa13f4168cd82d..2f184bbaf92c50fffd79529ea173d84a89d50421 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -26,6 +26,7 @@
 #  bio                        :string(255)
 #  failed_attempts            :integer          default(0)
 #  locked_at                  :datetime
+#  unlock_token               :string(255)
 #  username                   :string(255)
 #  can_create_group           :boolean          default(TRUE), not null
 #  can_create_team            :boolean          default(TRUE), not null
@@ -462,8 +463,8 @@ describe User, models: true do
       expect(User.search(user1.username.downcase).to_a).to eq([user1])
       expect(User.search(user2.username.upcase).to_a).to eq([user2])
       expect(User.search(user2.username.downcase).to_a).to eq([user2])
-      expect(User.search(user1.username.downcase).to_a.count).to eq(2)
-      expect(User.search(user2.username.downcase).to_a.count).to eq(1)
+      expect(User.search(user1.username.downcase).to_a.size).to eq(2)
+      expect(User.search(user2.username.downcase).to_a.size).to eq(1)
     end
   end
 
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 5c1b58535cc3b636122791e49e27a0e309b3950a..36461e84c3ab7c33283415c82505036c35d1e0d1 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -118,7 +118,7 @@ describe API::API, api: true  do
            branch_name: 'new design',
            ref: branch_sha
       expect(response.status).to eq(400)
-      expect(json_response['message']).to eq('Branch name invalid')
+      expect(json_response['message']).to eq('Branch name is invalid')
     end
 
     it 'should return 400 if branch already exists' do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index a91fa7353213d958ef8bf85bb0380464dab23c10..e194eb93cf48757cd7b21ee53080be87ab74a8c3 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -6,7 +6,7 @@ describe API::API, api: true  do
   let(:user) { create(:user) }
   let!(:project) {create(:project, creator_id: user.id, namespace: user.namespace) }
   let!(:merge_request) { create(:merge_request, :simple, author: user, assignee: user, source_project: project, target_project: project, title: "Test", created_at: base_time) }
-  let!(:merge_request_closed) { create(:merge_request, state: "closed", author: user, assignee: user, source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.seconds) }
+  let!(:merge_request_closed) { create(:merge_request, state: "closed", author: user, assignee: user, source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
   let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds) }
   let!(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
   let!(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index e784b7d1f2d9c96edbf47bde6fe1085f661213b2..7f0f9454b1006a193e5f10470e50857973af4a4b 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -65,6 +65,22 @@ describe API::API, api: true  do
         expect(json_response.first.keys).to include('tag_list')
       end
 
+      it 'should include open_issues_count' do
+        get api('/projects', user)
+        expect(response.status).to eq 200
+        expect(json_response).to be_an Array
+        expect(json_response.first.keys).to include('open_issues_count')
+      end
+
+      it 'should not include open_issues_count' do
+        project.update_attributes( { issues_enabled: false } )
+
+        get api('/projects', user)
+        expect(response.status).to eq 200
+        expect(json_response).to be_an Array
+        expect(json_response.first.keys).not_to include('open_issues_count')
+      end
+
       context 'and using search' do
         it 'should return searched project' do
           get api('/projects', user), { search: project.name }
@@ -115,6 +131,7 @@ describe API::API, api: true  do
 
         expect(json_response).to satisfy do |response|
           response.one? do |entry|
+            entry.has_key?('permissions') &&
             entry['name'] == project.name &&
               entry['owner']['username'] == user.username
           end
@@ -123,6 +140,25 @@ describe API::API, api: true  do
     end
   end
 
+  describe 'GET /projects/starred' do
+    before do
+      admin.starred_projects << project
+      admin.save!
+    end
+
+    it 'should return the starred projects' do
+      get api('/projects/all', admin)
+      expect(response.status).to eq(200)
+      expect(json_response).to be_an Array
+
+      expect(json_response).to satisfy do |response|
+        response.one? do |entry|
+          entry['name'] == project.name
+        end
+      end
+    end
+  end
+
   describe 'POST /projects' do
     context 'maximum number of projects reached' do
       it 'should not create new project and respond with 403' do
@@ -347,6 +383,18 @@ describe API::API, api: true  do
     end
 
     describe 'permissions' do
+      context 'all projects' do
+        it 'Contains permission information' do
+          project.team << [user, :master]
+          get api("/projects", user)
+
+          expect(response.status).to eq(200)
+          expect(json_response.first['permissions']['project_access']['access_level']).
+              to eq(Gitlab::Access::MASTER)
+          expect(json_response.first['permissions']['group_access']).to be_nil
+        end
+      end
+
       context 'personal project' do
         it 'Sets project access and returns 200' do
           project.team << [user, :master]
@@ -455,7 +503,7 @@ describe API::API, api: true  do
     end
   end
 
-  describe 'PUT /projects/:id/snippets/:shippet_id' do
+  describe 'PUT /projects/:id/snippets/:snippet_id' do
     it 'should update an existing project snippet' do
       put api("/projects/#{project.id}/snippets/#{snippet.id}", user),
         code: 'updated code'
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index b180d2fec77b8fd52197589b5e392c90bd1bf6ba..fed9ae1949b419834f3f6d1593765e449f27ff3f 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -29,7 +29,7 @@ describe API::API, api: true  do
         if required_attributes.empty?
           expected_code = 200
         else
-          attrs.delete(required_attributes.shuffle.first)
+          attrs.delete(required_attributes.sample)
           expected_code = 400
         end
         
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 2f609c63330d9d1142efbea168ccfd2de48cd61f..4f278551d0741b8cf7001fbf2f39570c2ef5a5fb 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -27,6 +27,13 @@ describe API::API, api: true  do
           user['username'] == username
         end['username']).to eq(username)
       end
+
+      it "should return one user" do
+        get api("/users?username=#{omniauth_user.username}", user)
+        expect(response.status).to eq(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['username']).to eq(omniauth_user.username)
+      end
     end
 
     context "when admin" do
diff --git a/spec/requests/ci/api/runners_spec.rb b/spec/requests/ci/api/runners_spec.rb
index 567da013e6f22ac3a6872456c8b51714fe17ebc5..5942aa7a1b59f27cade4f9b0fe08018bd0a76ea4 100644
--- a/spec/requests/ci/api/runners_spec.rb
+++ b/spec/requests/ci/api/runners_spec.rb
@@ -8,7 +8,6 @@ describe Ci::API::API do
 
   before do
     stub_gitlab_calls
-    stub_application_setting(ensure_runners_registration_token: registration_token)
     stub_application_setting(runners_registration_token: registration_token)
   end
 
diff --git a/spec/services/create_commit_builds_service_spec.rb b/spec/services/create_commit_builds_service_spec.rb
index 798c480b81af73a159eeeb0da3edc5cd836d710e..ea5dcfa068a0ffe114ebc1af7d3c5251b53da1ad 100644
--- a/spec/services/create_commit_builds_service_spec.rb
+++ b/spec/services/create_commit_builds_service_spec.rb
@@ -17,7 +17,7 @@ describe CreateCommitBuildsService, services: true do
                         before: '00000000',
                         after: '31das312',
                         commits: [{ message: "Message" }]
-        )
+                       )
       end
 
       it { expect(commit).to be_kind_of(Ci::Commit) }
@@ -34,7 +34,7 @@ describe CreateCommitBuildsService, services: true do
                                  before: '00000000',
                                  after: '31das312',
                                  commits: [{ message: "Message" }]
-        )
+                                )
         expect(result).to be_persisted
       end
 
@@ -47,26 +47,24 @@ describe CreateCommitBuildsService, services: true do
                                  before: '00000000',
                                  after: '31das312',
                                  commits: [{ message: "Message" }]
-        )
+                                )
         expect(result).to be_persisted
       end
     end
 
-    it 'skips commits without .gitlab-ci.yml' do
+    it 'skips creating ci_commit for refs without .gitlab-ci.yml' do
       stub_ci_commit_yaml_file(nil)
       result = service.execute(project, user,
                                ref: 'refs/heads/0_1',
                                before: '00000000',
                                after: '31das312',
                                commits: [{ message: 'Message' }]
-      )
-      expect(result).to be_persisted
-      expect(result.builds.any?).to be_falsey
-      expect(result.status).to eq('skipped')
-      expect(result.yaml_errors).to be_nil
+                              )
+      expect(result).to be_falsey
+      expect(Ci::Commit.count).to eq(0)
     end
 
-    it 'skips commits if yaml is invalid' do
+    it 'fails commits if yaml is invalid' do
       message = 'message'
       allow_any_instance_of(Ci::Commit).to receive(:git_commit_message) { message }
       stub_ci_commit_yaml_file('invalid: file: file')
@@ -76,7 +74,8 @@ describe CreateCommitBuildsService, services: true do
                                before: '00000000',
                                after: '31das312',
                                commits: commits
-      )
+                              )
+      expect(commit).to be_persisted
       expect(commit.builds.any?).to be false
       expect(commit.status).to eq('failed')
       expect(commit.yaml_errors).to_not be_nil
@@ -96,7 +95,8 @@ describe CreateCommitBuildsService, services: true do
                                  before: '00000000',
                                  after: '31das312',
                                  commits: commits
-        )
+                                )
+        expect(commit).to be_persisted
         expect(commit.builds.any?).to be false
         expect(commit.status).to eq("skipped")
       end
@@ -110,8 +110,9 @@ describe CreateCommitBuildsService, services: true do
                                  before: '00000000',
                                  after: '31das312',
                                  commits: commits
-        )
+                                )
 
+        expect(commit).to be_persisted
         expect(commit.builds.first.name).to eq("staging")
       end
 
@@ -123,7 +124,8 @@ describe CreateCommitBuildsService, services: true do
                                  before: '00000000',
                                  after: '31das312',
                                  commits: commits
-        )
+                                )
+        expect(commit).to be_persisted
         expect(commit.builds.any?).to be false
         expect(commit.status).to eq("skipped")
         expect(commit.yaml_errors).to be_nil
@@ -139,7 +141,8 @@ describe CreateCommitBuildsService, services: true do
                                before: '00000000',
                                after: '31das312',
                                commits: commits
-      )
+                              )
+      expect(commit).to be_persisted
       expect(commit.builds.count(:all)).to eq(2)
 
       commit = service.execute(project, user,
@@ -147,7 +150,8 @@ describe CreateCommitBuildsService, services: true do
                                before: '00000000',
                                after: '31das312',
                                commits: commits
-      )
+                              )
+      expect(commit).to be_persisted
       expect(commit.builds.count(:all)).to eq(2)
     end
 
@@ -161,8 +165,9 @@ describe CreateCommitBuildsService, services: true do
                                before: '00000000',
                                after: '31das312',
                                commits: commits
-      )
+                              )
 
+      expect(commit).to be_persisted
       expect(commit.status).to eq("failed")
       expect(commit.builds.any?).to be false
     end
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index a04c242cf0e72a26069c7f4735bf74b80e81018b..c1080ef190aa2303641d110aa0d45a99b8fa805d 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -265,6 +265,75 @@ describe GitPushService, services: true do
         expect(Issue.find(issue.id)).to be_opened
       end
     end
+
+    # EE-only tests
+    context "for jira issue tracker" do
+      include JiraServiceHelper
+
+      let(:jira_tracker) { project.create_jira_service if project.jira_service.nil? }
+
+      before do
+        jira_service_settings
+
+        WebMock.stub_request(:post, jira_api_transition_url)
+        WebMock.stub_request(:post, jira_api_comment_url)
+        WebMock.stub_request(:get, jira_api_comment_url).to_return(body: jira_issue_comments)
+        WebMock.stub_request(:get, jira_api_test_url)
+
+        allow(closing_commit).to receive_messages({
+                                                    issue_closing_regex: Regexp.new(Gitlab.config.gitlab.issue_closing_pattern),
+                                                    safe_message: message,
+                                                    author_name: commit_author.name,
+                                                    author_email: commit_author.email
+                                                  })
+
+        allow(project.repository).to receive_messages(commits_between: [closing_commit])
+      end
+
+      after do
+        jira_tracker.destroy!
+      end
+
+      context "mentioning an issue" do
+        let(:message) { "this is some work.\n\nrelated to JIRA-1" }
+
+        it "should initiate one api call to jira server to mention the issue" do
+          service.execute(project, user, @oldrev, @newrev, @ref)
+
+          expect(WebMock).to have_requested(:post, jira_api_comment_url).with(
+            body: /mentioned this issue in/
+          ).once
+        end
+      end
+
+      context "closing an issue" do
+        let(:message) { "this is some work.\n\ncloses JIRA-1" }
+
+        it "should initiate one api call to jira server to close the issue" do
+          transition_body = {
+            transition: {
+              id: '2'
+            }
+          }.to_json
+
+          service.execute(project, user, @oldrev, @newrev, @ref)
+          expect(WebMock).to have_requested(:post, jira_api_transition_url).with(
+            body: transition_body
+          ).once
+        end
+
+        it "should initiate one api call to jira server to comment on the issue" do
+          comment_body = {
+            body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]."
+          }.to_json
+
+          service.execute(project, user, @oldrev, @newrev, @ref)
+          expect(WebMock).to have_requested(:post, jira_api_comment_url).with(
+            body: comment_body
+          ).once
+        end
+      end
+    end
   end
 
   describe "empty project" do
diff --git a/spec/services/git_tag_push_service_spec.rb b/spec/services/git_tag_push_service_spec.rb
index e2d15f1a83d7d93ce3abba2e3225471136a8371d..b982274c529073ee106ed318bf56d49d9c68c9d4 100644
--- a/spec/services/git_tag_push_service_spec.rb
+++ b/spec/services/git_tag_push_service_spec.rb
@@ -58,14 +58,14 @@ describe GitTagPushService, services: true do
         it { is_expected.to include(timestamp: @commit.date.xmlschema) }
         it do
           is_expected.to include(
-                           url: [
-                             Gitlab.config.gitlab.url,
-                             project.namespace.to_param,
-                             project.to_param,
-                             'commit',
-                             @commit.id
-                           ].join('/')
-                         )
+            url: [
+             Gitlab.config.gitlab.url,
+             project.namespace.to_param,
+             project.to_param,
+             'commit',
+             @commit.id
+            ].join('/')
+          )
         end
 
         context "with a author" do
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index d7a898e85ff6f39e8c468daf1085f63aa0c77ccd..c103752198d7f21c6cb4b1967c9386b5aa6aa906 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -115,6 +115,7 @@ describe NotificationService, services: true do
 
       before do
         build_team(note.project)
+        note.project.team << [note.author, :master]
         ActionMailer::Base.deliveries.clear
       end
 
@@ -126,6 +127,8 @@ describe NotificationService, services: true do
           note.project.team.members.each do |member|
             # User with disabled notification should not be notified
             next if member.id == @u_disabled.id
+            # Author should not be notified
+            next if member.id == note.author.id
             should_email(member)
           end
 
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index c36d45819896a9d78f0bc0911c7e09deb721cf1e..3c06a8901634512a99828a8bfab6144fcfb56a1b 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -100,6 +100,45 @@ describe Projects::UpdateService, services: true do
     end
   end
 
+  describe :visibility_level do
+    let(:user) { create :user, admin: true }
+    let(:project) { create :project, visibility_level: Gitlab::VisibilityLevel::INTERNAL }
+    let(:forked_project) { create :forked_project_with_submodules, visibility_level: Gitlab::VisibilityLevel::INTERNAL }
+    let(:opts) { {} }
+
+    before do
+      forked_project.build_forked_project_link(forked_to_project_id: forked_project.id, forked_from_project_id: project.id)
+      forked_project.save
+
+      @created_internal = project.internal?
+      @fork_created_internal = forked_project.internal?
+    end
+
+    context 'should update forks visibility level when parent set to more restrictive' do
+      before do
+        opts.merge!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+        update_project(project, user, opts).inspect
+      end
+
+      it { expect(@created_internal).to be_truthy }
+      it { expect(@fork_created_internal).to be_truthy }
+      it { expect(project.private?).to be_truthy }
+      it { expect(project.forks.first.private?).to be_truthy }
+    end
+
+    context 'should not update forks visibility level when parent set to less restrictive' do
+      before do
+        opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC)
+        update_project(project, user, opts).inspect
+      end
+
+      it { expect(@created_internal).to be_truthy }
+      it { expect(@fork_created_internal).to be_truthy }
+      it { expect(project.public?).to be_truthy }
+      it { expect(project.forks.first.internal?).to be_truthy }
+    end
+  end
+
   def update_project(project, user, opts)
     Projects::UpdateService.new(project, user, opts).execute
   end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 0a4f9b230e890d6b48a528b7a931b01b6853c630..c9f828ae2f7a5e99f63a889e269885b5180e3bef 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -425,4 +425,65 @@ describe SystemNoteService, services: true do
       end
     end
   end
+
+  include JiraServiceHelper
+
+  describe 'JIRA integration' do
+    let(:project)    { create(:project) }
+    let(:author)     { create(:user) }
+    let(:issue)      { create(:issue, project: project) }
+    let(:mergereq)   { create(:merge_request, :simple, target_project: project, source_project: project) }
+    let(:jira_issue) { JiraIssue.new("JIRA-1", project)}
+    let(:jira_tracker) { project.create_jira_service if project.jira_service.nil? }
+    let(:commit)     { project.commit }
+
+    context 'in JIRA issue tracker' do
+      before do
+        jira_service_settings
+        WebMock.stub_request(:post, jira_api_comment_url)
+      end
+
+      after do
+        jira_tracker.destroy!
+      end
+
+      describe "new reference" do
+        before do
+          WebMock.stub_request(:get, jira_api_comment_url).to_return(body: jira_issue_comments)
+        end
+
+        subject { described_class.cross_reference(jira_issue, commit, author) }
+
+        it { is_expected.to eq(jira_status_message) }
+      end
+
+      describe "existing reference" do
+        before do
+          message = "[#{author.name}|http://localhost/u/#{author.username}] mentioned this issue in [a commit of #{project.path_with_namespace}|http://localhost/#{project.path_with_namespace}/commit/#{commit.id}]."
+          WebMock.stub_request(:get, jira_api_comment_url).to_return(body: "{\"comments\":[{\"body\":\"#{message}\"}]}")
+        end
+
+        subject { described_class.cross_reference(jira_issue, commit, author) }
+        it { is_expected.not_to eq(jira_status_message) }
+      end
+    end
+
+    context 'issue from an issue' do
+      context 'in JIRA issue tracker' do
+        before do
+          jira_service_settings
+          WebMock.stub_request(:post, jira_api_comment_url)
+          WebMock.stub_request(:get, jira_api_comment_url).to_return(body: jira_issue_comments)
+        end
+
+        after do
+          jira_tracker.destroy!
+        end
+
+        subject { described_class.cross_reference(jira_issue, issue, author) }
+
+        it { is_expected.to eq(jira_status_message) }
+      end
+    end
+  end
 end
diff --git a/spec/services/update_snippet_service_spec.rb b/spec/services/update_snippet_service_spec.rb
index 124bb76e678df6760b463830d3673601cb91e5c9..48d114896d0ff5f8a33c21390053e0d43499f697 100644
--- a/spec/services/update_snippet_service_spec.rb
+++ b/spec/services/update_snippet_service_spec.rb
@@ -42,7 +42,7 @@ describe UpdateSnippetService, services: true do
     CreateSnippetService.new(project, user, opts).execute
   end
 
-  def update_snippet(project = nil, user, snippet, opts)
+  def update_snippet(project, user, snippet, opts)
     UpdateSnippetService.new(project, user, snippet, opts).execute
   end
 end
diff --git a/spec/support/jira_service_helper.rb b/spec/support/jira_service_helper.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a3f496359b1675f45aebf946ce24d8b1a7818f87
--- /dev/null
+++ b/spec/support/jira_service_helper.rb
@@ -0,0 +1,67 @@
+module JiraServiceHelper
+
+  def jira_service_settings
+    properties = {
+      "title"=>"JIRA tracker",
+      "project_url"=>"http://jira.example/issues/?jql=project=A",
+      "issues_url"=>"http://jira.example/browse/JIRA-1",
+      "new_issue_url"=>"http://jira.example/secure/CreateIssue.jspa",
+      "api_url"=>"http://jira.example/rest/api/2"
+    }
+
+    jira_tracker.update_attributes(properties: properties, active: true)
+  end
+
+  def jira_status_message
+    "JiraService SUCCESS 200: Successfully posted to #{jira_api_comment_url}."
+  end
+
+  def jira_issue_comments
+    "{\"startAt\":0,\"maxResults\":11,\"total\":11,
+      \"comments\":[{\"self\":\"http://0.0.0.0:4567/rest/api/2/issue/10002/comment/10609\",
+      \"id\":\"10609\",\"author\":{\"self\":\"http://0.0.0.0:4567/rest/api/2/user?username=gitlab\",
+      \"name\":\"gitlab\",\"emailAddress\":\"gitlab@example.com\",
+      \"avatarUrls\":{\"16x16\":\"http://0.0.0.0:4567/secure/useravatar?size=xsmall&avatarId=10122\",
+      \"24x24\":\"http://0.0.0.0:4567/secure/useravatar?size=small&avatarId=10122\",
+      \"32x32\":\"http://0.0.0.0:4567/secure/useravatar?size=medium&avatarId=10122\",
+      \"48x48\":\"http://0.0.0.0:4567/secure/useravatar?avatarId=10122\"},
+      \"displayName\":\"GitLab\",\"active\":true},
+      \"body\":\"[Administrator|http://localhost:3000/u/root] mentioned JIRA-1 in Merge request of [gitlab-org/gitlab-test|http://localhost:3000/gitlab-org/gitlab-test/merge_requests/2].\",
+      \"updateAuthor\":{\"self\":\"http://0.0.0.0:4567/rest/api/2/user?username=gitlab\",\"name\":\"gitlab\",\"emailAddress\":\"gitlab@example.com\",
+      \"avatarUrls\":{\"16x16\":\"http://0.0.0.0:4567/secure/useravatar?size=xsmall&avatarId=10122\",
+      \"24x24\":\"http://0.0.0.0:4567/secure/useravatar?size=small&avatarId=10122\",
+      \"32x32\":\"http://0.0.0.0:4567/secure/useravatar?size=medium&avatarId=10122\",
+      \"48x48\":\"http://0.0.0.0:4567/secure/useravatar?avatarId=10122\"},\"displayName\":\"GitLab\",\"active\":true},
+      \"created\":\"2015-02-12T22:47:07.826+0100\",
+      \"updated\":\"2015-02-12T22:47:07.826+0100\"},
+     {\"self\":\"http://0.0.0.0:4567/rest/api/2/issue/10002/comment/10700\",
+        \"id\":\"10700\",\"author\":{\"self\":\"http://0.0.0.0:4567/rest/api/2/user?username=gitlab\",
+        \"name\":\"gitlab\",\"emailAddress\":\"gitlab@example.com\",
+        \"avatarUrls\":{\"16x16\":\"http://0.0.0.0:4567/secure/useravatar?size=xsmall&avatarId=10122\",
+        \"24x24\":\"http://0.0.0.0:4567/secure/useravatar?size=small&avatarId=10122\",
+        \"32x32\":\"http://0.0.0.0:4567/secure/useravatar?size=medium&avatarId=10122\",
+        \"48x48\":\"http://0.0.0.0:4567/secure/useravatar?avatarId=10122\"},\"displayName\":\"GitLab\",\"active\":true},
+        \"body\":\"[Administrator|http://localhost:3000/u/root] mentioned this issue in [a commit of h5bp/html5-boilerplate|http://localhost:3000/h5bp/html5-boilerplate/commit/2439f77897122fbeee3bfd9bb692d3608848433e].\",
+        \"updateAuthor\":{\"self\":\"http://0.0.0.0:4567/rest/api/2/user?username=gitlab\",\"name\":\"gitlab\",\"emailAddress\":\"gitlab@example.com\",
+        \"avatarUrls\":{\"16x16\":\"http://0.0.0.0:4567/secure/useravatar?size=xsmall&avatarId=10122\",
+        \"24x24\":\"http://0.0.0.0:4567/secure/useravatar?size=small&avatarId=10122\",
+        \"32x32\":\"http://0.0.0.0:4567/secure/useravatar?size=medium&avatarId=10122\",
+        \"48x48\":\"http://0.0.0.0:4567/secure/useravatar?avatarId=10122\"},\"displayName\":\"GitLab\",\"active\":true},
+        \"created\":\"2015-04-01T03:45:55.667+0200\",
+        \"updated\":\"2015-04-01T03:45:55.667+0200\"
+      }
+      ]}"
+  end
+
+  def jira_api_comment_url
+    'http://jira.example/rest/api/2/issue/JIRA-1/comment'
+  end
+
+  def jira_api_transition_url
+    'http://jira.example/rest/api/2/issue/JIRA-1/transitions'
+  end
+
+  def jira_api_test_url
+    'http://jira.example/rest/api/2/myself'
+  end
+end
diff --git a/spec/support/repo_helpers.rb b/spec/support/repo_helpers.rb
index aadf791bf3ff1ee5c245dc11e31dd1ac1d6f8d25..aa8258d6dad6ef0904684dd8a3869da479010ae4 100644
--- a/spec/support/repo_helpers.rb
+++ b/spec/support/repo_helpers.rb
@@ -45,12 +45,12 @@ eos
 
   def another_sample_commit
     OpenStruct.new(
-        id: "e56497bb5f03a90a51293fc6d516788730953899",
-        parent_id: '4cd80ccab63c82b4bad16faa5193fbd2aa06df40',
-        author_full_name: "Sytse Sijbrandij",
-        author_email: "sytse@gitlab.com",
-        files_changed_count: 1,
-        message: <<eos
+      id: "e56497bb5f03a90a51293fc6d516788730953899",
+      parent_id: '4cd80ccab63c82b4bad16faa5193fbd2aa06df40',
+      author_full_name: "Sytse Sijbrandij",
+      author_email: "sytse@gitlab.com",
+      files_changed_count: 1,
+      message: <<eos
 Add directory structure for tree_helper spec
 
 This directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module
diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb
index 245f066df1f6a016baa738e15e3c1642133e9a6f..dae31992620a0b86de8f8a64352b65cb4c669e0b 100644
--- a/spec/workers/repository_fork_worker_spec.rb
+++ b/spec/workers/repository_fork_worker_spec.rb
@@ -9,20 +9,22 @@ describe RepositoryForkWorker do
   describe "#perform" do
     it "creates a new repository from a fork" do
       expect_any_instance_of(Gitlab::Shell).to receive(:fork_repository).with(
-                                                   project.path_with_namespace,
-                                                   fork_project.namespace.path).
-                                                   and_return(true)
+        project.path_with_namespace,
+        fork_project.namespace.path
+      ).and_return(true)
 
-      subject.perform(project.id,
-                      project.path_with_namespace,
-                      fork_project.namespace.path)
+      subject.perform(
+        project.id,
+        project.path_with_namespace,
+        fork_project.namespace.path)
     end
 
     it "handles bad fork" do
       expect_any_instance_of(Gitlab::Shell).to receive(:fork_repository).and_return(false)
-      subject.perform(project.id,
-                      project.path_with_namespace,
-                      fork_project.namespace.path)
+      subject.perform(
+        project.id,
+        project.path_with_namespace,
+        fork_project.namespace.path)
     end
   end
 end
diff --git a/spec/workers/stuck_ci_builds_worker_spec.rb b/spec/workers/stuck_ci_builds_worker_spec.rb
index f9d87d97014f94e9e791882bbc7dfe6b5a875f66..665ec20f2243a7f5cc68fa72bd244d341bad8ccd 100644
--- a/spec/workers/stuck_ci_builds_worker_spec.rb
+++ b/spec/workers/stuck_ci_builds_worker_spec.rb
@@ -15,7 +15,7 @@ describe StuckCiBuildsWorker do
       end
 
       it 'gets dropped if it was updated over 2 days ago' do
-        build.update!(updated_at: 2.day.ago)
+        build.update!(updated_at: 2.days.ago)
         StuckCiBuildsWorker.new.perform
         is_expected.to eq('failed')
       end
@@ -35,7 +35,7 @@ describe StuckCiBuildsWorker do
       end
 
       it "is still #{status}" do
-        build.update!(updated_at: 2.day.ago)
+        build.update!(updated_at: 2.days.ago)
         StuckCiBuildsWorker.new.perform
         is_expected.to eq(status)
       end