├── .codeclimate.yml ├── .codecov.yml ├── .csslintrc ├── .eslintignore ├── .eslintrc ├── .github └── workflows │ ├── ci.yml │ └── client.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── .ruby-version ├── .travis.yml ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Procfile ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ └── vim_golf_logo.png │ ├── javascripts │ │ ├── application.js.erb │ │ └── prettify │ │ │ ├── lang-apollo.js │ │ │ ├── lang-css.js │ │ │ ├── lang-hs.js │ │ │ ├── lang-lisp.js │ │ │ ├── lang-lua.js │ │ │ ├── lang-ml.js │ │ │ ├── lang-proto.js │ │ │ ├── lang-scala.js │ │ │ ├── lang-sql.js │ │ │ ├── lang-vb.js │ │ │ ├── lang-vhdl.js │ │ │ ├── lang-wiki.js │ │ │ ├── lang-yaml.js │ │ │ └── prettify.js │ └── stylesheets │ │ ├── .gitkeep │ │ ├── 960.scss.erb │ │ ├── application.scss.erb │ │ ├── forms.scss.erb │ │ ├── images │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ ├── ui-bg_flat_10_000000_40x100.png │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_228ef1_256x240.png │ │ ├── ui-icons_ef8c08_256x240.png │ │ ├── ui-icons_ffd27a_256x240.png │ │ └── ui-icons_ffffff_256x240.png │ │ ├── oauth.scss.erb │ │ ├── prettify.css │ │ ├── reset.scss.erb │ │ ├── scaffold.scss.erb │ │ ├── screen.scss.erb │ │ ├── site.scss.erb │ │ ├── syntax.scss.erb │ │ └── text.scss.erb ├── controllers │ ├── application_controller.rb │ ├── challenges_controller.rb │ ├── entry_controller.rb │ ├── main_controller.rb │ ├── sessions_controller.rb │ └── users_controller.rb ├── helpers │ └── application_helper.rb ├── models │ ├── challenge.rb │ ├── comment.rb │ ├── entry.rb │ └── user.rb ├── repositories │ └── repository_challenge.rb ├── services │ ├── leaderboard.rb │ ├── show_challenge.rb │ ├── show_profile.rb │ ├── solution.rb │ ├── submissions.rb │ └── submissions_per_user.rb └── views │ ├── challenges │ ├── new.erb │ ├── show.erb │ └── user.erb │ ├── layouts │ └── application.html.erb │ ├── main │ ├── about.erb │ ├── feed.rss.builder │ ├── index.erb │ └── oauth.erb │ ├── shared │ ├── _challenge.erb │ ├── _challenge_credits.erb │ ├── _challenge_description.erb │ ├── _submissions.erb │ └── _tweets.erb │ └── users │ ├── show.erb │ └── top.erb ├── client ├── Dockerfile └── run-vimgolf.sh ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── application_controller_renderer.rb │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── content_security_policy.rb │ ├── cookies_serializer.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── new_framework_defaults_5_2.rb │ ├── omniauth.rb │ ├── secret_token.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── newrelic.yml ├── routes.rb ├── storage.yml └── unicorn.rb ├── db ├── migrate │ └── 20210425154000_create_tables.rb ├── schema.rb └── seeds.rb ├── lib └── vimgolf │ ├── .rspec │ ├── Gemfile │ ├── README.md │ ├── Rakefile │ ├── bin │ └── vimgolf │ ├── lib │ ├── vimgolf.rb │ └── vimgolf │ │ ├── challenge.rb │ │ ├── cli.rb │ │ ├── config.rb │ │ ├── keylog.rb │ │ ├── ui.rb │ │ ├── version.rb │ │ └── vimgolf.vimrc │ └── vimgolf.gemspec ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon-96x96.png └── robots.txt ├── script └── rails └── spec ├── cli_helper.rb ├── controllers ├── challenges_controller_spec.rb ├── entry_controller_spec.rb ├── main_controller_spec.rb ├── sessions_controller_spec.rb └── users_controller_spec.rb ├── data ├── diff.txt ├── input.txt └── output.txt ├── factories.rb ├── features ├── deleting_a_challenge_spec.rb ├── entry_feature_spec.rb ├── profile_spec.rb ├── sign_in_spec.rb └── submitting_a_challenge_spec.rb ├── lib ├── challenge_spec.rb ├── cli_spec.rb ├── fixtures │ ├── 4d19832d8ae121365c00000b.log │ ├── 4d1a1c36567bac34a9000002.log │ ├── 4d1a1c69567bac34a9000004.log │ ├── 4d1a21e88ae121365c00000e.log │ └── 4d1a34ccfa85f32065000004.log ├── keylog_spec.rb ├── mock_bin │ ├── mock_diff.rb │ └── mock_vim.rb ├── testdata │ ├── input.txt │ ├── mismatch.txt │ └── output.txt └── ui_spec.rb ├── models ├── challenge_spec.rb ├── comment_spec.rb ├── entry_spec.rb └── user_spec.rb ├── repositories └── repository_challenge_spec.rb ├── requests └── submit_entry_spec.rb ├── routing ├── challenge_spec.rb └── entry_spec.rb ├── services ├── submissions_per_user_spec.rb └── submissions_spec.rb ├── spec_helper.rb └── support └── omni_auth_helper.rb /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | brakeman: 4 | enabled: true 5 | bundler-audit: 6 | enabled: true 7 | csslint: 8 | enabled: true 9 | duplication: 10 | enabled: true 11 | config: 12 | languages: 13 | ruby: 14 | javascript: 15 | eslint: 16 | enabled: true 17 | fixme: 18 | enabled: true 19 | rubocop: 20 | enabled: true 21 | channel: rubocop-1-9-1 22 | ratings: 23 | paths: 24 | - Gemfile.lock 25 | - "**.erb" 26 | - "**.haml" 27 | - "**.rb" 28 | - "**.rhtml" 29 | - "**.slim" 30 | - "**.css" 31 | - "**.inc" 32 | - "**.js" 33 | - "**.jsx" 34 | - "**.module" 35 | exclude_paths: 36 | - config/ 37 | - db/ 38 | - script/ 39 | - spec/ 40 | - app/repositories/ 41 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | target: auto 6 | threshold: 1% 7 | patch: 8 | default: 9 | target: auto 10 | -------------------------------------------------------------------------------- /.csslintrc: -------------------------------------------------------------------------------- 1 | --exclude-exts=.min.css 2 | --ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*{.,-}min.js 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Vimgolf CI 2 | on: 3 | - push 4 | - pull_request 5 | 6 | jobs: 7 | rubocop: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Check out git tree 11 | uses: actions/checkout@v2 12 | - name: Set up Ruby 13 | uses: ruby/setup-ruby@v1 14 | with: 15 | bundler-cache: true 16 | - name: Run rubocop 17 | run: bundle exec rubocop 18 | 19 | rspec-rails: 20 | runs-on: ubuntu-latest 21 | env: 22 | FERRUM_PROCESS_TIMEOUT: 30 23 | steps: 24 | - name: Check out git tree 25 | uses: actions/checkout@v2 26 | - name: Set up Ruby 27 | uses: ruby/setup-ruby@v1 28 | with: 29 | bundler-cache: true 30 | - name: Run RSpec tests 31 | run: bundle exec rake 32 | - name: Upload coverage information 33 | uses: codecov/codecov-action@v1.5.0 34 | with: 35 | files: ./coverage/coverage.xml 36 | 37 | rspec-rails-macos: 38 | runs-on: macos-latest 39 | env: 40 | FERRUM_PROCESS_TIMEOUT: 30 41 | steps: 42 | - name: Check out git tree 43 | uses: actions/checkout@v2 44 | - name: Set up Ruby 45 | uses: ruby/setup-ruby@v1 46 | with: 47 | bundler-cache: true 48 | cache-version: 1 49 | - name: Run RSpec tests 50 | run: bundle exec rake 51 | 52 | rspec-rails-pg: 53 | runs-on: ubuntu-18.04 54 | services: 55 | postgres: 56 | image: postgres:latest 57 | env: 58 | POSTGRES_USER: vimgolfgh 59 | POSTGRES_PASSWORD: vimgolfpw 60 | ports: 61 | - 5432:5432 62 | env: 63 | DATABASE_ADAPTER: pg 64 | DATABASE_URL: postgresql://vimgolfgh:vimgolfpw@localhost/ 65 | FERRUM_PROCESS_TIMEOUT: 30 66 | steps: 67 | - name: Check out git tree 68 | uses: actions/checkout@v2 69 | - name: Set up Ruby 70 | uses: ruby/setup-ruby@v1 71 | with: 72 | bundler-cache: true 73 | - name: Create database 74 | run: bundle exec rails db:create db:migrate RAILS_ENV=test 75 | - name: Run RSpec tests 76 | run: bundle exec rake 77 | 78 | rspec-client-gem: 79 | strategy: 80 | fail-fast: false 81 | matrix: 82 | os: 83 | - ubuntu-latest 84 | - macos-latest 85 | ruby-version: 86 | - '2.3' 87 | - '2.4' 88 | - '2.7' 89 | - '3.0' 90 | include: 91 | - os: ubuntu-latest 92 | ruby-version: '2.1' 93 | - os: ubuntu-latest 94 | ruby-version: '2.0' 95 | - os: macos-latest 96 | ruby-version: '2.0' 97 | - os: windows-latest 98 | ruby-version: '2.7' 99 | runs-on: ${{ matrix.os }} 100 | steps: 101 | - name: Check out git tree 102 | uses: actions/checkout@v2 103 | - name: Set up Ruby 104 | uses: ruby/setup-ruby@v1 105 | with: 106 | ruby-version: ${{ matrix.ruby-version }} 107 | bundler-cache: true 108 | env: 109 | BUNDLE_GEMFILE: lib/vimgolf/Gemfile 110 | - name: Run RSpec tests 111 | working-directory: lib/vimgolf 112 | run: bundle exec rake 113 | -------------------------------------------------------------------------------- /.github/workflows/client.yml: -------------------------------------------------------------------------------- 1 | name: Vimgolf Docker client 2 | on: 3 | schedule: 4 | - cron: '30 5 * * 2' 5 | workflow_dispatch: {} 6 | 7 | jobs: 8 | docker: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Check out git tree 12 | uses: actions/checkout@v2 13 | - name: Generate Docker metadata 14 | id: meta 15 | uses: docker/metadata-action@v3 16 | with: 17 | images: | 18 | ghcr.io/${{ github.repository }} 19 | tags: | 20 | type=schedule,pattern={{date 'YYYYMMDD'}} 21 | type=raw,value={{date 'YYYYMMDD'}},prefix=manual-,enable=${{ github.event_name == 'workflow_dispatch' }} 22 | flavor: | 23 | latest=true 24 | - name: Set up QEMU 25 | uses: docker/setup-qemu-action@v2 26 | - name: Set up Buildx 27 | uses: docker/setup-buildx-action@v1 28 | - name: Login to GitHub Container Registry 29 | uses: docker/login-action@v1 30 | with: 31 | registry: ghcr.io 32 | username: ${{ github.repository_owner }} 33 | password: ${{ secrets.GITHUB_TOKEN }} 34 | - name: Build and Push 35 | uses: docker/build-push-action@v2 36 | with: 37 | context: client/ 38 | platforms: linux/amd64,linux/arm64 39 | push: true 40 | tags: ${{ steps.meta.outputs.tags }} 41 | labels: ${{ steps.meta.outputs.labels }} 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Also bundler vendored files, since this is the typical location for them. 11 | /vendor/bundle 12 | /vendor/cache 13 | 14 | # Ignore the default SQLite database. 15 | /db/*.sqlite3 16 | /db/*.sqlite3-journal 17 | /db/*.sqlite3-* 18 | 19 | # Ignore all logfiles and tempfiles. 20 | /log/* 21 | /tmp/* 22 | !/log/.keep 23 | !/tmp/.keep 24 | 25 | # Ignore pidfiles, but keep the directory. 26 | /tmp/pids/* 27 | !/tmp/pids/ 28 | !/tmp/pids/.keep 29 | 30 | # Ignore uploaded files in development. 31 | /storage/* 32 | !/storage/.keep 33 | 34 | /public/assets 35 | .byebug_history 36 | 37 | # Ignore master key for decrypting credentials and more. 38 | /config/master.key 39 | 40 | # Building client gem under lib/vimgolf. 41 | *.gem 42 | /lib/*/Gemfile.lock 43 | pkg/* 44 | local/* 45 | 46 | # Test coverage report from SimpleCov. 47 | /coverage/ 48 | 49 | # Vim swap files, backup files 50 | *.sw? 51 | *~ 52 | 53 | # Tags file from ctags, if one is generated. 54 | /tags 55 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --colour 2 | --order rand 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | inherit_mode: 4 | merge: 5 | - Exclude 6 | 7 | # Add Rubocop exceptions for db/schema.rb, which is generated by Rails, 8 | # so shouldn't be checked by Rubocop. 9 | 10 | Style/NumericLiterals: 11 | Exclude: 12 | - 'db/schema.rb' 13 | 14 | Layout/EmptyLinesAroundBlockBody: 15 | Exclude: 16 | - 'db/schema.rb' 17 | 18 | # We want to stay compatible with older versions of Ruby for the 19 | # client code, so don't complain about "begin"/"rescue" or 20 | # "begin"/"ensure" blocks. Using "rescue"/"ensure" in blocks that 21 | # don't use "begin" is only available on Ruby 2.5+. 22 | Style/RedundantBegin: 23 | Exclude: 24 | - 'lib/vimgolf/lib/**/*.rb' 25 | - 'spec/lib/**/*.rb' 26 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.7.6 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | os: linux 3 | dist: focal 4 | env: 5 | - GOLFHOST=https://vimgolf-staging.herokuapp.com 6 | jobs: 7 | include: 8 | - rvm: 2.6.7 # Test web AND cli with specific version 9 | gemfile: Gemfile 10 | - rvm: 2.4 # Test only the cli. 11 | gemfile: lib/vimgolf/Gemfile 12 | - rvm: 2.3 # Test only the cli, on older Ruby. 13 | dist: xenial 14 | gemfile: lib/vimgolf/Gemfile 15 | - rvm: 2.0 # Test only the cli, on older Ruby. 16 | dist: trusty 17 | gemfile: lib/vimgolf/Gemfile 18 | services: 19 | - mongodb 20 | before_install: 21 | - ls -l /home/travis/.rvm/gems # Future reference, targets for quick build 22 | - cd `dirname $BUNDLE_GEMFILE` 23 | - pwd # For debug info 24 | - gem install -v 1.16.2 bundler # Travis's Bundler 1.7.6 is causing problems 25 | script: 26 | - bundle exec rake 27 | addons: 28 | apt: 29 | sources: 30 | - mongodb-2.6-precise 31 | code_climate: 32 | repo_token: 87b58d792ac24c87c9eb7957aa3fe7e05f72f800619452853270ed6a8f5b3853 33 | after_success: 34 | - bundle exec codeclimate-test-reporter 35 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | ruby '~> 2.7' 3 | 4 | gem 'rails', '~> 5.2.0' 5 | 6 | # Reduces boot times through caching; required in config/boot.rb 7 | gem 'bootsnap', '>= 1.4.2', require: false 8 | 9 | gem 'pg' 10 | 11 | gem 'json' 12 | gem 'memcachier' 13 | gem 'dalli' 14 | gem 'omniauth', '~> 2.0' 15 | gem 'omniauth-rails_csrf_protection' 16 | gem 'omniauth-twitter2' 17 | gem 'omniauth-github' 18 | gem 'tweet-button' 19 | gem 'newrelic_rpm' 20 | gem 'unicorn' 21 | gem 'rack-timeout' 22 | gem 'sprockets-rails', '~> 2.0' 23 | gem 'sass-rails', '~> 5.0' 24 | gem 'uglifier', '>= 1.0.3' 25 | gem 'kaminari' 26 | gem 'ruby_identicon' 27 | 28 | gem 'vimgolf', path: 'lib/vimgolf' 29 | 30 | group :test, :development do 31 | gem 'sqlite3', '~> 1.3.6' 32 | gem 'rspec-rails', '~> 4.0' 33 | gem 'rails-controller-testing' 34 | gem 'shoulda-matchers' 35 | gem 'simplecov', require: false 36 | gem 'simplecov-cobertura', require: false 37 | gem 'codeclimate-test-reporter', '~> 1.0.0' 38 | gem 'capybara' 39 | gem 'climate_control' 40 | gem 'cuprite' 41 | gem 'diff-lcs', require: false 42 | gem 'execjs' 43 | gem 'mini_racer' 44 | gem 'launchy' 45 | gem 'listen', '~> 3.2' 46 | gem 'pry-byebug' 47 | gem 'pry-stack_explorer' 48 | gem 'factory_bot', '~> 4.0' 49 | gem 'faker' 50 | gem 'rubocop', '~> 1.9.1' 51 | gem 'rubocop-rails' 52 | gem 'rubocop-rspec' 53 | gem 'webmock' 54 | end 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2010 Ilya Grigorik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec unicorn -p $PORT -E $RACK_ENV -c config/unicorn.rb 2 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | require 'rake' 6 | 7 | Vimgolf::Application.load_tasks 8 | 9 | Rake::Task['test:prepare'].enhance(['db:test:prepare']) 10 | -------------------------------------------------------------------------------- /app/assets/images/vim_golf_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/vimgolf/766bd422147b27bbe05a481a2afc72a95697ae0a/app/assets/images/vim_golf_logo.png -------------------------------------------------------------------------------- /app/assets/javascripts/application.js.erb: -------------------------------------------------------------------------------- 1 | //= require prettify/prettify 2 | //= require_tree ./prettify 3 | //= require_self 4 | 5 | function toggle(id) { 6 | var el = document.getElementById(id) 7 | 8 | if (el.style.display === 'block') { 9 | el.style.display = 'none' 10 | } else { 11 | el.style.display = 'block' 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/javascripts/prettify/lang-apollo.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\r\n]*/,null,"#"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/, 2 | null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),["apollo","agc","aea"]) -------------------------------------------------------------------------------- /app/assets/javascripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[ \t\r\n\f]+/,null," \t\r\n\u000c"]],[["str",/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],["str",/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],["kwd",/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//], 2 | ["com",/^(?: 21 |
22 |

The page you were looking for doesn't exist.

23 |

You may have mistyped the address or the page may have moved.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

The change you wanted was rejected.

23 |

Maybe you tried to change something you didn't have access to.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 17 | 18 | 19 | 20 | 21 |
22 |

We're sorry, but something went wrong.

23 |

We've been notified about this issue and we'll take a look at it shortly.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/vimgolf/766bd422147b27bbe05a481a2afc72a95697ae0a/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/vimgolf/766bd422147b27bbe05a481a2afc72a95697ae0a/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igrigorik/vimgolf/766bd422147b27bbe05a481a2afc72a95697ae0a/public/favicon-96x96.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-Agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /script/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. 3 | 4 | APP_PATH = File.expand_path('../../config/application', __FILE__) 5 | require File.expand_path('../../config/boot', __FILE__) 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /spec/cli_helper.rb: -------------------------------------------------------------------------------- 1 | require 'vimgolf' 2 | require 'stringio' 3 | require 'climate_control' 4 | 5 | module Kernel 6 | def capture_stdio(input = nil, and_stderr: false) 7 | if input 8 | org_stdin = $stdin 9 | $stdin = StringIO.new(input) 10 | end 11 | org_stdout = $stdout 12 | $stdout = StringIO.new 13 | if and_stderr 14 | org_stderr = $stderr 15 | $stderr = $stdout 16 | end 17 | yield 18 | @out = $stdout.string 19 | ensure 20 | $stdout = org_stdout 21 | $stdin = org_stdin 22 | $stderr = org_stderr if and_stderr 23 | end 24 | alias capture_stdout capture_stdio 25 | end 26 | 27 | RSpec.configure do |config| 28 | config.after(:each) do 29 | # To imitate the initial class load before calling `VimGolf::CLI.start` 30 | VimGolf::CLI.reset_ui 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/controllers/challenges_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe ChallengesController do 4 | describe "#create" do 5 | it "should require login to create challenge" do 6 | post "create", :format => :json 7 | 8 | expect(response.status).to eq(302) 9 | end 10 | end 11 | 12 | describe "#show" do 13 | context "json format" do 14 | let(:challenge) do 15 | create( 16 | :challenge, 17 | title: "foo", 18 | description: "bar", 19 | input: "baz", 20 | input_type: "baz_type", 21 | output: "qux", 22 | output_type: "qux_type", 23 | diff: "hoge" 24 | ) 25 | end 26 | it "should allow download of challenge without login" do 27 | get "show", params: { id: challenge.urlkey }, :format => :json 28 | 29 | expect(response.status).to eq(200) 30 | end 31 | 32 | it "Return object with defined attributes" do 33 | get "show", params: { id: challenge.urlkey }, :format => :json 34 | 35 | json = ActiveSupport::JSON.decode(response.body) 36 | 37 | expect(json).to eq( 38 | { 39 | "in" => { "data" => "baz", "type" => "baz_type" }, 40 | "out" => { "data" => "qux", "type" => "qux_type" }, 41 | "client" => Vimgolf::VERSION 42 | } 43 | ) 44 | end 45 | end 46 | 47 | context "html format" do 48 | render_views 49 | 50 | let(:challenge) do 51 | create( 52 | :challenge, 53 | title: "foo", 54 | description: "bar", 55 | input: "baz", 56 | input_type: "baz_type", 57 | output: "qux", 58 | output_type: "qux_type", 59 | diff: "hoge" 60 | ) 61 | end 62 | 63 | before do 64 | challenge.entries << build(:entry) 65 | end 66 | 67 | it "works with html views" do 68 | get "show", params: { :id => challenge.urlkey } 69 | expect(response.status).to eq(200) 70 | end 71 | end 72 | end 73 | 74 | describe "#user" do 75 | context "html format" do 76 | render_views 77 | 78 | let(:user1) { create(:user) } 79 | let(:user2) { create(:user) } 80 | let(:challenge) { create(:challenge) } 81 | 82 | before do 83 | challenge.entries << build(:entry, user: user1, score: 19, created_at: Time.new(2018, 3, 20)) 84 | challenge.entries << build(:entry, user: user2, score: 17, created_at: Time.new(2018, 3, 19)) 85 | challenge.entries << build(:entry, user: user1, score: 11, created_at: Time.new(2018, 3, 18)) 86 | end 87 | 88 | it "works with html views" do 89 | get "user", params: { id: challenge.urlkey, username: user1.nickname } 90 | expect(response.status).to eq(200) 91 | end 92 | end 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /spec/controllers/entry_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe EntryController do 4 | it "should create an entry for an existing challenge without login" do 5 | User.create!( 6 | name: "Bill Nye", 7 | nickname: "The Science Guy", 8 | provider: "foo", 9 | image: "bar", 10 | uid: 12345 11 | ) 12 | c = Challenge.new({ 13 | :title => :test, 14 | :description => :test, 15 | :input => :a, 16 | :input_type => :txt, 17 | :output => :b, 18 | :output_type => :txt, 19 | :diff => :c 20 | }) 21 | 22 | c.user = User.first 23 | c.save 24 | 25 | request.accept = 'application/json' 26 | post "create", params: { 27 | :format => :json, 28 | :challenge_id => c.urlkey, 29 | :entry => 'a' * 50, 30 | :apikey => User.first.key 31 | } 32 | 33 | expect(response.status).to eq(200) 34 | expect(ActiveSupport::JSON.decode(response.body)).to include 'status' 35 | end 36 | 37 | it "should report an error for a non-existing challenge" do 38 | request.accept = 'application/json' 39 | post "create", :format => :json 40 | 41 | expect(response.status).to eq(400) 42 | expect(ActiveSupport::JSON.decode(response.body)).to include 'status' 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /spec/controllers/main_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe MainController do 4 | render_views 5 | 6 | describe "#index" do 7 | context "With 0 challenges 0 users 0 entries" do 8 | it "display empty list" do 9 | get "index" 10 | 11 | expect(response.status).to eq(200) 12 | expect(response.body).to match(/Open VimGolf challenges/) 13 | expect(assigns[:stats][:users]).to eq(0) 14 | expect(assigns[:stats][:challenges]).to eq(0) 15 | expect(assigns[:stats][:entries]).to eq(0) 16 | expect(assigns[:challenges].to_a.size).to eq(0) 17 | end 18 | end 19 | 20 | context "With > 50 challenges 200 users 200 entries" do 21 | before do 22 | 10.times do 23 | create(:user) 24 | end 25 | users = User.all 26 | 27 | 51.times do 28 | challenge = create(:challenge, user: users.sample) 29 | create(:entry, challenge: challenge, user: users.sample) 30 | create(:entry, challenge: challenge, user: users.sample) 31 | end 32 | end 33 | 34 | it "display page, prepare stats, display pagination and limit to 50" do 35 | get "index" 36 | 37 | expect(response.status).to eq(200) 38 | expect(response.body).to match(/Open VimGolf challenges/) 39 | 40 | expect(assigns[:stats][:users]).to eq(10) 41 | expect(assigns[:stats][:challenges]).to eq(51) 42 | expect(assigns[:stats][:entries]).to eq(102) 43 | expect(response.body).to match(/